gitforest 0.1.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +24 -4
  3. package/src/components/onboarding/DirectoriesStep.tsx +19 -19
  4. package/src/github/auth.ts +3 -3
  5. package/src/utils/debug.ts +4 -4
  6. package/.bunignore +0 -7
  7. package/.github/workflows/ci.yml +0 -73
  8. package/CLAUDE.md +0 -111
  9. package/CONTRIBUTING.md +0 -145
  10. package/bun.lock +0 -267
  11. package/bunfig.toml +0 -15
  12. package/cli +0 -0
  13. package/docs/ai/IMPROVEMENT_PLAN.md +0 -341
  14. package/docs/ai/VERIFICATION_REPORT.md +0 -87
  15. package/docs/ai/architecture.md +0 -169
  16. package/docs/ai/checks/check-2025-12-02-tests.md +0 -40
  17. package/docs/ai/checks/check-2025-12-02.md +0 -55
  18. package/docs/ai/checks/test-verification-report.md +0 -85
  19. package/docs/ai/implementation-guide.md +0 -776
  20. package/docs/ai/research/gitty-codebase-analysis.md +0 -221
  21. package/docs/ai/tickets/GENERAL-sitrep.md +0 -30
  22. package/docs/ai/tickets/TASK-database-tests-sitrep.md +0 -25
  23. package/docs/ai/tickets/TASK-deprecated-functions-sitrep.md +0 -28
  24. package/docs/ai/tickets/TASK-detail-modal-sitrep.md +0 -28
  25. package/docs/ai/tickets/TASK-filter-overlay-sitrep.md +0 -24
  26. package/docs/ai/tickets/TASK-github-service-sitrep.md +0 -32
  27. package/docs/ai/tickets/TASK-github-token-sitrep.md +0 -51
  28. package/docs/ai/tickets/TASK-hascommits-sitrep.md +0 -35
  29. package/docs/ai/tickets/TASK-keybindings-sitrep.md +0 -26
  30. package/docs/ai/tickets/TASK-layout-sitrep.md +0 -25
  31. package/docs/ai/tickets/TASK-markdown-sitrep.md +0 -28
  32. package/docs/ai/tickets/TASK-project-item-sitrep.md +0 -79
  33. package/docs/ai/tickets/TASK-sitrep.md +0 -28
  34. package/docs/ai/tickets/TASK-state-sitrep.md +0 -26
  35. package/docs/ai/tickets/TASK-types-sitrep.md +0 -25
  36. package/docs/ai/tickets/TASK-unified-item-fix-sitrep.md +0 -26
  37. package/docs/ai/tickets/TKT-001-sitrep.md +0 -24
  38. package/docs/ai/tickets/TKT-002-sitrep.md +0 -25
  39. package/docs/ai/tickets/TKT-003-git-service-refactoring-complete.md +0 -46
  40. package/docs/ai/tickets/TKT-003-git-service-refactoring-plan.md +0 -135
  41. package/docs/ai/tickets/TKT-003-sitrep.md +0 -26
  42. package/docs/ai/tickets/TKT-004-sitrep.md +0 -27
  43. package/docs/ai/tickets/TKT-005-sitrep.md +0 -25
  44. package/docs/ai/tickets/TKT-006-sitrep.md +0 -26
  45. package/docs/ai/tickets/TKT-007-sitrep.md +0 -30
  46. package/docs/ai/tickets/TKT-008-sitrep.md +0 -32
  47. package/docs/ai/tickets/TKT-009-sitrep.md +0 -27
  48. package/docs/ai/tickets/TKT-010-sitrep.md +0 -27
  49. package/docs/ai/tickets/TKT-011-sitrep.md +0 -26
  50. package/docs/ai/tickets/TKT-012-sitrep.md +0 -25
  51. package/docs/ai/tickets/sitreps/TASK-actions-sitrep.md +0 -28
  52. package/docs/ai/tickets/sitreps/TASK-actions-test-sitrep.md +0 -25
  53. package/docs/ai/tickets/sitreps/TASK-app-integration-sitrep.md +0 -25
  54. package/docs/ai/tickets/sitreps/TASK-background-fetch-sitrep.md +0 -24
  55. package/docs/ai/tickets/sitreps/TASK-background-fetch-test-sitrep.md +0 -29
  56. package/docs/ai/tickets/sitreps/TASK-batch-tests-sitrep.md +0 -29
  57. package/docs/ai/tickets/sitreps/TASK-bun-test-sitrep.md +0 -26
  58. package/docs/ai/tickets/sitreps/TASK-cache-tests-sitrep.md +0 -30
  59. package/docs/ai/tickets/sitreps/TASK-cli-tests-sitrep.md +0 -28
  60. package/docs/ai/tickets/sitreps/TASK-clone-error-handling-sitrep.md +0 -26
  61. package/docs/ai/tickets/sitreps/TASK-commands-tests-sitrep.md +0 -25
  62. package/docs/ai/tickets/sitreps/TASK-component-tests-1-sitrep.md +0 -30
  63. package/docs/ai/tickets/sitreps/TASK-configloader-tests-sitrep.md +0 -25
  64. package/docs/ai/tickets/sitreps/TASK-confirm-dialog-test-sitrep.md +0 -29
  65. package/docs/ai/tickets/sitreps/TASK-coverage-sitrep.md +0 -95
  66. package/docs/ai/tickets/sitreps/TASK-database-tests-summary.md +0 -61
  67. package/docs/ai/tickets/sitreps/TASK-error-boundary-sitrep.md +0 -30
  68. package/docs/ai/tickets/sitreps/TASK-error-tests-sitrep.md +0 -27
  69. package/docs/ai/tickets/sitreps/TASK-errors-tests-sitrep.md +0 -25
  70. package/docs/ai/tickets/sitreps/TASK-extract-reducer-sitrep.md +0 -27
  71. package/docs/ai/tickets/sitreps/TASK-filter-overlay-test-sitrep.md +0 -25
  72. package/docs/ai/tickets/sitreps/TASK-final-verification-sitrep.md +0 -28
  73. package/docs/ai/tickets/sitreps/TASK-fix-all-tests-sitrep.md +0 -25
  74. package/docs/ai/tickets/sitreps/TASK-fix-hooks-sitrep.md +0 -26
  75. package/docs/ai/tickets/sitreps/TASK-fix-remaining-tests-sitrep.md +0 -25
  76. package/docs/ai/tickets/sitreps/TASK-fix-test-failures-sitrep.md +0 -26
  77. package/docs/ai/tickets/sitreps/TASK-fix-tests-sitrep.md +0 -24
  78. package/docs/ai/tickets/sitreps/TASK-formatters-tests-sitrep.md +0 -25
  79. package/docs/ai/tickets/sitreps/TASK-git-timeouts-sitrep.md +0 -29
  80. package/docs/ai/tickets/sitreps/TASK-github-cache-test-sitrep.md +0 -25
  81. package/docs/ai/tickets/sitreps/TASK-githubcli-tests-sitrep.md +0 -24
  82. package/docs/ai/tickets/sitreps/TASK-gitstatus-tests-sitrep.md +0 -24
  83. package/docs/ai/tickets/sitreps/TASK-hooks-isolation-sitrep.md +0 -27
  84. package/docs/ai/tickets/sitreps/TASK-keybindings-tests-sitrep.md +0 -25
  85. package/docs/ai/tickets/sitreps/TASK-layout-tests-sitrep.md +0 -25
  86. package/docs/ai/tickets/sitreps/TASK-mock-factories-sitrep.md +0 -27
  87. package/docs/ai/tickets/sitreps/TASK-modal-tests-sitrep.md +0 -32
  88. package/docs/ai/tickets/sitreps/TASK-processbatch-fix-sitrep.md +0 -27
  89. package/docs/ai/tickets/sitreps/TASK-projectlist-tests-sitrep.md +0 -30
  90. package/docs/ai/tickets/sitreps/TASK-projectutils-tests-sitrep.md +0 -25
  91. package/docs/ai/tickets/sitreps/TASK-scanner-tests-sitrep.md +0 -29
  92. package/docs/ai/tickets/sitreps/TASK-select-all-sitrep.md +0 -25
  93. package/docs/ai/tickets/sitreps/TASK-shell-error-handling-sitrep.md +0 -27
  94. package/docs/ai/tickets/sitreps/TASK-store-tests-sitrep.md +0 -25
  95. package/docs/ai/tickets/sitreps/TASK-test-fixes-sitrep.md +0 -26
  96. package/docs/ai/tickets/sitreps/TASK-test-summary-sitrep.md +0 -25
  97. package/docs/ai/tickets/sitreps/TASK-test-verification-sitrep.md +0 -27
  98. package/docs/ai/tickets/sitreps/TASK-testsuite-sitrep.md +0 -75
  99. package/docs/ai/tickets/sitreps/TASK-unified-reducer-tests-sitrep.md +0 -29
  100. package/docs/ai/tickets/sitreps/TASK-unified-repos-test-sitrep.md +0 -29
  101. package/docs/ai/tickets/sitreps/TASK-unified-tests-sitrep.md +0 -25
  102. package/docs/ai/tickets/sitreps/TASK-useprojects-tests-sitrep.md +0 -25
  103. package/docs/ai/tickets/sitreps/TASK-utility-tests-sitrep.md +0 -32
  104. package/docs/ai/tickets/sitreps/TKT-003-git-service-refactoring-sitrep.md +0 -64
  105. package/docs/ai/tkt-001-fix-database-error.md +0 -217
  106. package/docs/ai/ui-enhancement-plan.md +0 -562
  107. package/test/integration/app.isolated.tsx +0 -240
  108. package/test/integration/cli-commands.test.ts +0 -287
  109. package/test/integration/cli-validation.test.ts +0 -264
  110. package/test/integration/git-operations.test.ts +0 -218
  111. package/test/integration/scanner.test.ts +0 -228
  112. package/test/preload.ts +0 -18
  113. package/test/unit/cli/commands.test.ts +0 -13
  114. package/test/unit/cli/formatters.test.ts +0 -1116
  115. package/test/unit/cli/github-commands.test.ts +0 -12
  116. package/test/unit/components/CloneDialog.test.tsx +0 -240
  117. package/test/unit/components/ColumnHeader.test.tsx +0 -128
  118. package/test/unit/components/CommandPalette.test.tsx +0 -355
  119. package/test/unit/components/ConfirmDialog.test.tsx +0 -111
  120. package/test/unit/components/ErrorBoundary.test.tsx +0 -139
  121. package/test/unit/components/FilterBar.test.tsx +0 -43
  122. package/test/unit/components/FilterOptionsOverlay.test.tsx +0 -197
  123. package/test/unit/components/HelpOverlay.test.tsx +0 -90
  124. package/test/unit/components/Layout.test.tsx +0 -328
  125. package/test/unit/components/MarkdownRenderer.test.tsx +0 -45
  126. package/test/unit/components/ProgressBar.test.tsx +0 -138
  127. package/test/unit/components/ProjectItem.test.tsx +0 -182
  128. package/test/unit/components/ProjectList.test.tsx +0 -311
  129. package/test/unit/components/RepoDetailModal.test.tsx +0 -445
  130. package/test/unit/components/StatusBar.test.tsx +0 -112
  131. package/test/unit/components/UnifiedProjectItem.test.tsx +0 -618
  132. package/test/unit/components/ViewModeIndicator.test.tsx +0 -137
  133. package/test/unit/components/test-utils.tsx +0 -63
  134. package/test/unit/config/loader.test.ts +0 -692
  135. package/test/unit/db/database.test.ts +0 -978
  136. package/test/unit/db/index.test.ts +0 -314
  137. package/test/unit/fixtures/setup.ts +0 -186
  138. package/test/unit/git/commands-untested.test.ts +0 -205
  139. package/test/unit/git/commands.test.ts +0 -269
  140. package/test/unit/git/operations.test.ts +0 -322
  141. package/test/unit/git/status.test.ts +0 -219
  142. package/test/unit/github/auth.test.ts +0 -317
  143. package/test/unit/github/cache.test.ts +0 -1028
  144. package/test/unit/github/cli.test.ts +0 -135
  145. package/test/unit/github/unified.test.ts +0 -1201
  146. package/test/unit/graceful-shutdown.test.ts +0 -83
  147. package/test/unit/hooks/useBackgroundFetch.test.tsx +0 -239
  148. package/test/unit/hooks/useConfirmDialogActions.test.tsx +0 -81
  149. package/test/unit/hooks/useKeyBindings.isolated.ts +0 -715
  150. package/test/unit/hooks/useProjects.test.tsx +0 -186
  151. package/test/unit/hooks/useUnifiedRepos-simple.test.tsx +0 -115
  152. package/test/unit/hooks/useUnifiedRepos.test.tsx +0 -177
  153. package/test/unit/mocks/config.ts +0 -109
  154. package/test/unit/mocks/git-service.ts +0 -274
  155. package/test/unit/mocks/github-service.ts +0 -250
  156. package/test/unit/mocks/index.ts +0 -72
  157. package/test/unit/mocks/project.ts +0 -148
  158. package/test/unit/mocks/state-mocks.ts +0 -187
  159. package/test/unit/mocks/unified.ts +0 -169
  160. package/test/unit/operations/batch.test.ts +0 -216
  161. package/test/unit/operations/commands.test.ts +0 -550
  162. package/test/unit/scanner/errors.test.ts +0 -297
  163. package/test/unit/scanner/index.test.ts +0 -1011
  164. package/test/unit/scanner/markers.test.ts +0 -150
  165. package/test/unit/scanner/submodules.test.ts +0 -99
  166. package/test/unit/services/git-errors.test.ts +0 -190
  167. package/test/unit/services/git.test.ts +0 -442
  168. package/test/unit/services/github-errors.test.ts +0 -293
  169. package/test/unit/services/github.test.ts +0 -200
  170. package/test/unit/state/actions.test.ts +0 -217
  171. package/test/unit/state/reducer.test.ts +0 -745
  172. package/test/unit/state/store.test.tsx +0 -711
  173. package/test/unit/types/commands.test.ts +0 -220
  174. package/test/unit/types/schema.test.ts +0 -179
  175. package/test/unit/utils/array.test.ts +0 -73
  176. package/test/unit/utils/debug.test.ts +0 -23
  177. package/test/unit/utils/errors.test.ts +0 -295
  178. package/test/unit/utils/markdown.test.ts +0 -163
  179. package/test/unit/utils/project-utils.test.ts +0 -756
  180. package/test/unit/utils/rate-limiter.test.ts +0 -256
  181. package/test/unit/utils/retry.test.ts +0 -165
  182. package/test/unit/utils/strip-ansi.ts +0 -13
  183. package/test/unit/utils/timeout.test.ts +0 -93
  184. package/tsconfig.json +0 -29
package/bun.lock DELETED
@@ -1,267 +0,0 @@
1
- {
2
- "lockfileVersion": 1,
3
- "configVersion": 1,
4
- "workspaces": {
5
- "": {
6
- "name": "gitty",
7
- "dependencies": {
8
- "@inkjs/ui": "^2.0.0",
9
- "chalk": "^5.3.0",
10
- "drizzle-orm": "^0.36.4",
11
- "ink": "^5.0.1",
12
- "ink-select-input": "^6.0.0",
13
- "react": "^18.3.1",
14
- "yaml": "^2.6.1",
15
- "zod": "^3.23.8",
16
- },
17
- "devDependencies": {
18
- "@types/bun": "latest",
19
- "@types/react": "^18.3.12",
20
- "drizzle-kit": "^0.28.1",
21
- "ink-testing-library": "^4.0.0",
22
- },
23
- "peerDependencies": {
24
- "typescript": "^5",
25
- },
26
- },
27
- },
28
- "packages": {
29
- "@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.1.3", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-3yWxPTq3UQ/FY9p1ErPxIyfT64elWaMvM9lIHnaqpyft63tkxodF5aUElYHrdisWve5cETkh1+KBw1yJuW0aRw=="],
30
-
31
- "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
32
-
33
- "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
34
-
35
- "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
36
-
37
- "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="],
38
-
39
- "@esbuild/android-arm": ["@esbuild/android-arm@0.19.12", "", { "os": "android", "cpu": "arm" }, "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w=="],
40
-
41
- "@esbuild/android-arm64": ["@esbuild/android-arm64@0.19.12", "", { "os": "android", "cpu": "arm64" }, "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA=="],
42
-
43
- "@esbuild/android-x64": ["@esbuild/android-x64@0.19.12", "", { "os": "android", "cpu": "x64" }, "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew=="],
44
-
45
- "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.19.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g=="],
46
-
47
- "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.19.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A=="],
48
-
49
- "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.19.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA=="],
50
-
51
- "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.19.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg=="],
52
-
53
- "@esbuild/linux-arm": ["@esbuild/linux-arm@0.19.12", "", { "os": "linux", "cpu": "arm" }, "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w=="],
54
-
55
- "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.19.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA=="],
56
-
57
- "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.19.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA=="],
58
-
59
- "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA=="],
60
-
61
- "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w=="],
62
-
63
- "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.19.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg=="],
64
-
65
- "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg=="],
66
-
67
- "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.19.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg=="],
68
-
69
- "@esbuild/linux-x64": ["@esbuild/linux-x64@0.19.12", "", { "os": "linux", "cpu": "x64" }, "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg=="],
70
-
71
- "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.19.12", "", { "os": "none", "cpu": "x64" }, "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA=="],
72
-
73
- "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.19.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw=="],
74
-
75
- "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.19.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA=="],
76
-
77
- "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.19.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A=="],
78
-
79
- "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.19.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ=="],
80
-
81
- "@esbuild/win32-x64": ["@esbuild/win32-x64@0.19.12", "", { "os": "win32", "cpu": "x64" }, "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA=="],
82
-
83
- "@inkjs/ui": ["@inkjs/ui@2.0.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-spinners": "^3.0.0", "deepmerge": "^4.3.1", "figures": "^6.1.0" }, "peerDependencies": { "ink": ">=5" } }, "sha512-5+8fJmwtF9UvikzLfph9sA+LS+l37Ij/szQltkuXLOAXwNkBX9innfzh4pLGXIB59vKEQUtc6D4qGvhD7h3pAg=="],
84
-
85
- "@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="],
86
-
87
- "@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
88
-
89
- "@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="],
90
-
91
- "@types/react": ["@types/react@18.3.27", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" } }, "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w=="],
92
-
93
- "ansi-escapes": ["ansi-escapes@7.2.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw=="],
94
-
95
- "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
96
-
97
- "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
98
-
99
- "auto-bind": ["auto-bind@5.0.1", "", {}, "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg=="],
100
-
101
- "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
102
-
103
- "bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="],
104
-
105
- "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
106
-
107
- "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
108
-
109
- "cli-cursor": ["cli-cursor@4.0.0", "", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="],
110
-
111
- "cli-spinners": ["cli-spinners@3.3.0", "", {}, "sha512-/+40ljC3ONVnYIttjMWrlL51nItDAbBrq2upN8BPyvGU/2n5Oxw3tbNwORCaNuNqLJnxGqOfjUuhsv7l5Q4IsQ=="],
112
-
113
- "cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="],
114
-
115
- "code-excerpt": ["code-excerpt@4.0.0", "", { "dependencies": { "convert-to-spaces": "^2.0.1" } }, "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA=="],
116
-
117
- "convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
118
-
119
- "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
120
-
121
- "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
122
-
123
- "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
124
-
125
- "drizzle-kit": ["drizzle-kit@0.28.1", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-JimOV+ystXTWMgZkLHYHf2w3oS28hxiH1FR0dkmJLc7GHzdGJoJAQtQS5DRppnabsRZwE2U1F6CuezVBgmsBBQ=="],
126
-
127
- "drizzle-orm": ["drizzle-orm@0.36.4", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=3", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/react": ">=18", "@types/sql.js": "*", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "react": ">=18", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/react", "@types/sql.js", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "knex", "kysely", "mysql2", "pg", "postgres", "react", "sql.js", "sqlite3"] }, "sha512-1OZY3PXD7BR00Gl61UUOFihslDldfH4NFRH2MbP54Yxi0G/PKn4HfO65JYZ7c16DeP3SpM3Aw+VXVG9j6CRSXA=="],
128
-
129
- "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
130
-
131
- "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
132
-
133
- "es-toolkit": ["es-toolkit@1.42.0", "", {}, "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA=="],
134
-
135
- "esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="],
136
-
137
- "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
138
-
139
- "escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
140
-
141
- "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
142
-
143
- "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
144
-
145
- "get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
146
-
147
- "indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="],
148
-
149
- "ink": ["ink@5.2.1", "", { "dependencies": { "@alcalzone/ansi-tokenize": "^0.1.3", "ansi-escapes": "^7.0.0", "ansi-styles": "^6.2.1", "auto-bind": "^5.0.1", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "cli-cursor": "^4.0.0", "cli-truncate": "^4.0.0", "code-excerpt": "^4.0.0", "es-toolkit": "^1.22.0", "indent-string": "^5.0.0", "is-in-ci": "^1.0.0", "patch-console": "^2.0.0", "react-reconciler": "^0.29.0", "scheduler": "^0.23.0", "signal-exit": "^3.0.7", "slice-ansi": "^7.1.0", "stack-utils": "^2.0.6", "string-width": "^7.2.0", "type-fest": "^4.27.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0", "ws": "^8.18.0", "yoga-layout": "~3.2.1" }, "peerDependencies": { "@types/react": ">=18.0.0", "react": ">=18.0.0", "react-devtools-core": "^4.19.1" }, "optionalPeers": ["@types/react", "react-devtools-core"] }, "sha512-BqcUyWrG9zq5HIwW6JcfFHsIYebJkWWb4fczNah1goUO0vv5vneIlfwuS85twyJ5hYR/y18FlAYUxrO9ChIWVg=="],
150
-
151
- "ink-select-input": ["ink-select-input@6.2.0", "", { "dependencies": { "figures": "^6.1.0", "to-rotated": "^1.0.0" }, "peerDependencies": { "ink": ">=5.0.0", "react": ">=18.0.0" } }, "sha512-304fZXxkpYxJ9si5lxRCaX01GNlmPBgOZumXXRnPYbHW/iI31cgQynqk2tRypGLOF1cMIwPUzL2LSm6q4I5rQQ=="],
152
-
153
- "ink-testing-library": ["ink-testing-library@4.0.0", "", { "peerDependencies": { "@types/react": ">=18.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-yF92kj3pmBvk7oKbSq5vEALO//o7Z9Ck/OaLNlkzXNeYdwfpxMQkSowGTFUCS5MSu9bWfSZMewGpp7bFc66D7Q=="],
154
-
155
- "is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="],
156
-
157
- "is-in-ci": ["is-in-ci@1.0.0", "", { "bin": { "is-in-ci": "cli.js" } }, "sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg=="],
158
-
159
- "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
160
-
161
- "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
162
-
163
- "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
164
-
165
- "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
166
-
167
- "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
168
-
169
- "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
170
-
171
- "patch-console": ["patch-console@2.0.0", "", {}, "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA=="],
172
-
173
- "react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="],
174
-
175
- "react-reconciler": ["react-reconciler@0.29.2", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg=="],
176
-
177
- "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
178
-
179
- "restore-cursor": ["restore-cursor@4.0.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="],
180
-
181
- "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
182
-
183
- "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
184
-
185
- "slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
186
-
187
- "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
188
-
189
- "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
190
-
191
- "stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
192
-
193
- "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
194
-
195
- "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
196
-
197
- "to-rotated": ["to-rotated@1.0.0", "", {}, "sha512-KsEID8AfgUy+pxVRLsWp0VzCa69wxzUDZnzGbyIST/bcgcrMvTYoFBX/QORH4YApoD89EDuUovx4BTdpOn319Q=="],
198
-
199
- "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
200
-
201
- "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
202
-
203
- "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
204
-
205
- "widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="],
206
-
207
- "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
208
-
209
- "ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
210
-
211
- "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="],
212
-
213
- "yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="],
214
-
215
- "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
216
-
217
- "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
218
-
219
- "cli-truncate/slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="],
220
-
221
- "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
222
-
223
- "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
224
-
225
- "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
226
-
227
- "@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
228
-
229
- "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
230
-
231
- "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
232
-
233
- "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
234
-
235
- "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
236
-
237
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
238
-
239
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
240
-
241
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
242
-
243
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
244
-
245
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
246
-
247
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
248
-
249
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
250
-
251
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
252
-
253
- "@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
254
-
255
- "@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
256
-
257
- "@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
258
-
259
- "@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
260
-
261
- "@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
262
-
263
- "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
264
-
265
- "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
266
- }
267
- }
package/bunfig.toml DELETED
@@ -1,15 +0,0 @@
1
- [test]
2
- preload = ["./test/preload.ts"]
3
-
4
- # Test discovery automatically finds .test.ts/.test.tsx files
5
- # Files named .test.isolated.ts/.tsx are excluded by pattern but can be run directly
6
- #
7
- # To run ALL tests: ./run-all-tests.sh
8
- # To run main tests only: bun test
9
- #
10
- # Why isolated tests exist:
11
- # 2 test files mock 'ink' using mock.module() which leaks between test files
12
- # due to a known Bun limitation: https://github.com/oven-sh/bun/issues/12823
13
- # These must run in separate processes:
14
- # - test/hooks/useKeyBindings.test.isolated.ts
15
- # - test-integration/app.test.isolated.tsx
package/cli DELETED
Binary file
@@ -1,341 +0,0 @@
1
- # Gitforest Codebase Improvement Plan
2
-
3
- ## Overview
4
- This document outlines a comprehensive plan to improve the gitforest codebase based on the evaluation findings. The plan is organized by priority with detailed implementation steps for each improvement.
5
-
6
- ## Implementation Plan
7
-
8
- ### 🔴 High Priority (Critical Issues)
9
-
10
- #### TKT-001: Fix Database Error in clearCache
11
- **Issue:** Missing `await` in database operations
12
- **Location:** `src/db/index.ts:97-101`
13
- **Implementation:**
14
- 1. Add `await` to both delete operations
15
- 2. Consider using batch operations for better performance
16
-
17
- #### TKT-002: Implement Graceful Shutdown
18
- **Issue:** No cleanup on process termination
19
- **Location:** `index.tsx:329-344`
20
- **Implementation:**
21
- 1. Add signal handlers for SIGINT and SIGTERM
22
- 2. Ensure database connections are properly closed
23
- 3. Clean up any background processes
24
-
25
- #### TKT-003: Remove Deprecated Functions
26
- **Issue:** Deprecated functions still in use
27
- **Location:** `src/git/operations.ts` and `src/hooks/useKeyBindings.ts`
28
- **Implementation:**
29
- 1. Check if `operations/batch.ts` has equivalent functions
30
- 2. Migrate calls from deprecated functions
31
- 3. Remove deprecated functions or @deprecated tags
32
-
33
- #### TKT-012: Add GitHub Token Security
34
- **Issue:** No validation of GitHub token format or permissions
35
- **Location:** `src/services/github.ts`
36
- **Implementation:**
37
- 1. Add token format validation
38
- 2. Add warning for excessive permissions
39
- 3. Consider secure credential storage
40
-
41
- ### 🟡 Medium Priority (Reliability & Performance)
42
-
43
- #### TKT-004: Add GitHub API Retry Logic
44
- **Issue:** No retry on transient failures
45
- **Location:** `src/services/github.ts`
46
- **Implementation:**
47
- 1. Create retry utility function
48
- 2. Implement exponential backoff
49
- 3. Add retry for 429 (rate limit) and 5xx errors
50
-
51
- #### TKT-005: Convert Sync to Async File Operations
52
- **Issue:** Blocking file system operations
53
- **Location:** `src/scanner/index.ts`
54
- **Implementation:**
55
- 1. Replace `readdirSync` with `readdir` from fs/promises
56
- 2. Replace `statSync` with `stat` from fs/promises
57
- 3. Update scanDirectory function to be async
58
-
59
- #### TKT-006: Add Rate Limiting for Batch Operations
60
- **Issue:** All operations fire at once
61
- **Location:** `src/git/operations.ts`
62
- **Implementation:**
63
- 1. Create Semaphore utility
64
- 2. Limit concurrent operations
65
- 3. Make limit configurable
66
-
67
- #### TKT-009: Improve Test Coverage
68
- **Issue:** Missing tests for critical paths
69
- **Location:** Multiple files
70
- **Implementation:**
71
- 1. Add tests for useKeyBindings hook
72
- 2. Add tests for ConfirmDialog component
73
- 3. Add error scenario tests
74
- 4. Add integration tests for keyboard flows
75
-
76
- #### TKT-010: Add CLI Input Validation
77
- **Issue:** No validation for CLI arguments
78
- **Location:** `index.tsx:127-174`
79
- **Implementation:**
80
- 1. Add validation for unknown flags
81
- 2. Add better error messages
82
- 3. Consider using CLI parsing library
83
-
84
- ### 🟢 Low Priority (Maintainability)
85
-
86
- #### TKT-007: Extract Magic Numbers
87
- **Issue:** Hardcoded values scattered throughout
88
- **Location:** Multiple files
89
- **Implementation:**
90
- 1. Create constants file
91
- 2. Extract UI constants (header height, etc.)
92
- 3. Extract API constants (page size, etc.)
93
-
94
- #### TKT-008: Add JSDoc Documentation
95
- **Issue:** Missing documentation on public APIs
96
- **Location:** All public functions
97
- **Implementation:**
98
- 1. Add JSDoc to exported functions
99
- 2. Document parameters and return types
100
- 3. Add usage examples where helpful
101
-
102
- #### TKT-011: Create Documentation
103
- **Issue:** Missing contributor documentation
104
- **Implementation:**
105
- 1. Create CONTRIBUTING.md
106
- 2. Create architecture documentation
107
- 3. Document development setup
108
-
109
- ## Implementation Order
110
-
111
- ### Phase 1: Critical Fixes (Week 1)
112
- 1. TKT-001: Fix database error
113
- 2. TKT-002: Add graceful shutdown
114
- 3. TKT-012: Add token security
115
-
116
- ### Phase 2: Core Reliability (Week 2)
117
- 1. TKT-003: Remove deprecated functions
118
- 2. TKT-004: Add API retry logic
119
- 3. TKT-005: Convert to async operations
120
-
121
- ### Phase 3: Performance & Testing (Week 3)
122
- 1. TKT-006: Add rate limiting
123
- 2. TKT-009: Improve test coverage
124
- 3. TKT-010: Add input validation
125
-
126
- ### Phase 4: Documentation & Polish (Week 4)
127
- 1. TKT-007: Extract constants
128
- 2. TKT-008: Add JSDoc
129
- 3. TKT-011: Create documentation
130
-
131
- ## Detailed Implementation Steps
132
-
133
- ### TKT-001: Fix Database Error
134
- ```typescript
135
- // src/db/index.ts
136
- export async function clearCache(): Promise<void> {
137
- const database = await initDb();
138
- await database.delete(schema.projects).all(); // Add await
139
- await database.delete(schema.remoteStatus).all(); // Add await
140
- }
141
- ```
142
-
143
- ### TKT-002: Add Graceful Shutdown
144
- ```typescript
145
- // index.tsx
146
- async function main() {
147
- // ... existing code ...
148
-
149
- // Add signal handlers
150
- process.on('SIGINT', gracefulShutdown);
151
- process.on('SIGTERM', gracefulShutdown);
152
-
153
- // ... rest of main function ...
154
- }
155
-
156
- async function gracefulShutdown() {
157
- console.log('\nShutting down gracefully...');
158
- try {
159
- closeDb();
160
- process.exit(0);
161
- } catch (error) {
162
- console.error('Error during shutdown:', error);
163
- process.exit(1);
164
- }
165
- }
166
- ```
167
-
168
- ### TKT-003: Remove Deprecated Functions
169
- 1. Check if batch operations in `operations/batch.ts` exist
170
- 2. If yes, migrate calls in `useKeyBindings.ts`
171
- 3. If no, remove @deprecated tags
172
-
173
- ### TKT-004: Add Retry Logic
174
- ```typescript
175
- // src/utils/retry.ts
176
- export async function withRetry<T>(
177
- fn: () => Promise<T>,
178
- options: {
179
- retries?: number;
180
- delay?: number;
181
- backoff?: number;
182
- shouldRetry?: (error: Error) => boolean;
183
- } = {}
184
- ): Promise<T> {
185
- const { retries = 3, delay = 1000, backoff = 2, shouldRetry } = options;
186
-
187
- let lastError: Error;
188
-
189
- for (let i = 0; i <= retries; i++) {
190
- try {
191
- return await fn();
192
- } catch (error) {
193
- lastError = error as Error;
194
-
195
- if (i === retries) break;
196
- if (shouldRetry && !shouldRetry(lastError)) break;
197
-
198
- const waitTime = delay * Math.pow(backoff, i);
199
- await new Promise(resolve => setTimeout(resolve, waitTime));
200
- }
201
- }
202
-
203
- throw lastError;
204
- }
205
- ```
206
-
207
- ### TKT-005: Convert to Async Operations
208
- ```typescript
209
- // src/scanner/index.ts
210
- import { readdir, stat } from 'fs/promises';
211
-
212
- async function scanDirectory(
213
- dirPath: string,
214
- config: GitforestConfig,
215
- depth: number,
216
- maxDepth: number,
217
- foundProjects: Project[],
218
- processedPaths: Set<string>
219
- ): Promise<void> {
220
- // ... existing validation ...
221
-
222
- try {
223
- const entries = await readdir(dirPath); // Async
224
-
225
- for (const entry of entries) {
226
- if (shouldIgnore(entry, config.scan.ignore, config.scan.includeHidden)) {
227
- continue;
228
- }
229
-
230
- const entryPath = join(dirPath, entry);
231
-
232
- try {
233
- const entryStat = await stat(entryPath); // Async
234
- if (entryStat.isDirectory()) {
235
- await scanDirectory(
236
- entryPath,
237
- config,
238
- depth + 1,
239
- maxDepth,
240
- foundProjects,
241
- processedPaths
242
- );
243
- }
244
- } catch {
245
- // Skip entries we can't stat
246
- }
247
- }
248
- } catch {
249
- // Skip directories we can't read
250
- }
251
- }
252
- ```
253
-
254
- ### TKT-006: Add Rate Limiting
255
- ```typescript
256
- // src/utils/semaphore.ts
257
- export class Semaphore {
258
- private permits: number;
259
- private waiting: Array<() => void> = [];
260
-
261
- constructor(permits: number) {
262
- this.permits = permits;
263
- }
264
-
265
- async acquire(): Promise<void> {
266
- if (this.permits > 0) {
267
- this.permits--;
268
- return;
269
- }
270
-
271
- return new Promise<void>(resolve => {
272
- this.waiting.push(resolve);
273
- });
274
- }
275
-
276
- release(): void {
277
- this.permits++;
278
-
279
- if (this.waiting.length > 0) {
280
- const next = this.waiting.shift();
281
- if (next) {
282
- this.permits--;
283
- next();
284
- }
285
- }
286
- }
287
- }
288
-
289
- // Usage in git/operations.ts
290
- const semaphore = new Semaphore(5); // Max 5 concurrent operations
291
-
292
- export async function batchOperation<T>(
293
- items: T[],
294
- operation: (item: T) => Promise<any>,
295
- concurrency = 5
296
- ): Promise<any[]> {
297
- const sem = new Semaphore(concurrency);
298
- const promises = items.map(async item => {
299
- await sem.acquire();
300
- try {
301
- return await operation(item);
302
- } finally {
303
- sem.release();
304
- }
305
- });
306
-
307
- return Promise.all(promises);
308
- }
309
- ```
310
-
311
- ## Success Criteria
312
-
313
- ### Phase 1 Success
314
- - All database operations properly awaited
315
- - Graceful shutdown implemented and tested
316
- - GitHub token validation added
317
- - No deprecated functions in use
318
-
319
- ### Phase 2 Success
320
- - GitHub API calls have retry logic
321
- - File operations are async
322
- - Performance improved (measure scan time)
323
- - Error rates reduced
324
-
325
- ### Phase 3 Success
326
- - Batch operations have rate limiting
327
- - Test coverage >80% for critical paths
328
- - CLI validation catches invalid inputs
329
- - No memory leaks detected
330
-
331
- ### Phase 4 Success
332
- - All magic numbers extracted to constants
333
- - Public APIs documented with JSDoc
334
- - Documentation complete and reviewed
335
-
336
- ## Notes
337
-
338
- - Each task should be implemented on a separate branch
339
- - Run tests after each change
340
- - Update this plan as tasks are completed
341
- - Consider user feedback for future improvements