@shepai/cli 1.124.0-pr403.3ad79ff → 1.124.0-pr404.6e2ed37
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.
- package/apis/json-schema/EnvironmentConfig.yaml +3 -0
- package/apis/json-schema/Repository.yaml +3 -0
- package/dist/packages/core/src/application/ports/output/repositories/repository-repository.interface.d.ts +4 -0
- package/dist/packages/core/src/application/ports/output/repositories/repository-repository.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.d.ts +118 -0
- package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.js +58 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts +2 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/index.js +1 -0
- package/dist/packages/core/src/application/use-cases/repositories/import-github-repository.use-case.d.ts +31 -0
- package/dist/packages/core/src/application/use-cases/repositories/import-github-repository.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/repositories/import-github-repository.use-case.js +86 -0
- package/dist/packages/core/src/application/use-cases/repositories/list-github-repositories.use-case.d.ts +13 -0
- package/dist/packages/core/src/application/use-cases/repositories/list-github-repositories.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/repositories/list-github-repositories.use-case.js +35 -0
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.d.ts.map +1 -1
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +1 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +8 -0
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +12 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.js +2 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/040-add-repository-remote-url.d.ts +12 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/040-add-repository-remote-url.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/040-add-repository-remote-url.js +29 -0
- package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.d.ts +3 -0
- package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.js +38 -2
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts +18 -0
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.js +171 -0
- package/dist/src/presentation/cli/commands/repo/add.command.d.ts +13 -0
- package/dist/src/presentation/cli/commands/repo/add.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/repo/add.command.js +82 -0
- package/dist/src/presentation/cli/commands/repo/index.d.ts +1 -0
- package/dist/src/presentation/cli/commands/repo/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/repo/index.js +4 -1
- package/dist/src/presentation/tui/wizards/github-import.wizard.d.ts +33 -0
- package/dist/src/presentation/tui/wizards/github-import.wizard.d.ts.map +1 -0
- package/dist/src/presentation/tui/wizards/github-import.wizard.js +121 -0
- package/dist/src/presentation/web/app/actions/import-github-repository.d.ts +11 -0
- package/dist/src/presentation/web/app/actions/import-github-repository.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/import-github-repository.js +27 -0
- package/dist/src/presentation/web/app/actions/list-github-repositories.d.ts +11 -0
- package/dist/src/presentation/web/app/actions/list-github-repositories.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/list-github-repositories.js +17 -0
- package/dist/src/presentation/web/components/common/add-repository-button/add-repository-button.d.ts +4 -3
- package/dist/src/presentation/web/components/common/add-repository-button/add-repository-button.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/add-repository-button/add-repository-button.js +20 -5
- package/dist/src/presentation/web/components/common/github-import-dialog/github-import-dialog.d.ts +8 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-import-dialog.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-import-dialog.js +33 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-import-dialog.stories.d.ts +10 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-import-dialog.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-import-dialog.stories.js +26 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.d.ts +15 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.js +52 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.stories.d.ts +10 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.stories.js +78 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-url-input.d.ts +7 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-url-input.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-url-input.js +46 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-url-input.stories.d.ts +10 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-url-input.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-url-input.stories.js +29 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/index.d.ts +4 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/index.js +3 -0
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.d.ts.map +1 -1
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +19 -3
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +74 -44
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +86 -56
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +86 -56
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +70 -40
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +74 -44
- package/web/.next/server/app/(dashboard)/create/page.js +2 -2
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +86 -56
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +2 -2
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +86 -56
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +2 -2
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +70 -40
- package/web/.next/server/app/(dashboard)/page.js +2 -2
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +70 -40
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +2 -2
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +32 -2
- package/web/.next/server/app/_not-found/page.js +1 -1
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +42 -12
- package/web/.next/server/app/settings/page.js +2 -2
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +42 -12
- package/web/.next/server/app/skills/page.js +2 -2
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +42 -12
- package/web/.next/server/app/tools/page.js +2 -2
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +32 -2
- package/web/.next/server/app/version/page.js +2 -2
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__dcd4f847._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_f37f9c0c._.js +3 -0
- package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_f37f9c0c._.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_1bb88051.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_1bb88051.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_b194b126.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_b194b126.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0fcd508b._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0fcd508b._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__14664e9b._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__14664e9b._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__ce6057f6._.js → [root-of-the-server]__2bc3b279._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__ce6057f6._.js.map → [root-of-the-server]__2bc3b279._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2f886f77._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2f886f77._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__71071a92._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__71071a92._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__9e8b25ad._.js → [root-of-the-server]__873eddba._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__7cbda1ea._.js.map → [root-of-the-server]__873eddba._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__7cbda1ea._.js → [root-of-the-server]__985330c0._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__aed1d6f8._.js.map → [root-of-the-server]__985330c0._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__6677a82c._.js → [root-of-the-server]__98f3918f._.js} +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__98f3918f._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__aed1d6f8._.js → [root-of-the-server]__bcc81726._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__9e8b25ad._.js.map → [root-of-the-server]__bcc81726._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d61bd462._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d61bd462._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_918887c5._.js → _0020fddd._.js} +2 -2
- package/web/.next/server/chunks/ssr/_0020fddd._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_2f6f48b8._.js → _02ec1aea._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_2f6f48b8._.js.map → _02ec1aea._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_0de326ae._.js +9 -0
- package/web/.next/server/chunks/ssr/_0de326ae._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_5120b8b8._.js +3 -0
- package/web/.next/server/chunks/ssr/_5120b8b8._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_67104d9e._.js +3 -0
- package/web/.next/server/chunks/ssr/_67104d9e._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_c519a1c7._.js +5 -0
- package/web/.next/server/chunks/ssr/_c519a1c7._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_580a1781._.js → _e6376080._.js} +2 -2
- package/web/.next/server/chunks/ssr/_e6376080._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_fc351f8f._.js +3 -0
- package/web/.next/server/chunks/ssr/_fc351f8f._.js.map +1 -0
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/node_modules__pnpm_1300ae39._.js +3 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_1300ae39._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_3574f9cb._.js +5 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_c4337169._.js.map → src_presentation_web_3574f9cb._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_013c03b8.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_013c03b8.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_ceb7886b._.js +5 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_5f039db1._.js.map → src_presentation_web_ceb7886b._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_a5e6c910._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_a5e6c910._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +482 -270
- package/web/.next/static/chunks/13f6da76b9b9f734.js +1 -0
- package/web/.next/static/chunks/314b8314f77d6921.js +1 -0
- package/web/.next/static/chunks/3a8374ee5ee9ce30.js +1 -0
- package/web/.next/static/chunks/3e1e0f9bde3530d2.js +1 -0
- package/web/.next/static/chunks/4aaca11c1a53b7c5.js +1 -0
- package/web/.next/static/chunks/554353f8433555fc.js +3 -0
- package/web/.next/static/chunks/601585ba5c04ded9.css +1 -0
- package/web/.next/static/chunks/656c38eae1ff907f.js +1 -0
- package/web/.next/static/chunks/688971d5bad5dc7c.js +1 -0
- package/web/.next/static/chunks/7005f1d6346c6a7a.js +11 -0
- package/web/.next/static/chunks/{e80fd818b2c6b13d.js → 7dbe4c13bcad0363.js} +2 -2
- package/web/.next/static/chunks/{c69ea4b27e353eba.js → 7ea9d2863244bd69.js} +1 -1
- package/web/.next/static/chunks/{79d97aa93fd1e121.js → 83fb25b394fb6ae5.js} +1 -1
- package/web/.next/static/chunks/885ac8fd15b3d732.js +1 -0
- package/web/.next/static/chunks/955e6c81d4eab26a.js +1 -0
- package/web/.next/static/chunks/{25001092d097ddb4.js → bd5058b5336bfc7a.js} +1 -1
- package/web/.next/static/chunks/f14591fcf2bb71b5.js +1 -0
- package/web/.next/static/chunks/fb890f2c8134c369.js +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js.map +0 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__56ecbe40._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__56ecbe40._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6677a82c._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__68c2d48e._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__68c2d48e._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_1bb79fe8._.js +0 -3
- package/web/.next/server/chunks/ssr/_1bb79fe8._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_580a1781._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_6985c922._.js +0 -3
- package/web/.next/server/chunks/ssr/_6985c922._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_6d26a08f._.js +0 -3
- package/web/.next/server/chunks/ssr/_6d26a08f._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_918887c5._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_9ac70f88._.js +0 -5
- package/web/.next/server/chunks/ssr/_9ac70f88._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_b56e7571._.js +0 -3
- package/web/.next/server/chunks/ssr/_b56e7571._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_e9703421._.js +0 -3
- package/web/.next/server/chunks/ssr/_e9703421._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_f1a649e3._.js +0 -9
- package/web/.next/server/chunks/ssr/_f1a649e3._.js.map +0 -1
- package/web/.next/server/chunks/ssr/node_modules__pnpm_bc66dcc6._.js +0 -3
- package/web/.next/server/chunks/ssr/node_modules__pnpm_bc66dcc6._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_0c0bf8cd._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_0c0bf8cd._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bdcfba35._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bdcfba35._.js.map +0 -1
- package/web/.next/static/chunks/0158bd913a9f8332.css +0 -1
- package/web/.next/static/chunks/01ba448cf76c6014.js +0 -1
- package/web/.next/static/chunks/22a9e0a854f004b4.js +0 -1
- package/web/.next/static/chunks/303a1217006489b9.js +0 -1
- package/web/.next/static/chunks/37ada233462bcaec.js +0 -11
- package/web/.next/static/chunks/4443ee9c7733399b.js +0 -1
- package/web/.next/static/chunks/52b56677c842e45f.js +0 -3
- package/web/.next/static/chunks/928630e95ee8880b.js +0 -1
- package/web/.next/static/chunks/c068a726224db05d.js +0 -1
- package/web/.next/static/chunks/cca0f5112a9260d8.js +0 -1
- package/web/.next/static/chunks/d378fd488e2ea128.js +0 -1
- package/web/.next/static/chunks/dbbb446493f21874.js +0 -1
- package/web/.next/static/chunks/ee776a212fb02c56.js +0 -1
- package/web/.next/static/chunks/f4e3b6092c7ab027.js +0 -1
- /package/web/.next/static/{JTTVp0Y9VKbOO74jiTEeD → MDctPfGHQTYz1gOHmRQQo}/_buildManifest.js +0 -0
- /package/web/.next/static/{JTTVp0Y9VKbOO74jiTEeD → MDctPfGHQTYz1gOHmRQQo}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{JTTVp0Y9VKbOO74jiTEeD → MDctPfGHQTYz1gOHmRQQo}/_ssgManifest.js +0 -0
package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.mapper.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"repository.mapper.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,CAc1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,CAU3D"}
|
package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/repository.mapper.js
CHANGED
|
@@ -15,6 +15,7 @@ export function toDatabase(repo) {
|
|
|
15
15
|
id: repo.id,
|
|
16
16
|
name: repo.name,
|
|
17
17
|
path: repo.path,
|
|
18
|
+
remote_url: repo.remoteUrl ?? null,
|
|
18
19
|
created_at: repo.createdAt instanceof Date ? repo.createdAt.getTime() : repo.createdAt,
|
|
19
20
|
updated_at: repo.updatedAt instanceof Date ? repo.updatedAt.getTime() : repo.updatedAt,
|
|
20
21
|
deleted_at: repo.deletedAt
|
|
@@ -32,6 +33,7 @@ export function fromDatabase(row) {
|
|
|
32
33
|
id: row.id,
|
|
33
34
|
name: row.name,
|
|
34
35
|
path: row.path,
|
|
36
|
+
remoteUrl: row.remote_url ?? undefined,
|
|
35
37
|
createdAt: new Date(row.created_at),
|
|
36
38
|
updatedAt: new Date(row.updated_at),
|
|
37
39
|
deletedAt: row.deleted_at ? new Date(row.deleted_at) : undefined,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 040: Add remote_url column to repositories table.
|
|
3
|
+
*
|
|
4
|
+
* Adds a nullable TEXT column for storing the GitHub remote URL a repository
|
|
5
|
+
* was cloned from. Includes an index for efficient duplicate detection
|
|
6
|
+
* via findByRemoteUrl().
|
|
7
|
+
*/
|
|
8
|
+
import type { MigrationParams } from 'umzug';
|
|
9
|
+
import type Database from 'better-sqlite3';
|
|
10
|
+
export declare function up({ context: db }: MigrationParams<Database.Database>): Promise<void>;
|
|
11
|
+
export declare function down({ context: db }: MigrationParams<Database.Database>): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=040-add-repository-remote-url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"040-add-repository-remote-url.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/persistence/sqlite/migrations/040-add-repository-remote-url.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,wBAAsB,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAc3F;AAED,wBAAsB,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7F"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 040: Add remote_url column to repositories table.
|
|
3
|
+
*
|
|
4
|
+
* Adds a nullable TEXT column for storing the GitHub remote URL a repository
|
|
5
|
+
* was cloned from. Includes an index for efficient duplicate detection
|
|
6
|
+
* via findByRemoteUrl().
|
|
7
|
+
*/
|
|
8
|
+
export async function up({ context: db }) {
|
|
9
|
+
const columns = db.pragma('table_info(repositories)');
|
|
10
|
+
const existing = new Set(columns.map((c) => c.name));
|
|
11
|
+
if (!existing.has('remote_url')) {
|
|
12
|
+
db.exec('ALTER TABLE repositories ADD COLUMN remote_url TEXT');
|
|
13
|
+
}
|
|
14
|
+
// Add index for efficient duplicate detection by remote URL
|
|
15
|
+
const indexes = db.pragma('index_list(repositories)');
|
|
16
|
+
const indexNames = new Set(indexes.map((i) => i.name));
|
|
17
|
+
if (!indexNames.has('idx_repositories_remote_url')) {
|
|
18
|
+
db.exec('CREATE INDEX idx_repositories_remote_url ON repositories(remote_url)');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function down({ context: db }) {
|
|
22
|
+
// SQLite does not support DROP COLUMN before 3.35.0; drop the index only.
|
|
23
|
+
// The column remains but is unused after rollback.
|
|
24
|
+
const indexes = db.pragma('index_list(repositories)');
|
|
25
|
+
const indexNames = new Set(indexes.map((i) => i.name));
|
|
26
|
+
if (indexNames.has('idx_repositories_remote_url')) {
|
|
27
|
+
db.exec('DROP INDEX idx_repositories_remote_url');
|
|
28
|
+
}
|
|
29
|
+
}
|
package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.d.ts
CHANGED
|
@@ -15,7 +15,10 @@ export declare class SQLiteRepositoryRepository implements IRepositoryRepository
|
|
|
15
15
|
list(): Promise<Repository[]>;
|
|
16
16
|
remove(id: string): Promise<void>;
|
|
17
17
|
findByPathIncludingDeleted(path: string): Promise<Repository | null>;
|
|
18
|
+
findByRemoteUrl(url: string): Promise<Repository | null>;
|
|
19
|
+
update(id: string, fields: Partial<Pick<Repository, 'name' | 'path' | 'remoteUrl'>>): Promise<Repository>;
|
|
18
20
|
softDelete(id: string): Promise<void>;
|
|
19
21
|
restore(id: string): Promise<void>;
|
|
22
|
+
static normalizeRemoteUrl(url: string): string;
|
|
20
23
|
}
|
|
21
24
|
//# sourceMappingURL=sqlite-repository.repository.d.ts.map
|
package/dist/packages/core/src/infrastructure/repositories/sqlite-repository.repository.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-repository.repository.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/repositories/sqlite-repository.repository.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gFAAgF,CAAC;AAC5H,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAOnE,qBACa,0BAA2B,YAAW,qBAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAE5C,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAYnD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAMhD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAQpD,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAQ7B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAMpE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlite-repository.repository.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/repositories/sqlite-repository.repository.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gFAAgF,CAAC;AAC5H,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAOnE,qBACa,0BAA2B,YAAW,qBAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAE5C,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAYnD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAMhD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAQpD,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAQ7B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAMpE,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IASxD,MAAM,CACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC,GAC/D,OAAO,CAAC,UAAU,CAAC;IA+BhB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxC,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;CAG/C"}
|
|
@@ -12,9 +12,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
12
12
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
13
13
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
14
14
|
};
|
|
15
|
+
var SQLiteRepositoryRepository_1;
|
|
15
16
|
import { injectable } from 'tsyringe';
|
|
16
17
|
import { toDatabase, fromDatabase, } from '../persistence/sqlite/mappers/repository.mapper.js';
|
|
17
|
-
let SQLiteRepositoryRepository = class SQLiteRepositoryRepository {
|
|
18
|
+
let SQLiteRepositoryRepository = SQLiteRepositoryRepository_1 = class SQLiteRepositoryRepository {
|
|
18
19
|
db;
|
|
19
20
|
constructor(db) {
|
|
20
21
|
this.db = db;
|
|
@@ -54,6 +55,38 @@ let SQLiteRepositoryRepository = class SQLiteRepositoryRepository {
|
|
|
54
55
|
const row = stmt.get(path.replace(/\\/g, '/'));
|
|
55
56
|
return row ? fromDatabase(row) : null;
|
|
56
57
|
}
|
|
58
|
+
async findByRemoteUrl(url) {
|
|
59
|
+
const normalized = SQLiteRepositoryRepository_1.normalizeRemoteUrl(url);
|
|
60
|
+
const stmt = this.db.prepare('SELECT * FROM repositories WHERE remote_url = ? AND deleted_at IS NULL');
|
|
61
|
+
const row = stmt.get(normalized);
|
|
62
|
+
return row ? fromDatabase(row) : null;
|
|
63
|
+
}
|
|
64
|
+
async update(id, fields) {
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
const setClauses = ['updated_at = ?'];
|
|
67
|
+
const values = [now];
|
|
68
|
+
if (fields.name !== undefined) {
|
|
69
|
+
setClauses.push('name = ?');
|
|
70
|
+
values.push(fields.name);
|
|
71
|
+
}
|
|
72
|
+
if (fields.path !== undefined) {
|
|
73
|
+
setClauses.push('path = ?');
|
|
74
|
+
values.push(fields.path);
|
|
75
|
+
}
|
|
76
|
+
if (fields.remoteUrl !== undefined) {
|
|
77
|
+
setClauses.push('remote_url = ?');
|
|
78
|
+
values.push(fields.remoteUrl);
|
|
79
|
+
}
|
|
80
|
+
values.push(id);
|
|
81
|
+
const stmt = this.db.prepare(`UPDATE repositories SET ${setClauses.join(', ')} WHERE id = ?`);
|
|
82
|
+
const result = stmt.run(...values);
|
|
83
|
+
if (result.changes === 0) {
|
|
84
|
+
throw new Error(`Repository not found: ${id}`);
|
|
85
|
+
}
|
|
86
|
+
const selectStmt = this.db.prepare('SELECT * FROM repositories WHERE id = ?');
|
|
87
|
+
const row = selectStmt.get(id);
|
|
88
|
+
return fromDatabase(row);
|
|
89
|
+
}
|
|
57
90
|
async softDelete(id) {
|
|
58
91
|
const now = Date.now();
|
|
59
92
|
const stmt = this.db.prepare('UPDATE repositories SET deleted_at = ?, updated_at = ? WHERE id = ?');
|
|
@@ -64,8 +97,11 @@ let SQLiteRepositoryRepository = class SQLiteRepositoryRepository {
|
|
|
64
97
|
const stmt = this.db.prepare('UPDATE repositories SET deleted_at = NULL, updated_at = ? WHERE id = ?');
|
|
65
98
|
stmt.run(now, id);
|
|
66
99
|
}
|
|
100
|
+
static normalizeRemoteUrl(url) {
|
|
101
|
+
return url.replace(/\.git$/, '').toLowerCase();
|
|
102
|
+
}
|
|
67
103
|
};
|
|
68
|
-
SQLiteRepositoryRepository = __decorate([
|
|
104
|
+
SQLiteRepositoryRepository = SQLiteRepositoryRepository_1 = __decorate([
|
|
69
105
|
injectable(),
|
|
70
106
|
__metadata("design:paramtypes", [Object])
|
|
71
107
|
], SQLiteRepositoryRepository);
|
package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Repository Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Implements IGitHubRepositoryService using the gh CLI for authentication
|
|
5
|
+
* checks, repository listing, cloning (with progress streaming), and URL parsing.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExecFunction } from '../git/worktree.service.js';
|
|
8
|
+
import type { IGitHubRepositoryService, GitHubRepo, ListUserRepositoriesOptions, CloneOptions, ParsedGitHubUrl } from '../../../application/ports/output/services/github-repository-service.interface.js';
|
|
9
|
+
export declare class GitHubRepositoryService implements IGitHubRepositoryService {
|
|
10
|
+
private readonly execFile;
|
|
11
|
+
constructor(execFile: ExecFunction);
|
|
12
|
+
checkAuth(): Promise<void>;
|
|
13
|
+
listUserRepositories(options?: ListUserRepositoriesOptions): Promise<GitHubRepo[]>;
|
|
14
|
+
cloneRepository(nameWithOwner: string, destination: string, options?: CloneOptions): Promise<void>;
|
|
15
|
+
parseGitHubUrl(url: string): ParsedGitHubUrl;
|
|
16
|
+
private cleanupPartialClone;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=github-repository.service.d.ts.map
|
package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-repository.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/external/github-repository.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EACV,wBAAwB,EACxB,UAAU,EACV,2BAA2B,EAC3B,YAAY,EACZ,eAAe,EAChB,MAAM,mFAAmF,CAAC;AAwB3F,qBACa,uBAAwB,YAAW,wBAAwB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAErE,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB1B,oBAAoB,CAAC,OAAO,CAAC,EAAE,2BAA2B,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAsClF,eAAe,CACnB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,IAAI,CAAC;IAgDhB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;YA2C9B,mBAAmB;CAOlC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Repository Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Implements IGitHubRepositoryService using the gh CLI for authentication
|
|
5
|
+
* checks, repository listing, cloning (with progress streaming), and URL parsing.
|
|
6
|
+
*/
|
|
7
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
8
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
11
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
12
|
+
};
|
|
13
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
15
|
+
};
|
|
16
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
17
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
18
|
+
};
|
|
19
|
+
import { injectable, inject } from 'tsyringe';
|
|
20
|
+
import { resolve, normalize } from 'node:path';
|
|
21
|
+
import { rm } from 'node:fs/promises';
|
|
22
|
+
import { spawn } from 'node:child_process';
|
|
23
|
+
import { GitHubAuthError, GitHubCloneError, GitHubRepoListError, GitHubUrlParseError, } from '../../../application/ports/output/services/github-repository-service.interface.js';
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// URL regex patterns
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/** Matches https://github.com/owner/repo or https://github.com/owner/repo.git */
|
|
28
|
+
const HTTPS_PATTERN = /^https:\/\/github\.com\/([^/]+)\/([^/.]+?)(?:\.git)?$/;
|
|
29
|
+
/** Matches git@github.com:owner/repo.git */
|
|
30
|
+
const SSH_PATTERN = /^git@github\.com:([^/]+)\/([^/.]+?)(?:\.git)?$/;
|
|
31
|
+
/** Matches owner/repo shorthand (no slashes except the one separating owner/repo) */
|
|
32
|
+
const SHORTHAND_PATTERN = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)$/;
|
|
33
|
+
/** Default limit for listing repositories */
|
|
34
|
+
const DEFAULT_LIST_LIMIT = 30;
|
|
35
|
+
let GitHubRepositoryService = class GitHubRepositoryService {
|
|
36
|
+
execFile;
|
|
37
|
+
constructor(execFile) {
|
|
38
|
+
this.execFile = execFile;
|
|
39
|
+
}
|
|
40
|
+
async checkAuth() {
|
|
41
|
+
try {
|
|
42
|
+
// Use `gh auth token` instead of `gh auth status` because `gh auth status`
|
|
43
|
+
// exits non-zero when *any* configured account has a stale token, even if
|
|
44
|
+
// the active account is fully authenticated. `gh auth token` only checks the
|
|
45
|
+
// active account and exits 0 as long as it has a valid token.
|
|
46
|
+
await this.execFile('gh', ['auth', 'token']);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const cause = error instanceof Error ? error : undefined;
|
|
50
|
+
const errnoCode = error?.code;
|
|
51
|
+
if (errnoCode === 'ENOENT') {
|
|
52
|
+
throw new GitHubAuthError('GitHub CLI (gh) is not installed. Install it from https://cli.github.com/', cause);
|
|
53
|
+
}
|
|
54
|
+
throw new GitHubAuthError('GitHub CLI is not authenticated. Run `gh auth login` to sign in.', cause);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async listUserRepositories(options) {
|
|
58
|
+
const limit = options?.limit ?? DEFAULT_LIST_LIMIT;
|
|
59
|
+
const args = [
|
|
60
|
+
'repo',
|
|
61
|
+
'list',
|
|
62
|
+
'--json',
|
|
63
|
+
'name,nameWithOwner,description,isPrivate,pushedAt',
|
|
64
|
+
'--limit',
|
|
65
|
+
String(limit),
|
|
66
|
+
];
|
|
67
|
+
if (options?.search) {
|
|
68
|
+
// gh repo list does not have a --match flag; use jq to filter by name
|
|
69
|
+
const escaped = options.search.replace(/"/g, '\\"');
|
|
70
|
+
args.push('-q', `[.[] | select(.name | test("${escaped}"; "i"))]`);
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const { stdout } = await this.execFile('gh', args);
|
|
74
|
+
return JSON.parse(stdout);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const cause = error instanceof Error ? error : undefined;
|
|
78
|
+
const errnoCode = error?.code;
|
|
79
|
+
if (errnoCode === 'ENOENT') {
|
|
80
|
+
throw new GitHubRepoListError('GitHub CLI (gh) is not installed. Install it from https://cli.github.com/', cause);
|
|
81
|
+
}
|
|
82
|
+
throw new GitHubRepoListError(`Failed to list GitHub repositories: ${cause?.message ?? String(error)}`, cause);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async cloneRepository(nameWithOwner, destination, options) {
|
|
86
|
+
// Validate destination path — reject path traversal
|
|
87
|
+
const resolved = resolve(destination);
|
|
88
|
+
const normalized = normalize(resolved);
|
|
89
|
+
if (normalized !== resolved || destination.includes('..')) {
|
|
90
|
+
throw new GitHubCloneError(`Invalid clone destination: path traversal detected in "${destination}"`);
|
|
91
|
+
}
|
|
92
|
+
return new Promise((resolvePromise, reject) => {
|
|
93
|
+
const child = spawn('gh', ['repo', 'clone', nameWithOwner, resolved], {
|
|
94
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
95
|
+
});
|
|
96
|
+
let stderrOutput = '';
|
|
97
|
+
child.stderr?.on('data', (chunk) => {
|
|
98
|
+
const data = chunk.toString();
|
|
99
|
+
stderrOutput += data;
|
|
100
|
+
options?.onProgress?.(data);
|
|
101
|
+
});
|
|
102
|
+
child.stdout?.on('data', (chunk) => {
|
|
103
|
+
const data = chunk.toString();
|
|
104
|
+
options?.onProgress?.(data);
|
|
105
|
+
});
|
|
106
|
+
child.on('error', async (error) => {
|
|
107
|
+
await this.cleanupPartialClone(resolved);
|
|
108
|
+
reject(new GitHubCloneError(`Failed to clone ${nameWithOwner}: ${error.message}`, error));
|
|
109
|
+
});
|
|
110
|
+
child.on('close', async (code) => {
|
|
111
|
+
if (code === 0) {
|
|
112
|
+
resolvePromise();
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
await this.cleanupPartialClone(resolved);
|
|
116
|
+
reject(new GitHubCloneError(`Clone of ${nameWithOwner} failed with exit code ${code}: ${stderrOutput.trim()}`));
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
parseGitHubUrl(url) {
|
|
122
|
+
const trimmed = url.trim();
|
|
123
|
+
if (!trimmed) {
|
|
124
|
+
throw new GitHubUrlParseError('URL cannot be empty');
|
|
125
|
+
}
|
|
126
|
+
// Try HTTPS format
|
|
127
|
+
const httpsMatch = trimmed.match(HTTPS_PATTERN);
|
|
128
|
+
if (httpsMatch) {
|
|
129
|
+
return {
|
|
130
|
+
owner: httpsMatch[1],
|
|
131
|
+
repo: httpsMatch[2],
|
|
132
|
+
nameWithOwner: `${httpsMatch[1]}/${httpsMatch[2]}`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Try SSH format
|
|
136
|
+
const sshMatch = trimmed.match(SSH_PATTERN);
|
|
137
|
+
if (sshMatch) {
|
|
138
|
+
return {
|
|
139
|
+
owner: sshMatch[1],
|
|
140
|
+
repo: sshMatch[2],
|
|
141
|
+
nameWithOwner: `${sshMatch[1]}/${sshMatch[2]}`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// Try shorthand format (must be last — it's the loosest pattern)
|
|
145
|
+
const shorthandMatch = trimmed.match(SHORTHAND_PATTERN);
|
|
146
|
+
if (shorthandMatch) {
|
|
147
|
+
return {
|
|
148
|
+
owner: shorthandMatch[1],
|
|
149
|
+
repo: shorthandMatch[2],
|
|
150
|
+
nameWithOwner: `${shorthandMatch[1]}/${shorthandMatch[2]}`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
throw new GitHubUrlParseError(`Unrecognized GitHub URL format: "${trimmed}". ` +
|
|
154
|
+
'Supported formats: https://github.com/owner/repo, ' +
|
|
155
|
+
'git@github.com:owner/repo.git, or owner/repo shorthand.');
|
|
156
|
+
}
|
|
157
|
+
async cleanupPartialClone(destination) {
|
|
158
|
+
try {
|
|
159
|
+
await rm(destination, { recursive: true, force: true });
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Cleanup is best-effort
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
GitHubRepositoryService = __decorate([
|
|
167
|
+
injectable(),
|
|
168
|
+
__param(0, inject('ExecFunction')),
|
|
169
|
+
__metadata("design:paramtypes", [Function])
|
|
170
|
+
], GitHubRepositoryService);
|
|
171
|
+
export { GitHubRepositoryService };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo Add Command
|
|
3
|
+
*
|
|
4
|
+
* Import a GitHub repository by URL or interactively browse user's repos.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* shep repo add # Interactive wizard
|
|
8
|
+
* shep repo add --url owner/repo # Direct import by URL
|
|
9
|
+
* shep repo add --url <url> --dest /path # Override clone destination
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
export declare function createAddCommand(): Command;
|
|
13
|
+
//# sourceMappingURL=add.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/repo/add.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,gBAAgB,IAAI,OAAO,CA0E1C"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo Add Command
|
|
3
|
+
*
|
|
4
|
+
* Import a GitHub repository by URL or interactively browse user's repos.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* shep repo add # Interactive wizard
|
|
8
|
+
* shep repo add --url owner/repo # Direct import by URL
|
|
9
|
+
* shep repo add --url <url> --dest /path # Override clone destination
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
|
|
13
|
+
import { getSettings } from '../../../../../packages/core/src/infrastructure/services/settings.service.js';
|
|
14
|
+
import { ImportGitHubRepositoryUseCase } from '../../../../../packages/core/src/application/use-cases/repositories/import-github-repository.use-case.js';
|
|
15
|
+
import { ListGitHubRepositoriesUseCase } from '../../../../../packages/core/src/application/use-cases/repositories/list-github-repositories.use-case.js';
|
|
16
|
+
import { GitHubAuthError, GitHubCloneError, GitHubUrlParseError, } from '../../../../../packages/core/src/application/ports/output/services/github-repository-service.interface.js';
|
|
17
|
+
import { messages } from '../../ui/index.js';
|
|
18
|
+
import { githubImportWizard } from '../../../tui/wizards/github-import.wizard.js';
|
|
19
|
+
export function createAddCommand() {
|
|
20
|
+
return new Command('add')
|
|
21
|
+
.description('Import a GitHub repository (clone and register)')
|
|
22
|
+
.option('--url <url>', 'GitHub repository URL or owner/repo shorthand')
|
|
23
|
+
.option('--dest <path>', 'Override clone destination directory')
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
try {
|
|
26
|
+
const importUseCase = container.resolve(ImportGitHubRepositoryUseCase);
|
|
27
|
+
let url;
|
|
28
|
+
let dest = options.dest;
|
|
29
|
+
if (options.url) {
|
|
30
|
+
url = options.url;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// Interactive wizard
|
|
34
|
+
const gitHubService = container.resolve('IGitHubRepositoryService');
|
|
35
|
+
const listUseCase = container.resolve(ListGitHubRepositoriesUseCase);
|
|
36
|
+
const wizardResult = await githubImportWizard(gitHubService, listUseCase);
|
|
37
|
+
url = wizardResult.url;
|
|
38
|
+
if (!dest && wizardResult.dest) {
|
|
39
|
+
dest = wizardResult.dest;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Read default clone directory from settings
|
|
43
|
+
const settings = getSettings();
|
|
44
|
+
const defaultCloneDir = settings.environment?.defaultCloneDirectory;
|
|
45
|
+
const repository = await importUseCase.execute({
|
|
46
|
+
url,
|
|
47
|
+
dest,
|
|
48
|
+
defaultCloneDir,
|
|
49
|
+
});
|
|
50
|
+
messages.success(`Repository imported: ${repository.name}`);
|
|
51
|
+
messages.info(`Path: ${repository.path}`);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof GitHubAuthError) {
|
|
55
|
+
messages.error('GitHub CLI is not authenticated. Run `gh auth login` to sign in.');
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (error instanceof GitHubUrlParseError) {
|
|
60
|
+
messages.error(`Invalid GitHub URL: ${error.message}`);
|
|
61
|
+
messages.info('Supported formats: https://github.com/owner/repo, git@github.com:owner/repo.git, or owner/repo');
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (error instanceof GitHubCloneError) {
|
|
66
|
+
messages.error(`Clone failed: ${error.message}`);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// Handle Ctrl+C gracefully
|
|
71
|
+
if (error &&
|
|
72
|
+
typeof error === 'object' &&
|
|
73
|
+
'name' in error &&
|
|
74
|
+
error.name === 'ExitPromptError') {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
78
|
+
messages.error('Failed to import repository', err);
|
|
79
|
+
process.exitCode = 1;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/repo/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/repo/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAQ3C"}
|
|
@@ -9,10 +9,12 @@
|
|
|
9
9
|
* Subcommands:
|
|
10
10
|
* shep repo ls List tracked repositories
|
|
11
11
|
* shep repo show <id> Display details of a tracked repository
|
|
12
|
+
* shep repo add Import a GitHub repository
|
|
12
13
|
*/
|
|
13
14
|
import { Command } from 'commander';
|
|
14
15
|
import { createShowCommand } from './show.command.js';
|
|
15
16
|
import { createLsCommand } from './ls.command.js';
|
|
17
|
+
import { createAddCommand } from './add.command.js';
|
|
16
18
|
/**
|
|
17
19
|
* Create the repo command with all subcommands
|
|
18
20
|
*/
|
|
@@ -20,6 +22,7 @@ export function createRepoCommand() {
|
|
|
20
22
|
const repo = new Command('repo')
|
|
21
23
|
.description('Manage tracked repositories')
|
|
22
24
|
.addCommand(createLsCommand())
|
|
23
|
-
.addCommand(createShowCommand())
|
|
25
|
+
.addCommand(createShowCommand())
|
|
26
|
+
.addCommand(createAddCommand());
|
|
24
27
|
return repo;
|
|
25
28
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Import Wizard
|
|
3
|
+
*
|
|
4
|
+
* Interactive TUI wizard that guides users through importing a GitHub repository.
|
|
5
|
+
* Offers two paths: paste a GitHub URL or browse the user's repositories.
|
|
6
|
+
* Returns the selected URL/nameWithOwner and optional destination override.
|
|
7
|
+
*/
|
|
8
|
+
import type { IGitHubRepositoryService } from '../../../../packages/core/src/application/ports/output/services/github-repository-service.interface.js';
|
|
9
|
+
import type { ListGitHubRepositoriesUseCase } from '../../../../packages/core/src/application/use-cases/repositories/list-github-repositories.use-case.js';
|
|
10
|
+
/**
|
|
11
|
+
* Result returned by the GitHub import wizard.
|
|
12
|
+
*/
|
|
13
|
+
export interface GitHubImportWizardResult {
|
|
14
|
+
/** GitHub URL or owner/repo shorthand */
|
|
15
|
+
url: string;
|
|
16
|
+
/** Optional override for clone destination directory */
|
|
17
|
+
dest?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Runs the interactive GitHub import wizard.
|
|
21
|
+
*
|
|
22
|
+
* Steps:
|
|
23
|
+
* 1. Choose import method (URL input or browse repos)
|
|
24
|
+
* 2a. If URL: prompt for URL, validate with parseGitHubUrl
|
|
25
|
+
* 2b. If browse: fetch repos via listUseCase, display select list
|
|
26
|
+
* 3. Optionally prompt for destination directory override
|
|
27
|
+
*
|
|
28
|
+
* @param gitHubService - Service for URL validation
|
|
29
|
+
* @param listUseCase - Use case for listing user repos
|
|
30
|
+
* @returns The selected import target and optional destination
|
|
31
|
+
*/
|
|
32
|
+
export declare function githubImportWizard(gitHubService: IGitHubRepositoryService, listUseCase: ListGitHubRepositoriesUseCase): Promise<GitHubImportWizardResult>;
|
|
33
|
+
//# sourceMappingURL=github-import.wizard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-import.wizard.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/wizards/github-import.wizard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,wBAAwB,EAEzB,MAAM,4EAA4E,CAAC;AAEpF,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2EAA2E,CAAC;AAG/H;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAoBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,wBAAwB,EACvC,WAAW,EAAE,6BAA6B,GACzC,OAAO,CAAC,wBAAwB,CAAC,CAoCnC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Import Wizard
|
|
3
|
+
*
|
|
4
|
+
* Interactive TUI wizard that guides users through importing a GitHub repository.
|
|
5
|
+
* Offers two paths: paste a GitHub URL or browse the user's repositories.
|
|
6
|
+
* Returns the selected URL/nameWithOwner and optional destination override.
|
|
7
|
+
*/
|
|
8
|
+
import { select, input } from '@inquirer/prompts';
|
|
9
|
+
import { GitHubUrlParseError } from '../../../../packages/core/src/application/ports/output/services/github-repository-service.interface.js';
|
|
10
|
+
import { shepTheme } from '../themes/shep.theme.js';
|
|
11
|
+
/**
|
|
12
|
+
* Format a GitHub repo for display in the select list.
|
|
13
|
+
* Shows name, visibility badge, and truncated description.
|
|
14
|
+
*/
|
|
15
|
+
function formatRepoChoice(repo) {
|
|
16
|
+
const visibility = repo.isPrivate ? ' (private)' : '';
|
|
17
|
+
return {
|
|
18
|
+
name: `${repo.nameWithOwner}${visibility}`,
|
|
19
|
+
value: repo.nameWithOwner,
|
|
20
|
+
description: repo.description || undefined,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Runs the interactive GitHub import wizard.
|
|
25
|
+
*
|
|
26
|
+
* Steps:
|
|
27
|
+
* 1. Choose import method (URL input or browse repos)
|
|
28
|
+
* 2a. If URL: prompt for URL, validate with parseGitHubUrl
|
|
29
|
+
* 2b. If browse: fetch repos via listUseCase, display select list
|
|
30
|
+
* 3. Optionally prompt for destination directory override
|
|
31
|
+
*
|
|
32
|
+
* @param gitHubService - Service for URL validation
|
|
33
|
+
* @param listUseCase - Use case for listing user repos
|
|
34
|
+
* @returns The selected import target and optional destination
|
|
35
|
+
*/
|
|
36
|
+
export async function githubImportWizard(gitHubService, listUseCase) {
|
|
37
|
+
// Step 1: Choose import method
|
|
38
|
+
const method = await select({
|
|
39
|
+
message: 'How would you like to add a GitHub repository?',
|
|
40
|
+
choices: [
|
|
41
|
+
{
|
|
42
|
+
name: 'Paste a GitHub URL',
|
|
43
|
+
value: 'url',
|
|
44
|
+
description: 'Enter a GitHub repository URL or owner/repo shorthand',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Browse my repositories',
|
|
48
|
+
value: 'browse',
|
|
49
|
+
description: 'Search and select from your GitHub repositories',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
theme: shepTheme,
|
|
53
|
+
});
|
|
54
|
+
let url;
|
|
55
|
+
if (method === 'url') {
|
|
56
|
+
url = await promptForUrl(gitHubService);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
url = await promptForBrowse(listUseCase);
|
|
60
|
+
}
|
|
61
|
+
// Step 3: Optional destination override
|
|
62
|
+
const dest = await promptForDestination();
|
|
63
|
+
const result = { url };
|
|
64
|
+
if (dest) {
|
|
65
|
+
result.dest = dest;
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Prompt the user for a GitHub URL and validate it.
|
|
71
|
+
* Re-prompts on invalid input until a valid URL is provided.
|
|
72
|
+
*/
|
|
73
|
+
async function promptForUrl(gitHubService) {
|
|
74
|
+
const url = await input({
|
|
75
|
+
message: 'Enter a GitHub repository URL or owner/repo',
|
|
76
|
+
validate: (value) => {
|
|
77
|
+
if (!value.trim()) {
|
|
78
|
+
return 'URL is required';
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
gitHubService.parseGitHubUrl(value.trim());
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof GitHubUrlParseError) {
|
|
86
|
+
return error.message;
|
|
87
|
+
}
|
|
88
|
+
return 'Invalid GitHub URL format. Use https://github.com/owner/repo or owner/repo';
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
theme: shepTheme,
|
|
92
|
+
});
|
|
93
|
+
return url.trim();
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Prompt the user to browse and select from their GitHub repositories.
|
|
97
|
+
* Fetches repos via the list use case and displays them in a select prompt.
|
|
98
|
+
*/
|
|
99
|
+
async function promptForBrowse(listUseCase) {
|
|
100
|
+
const repos = await listUseCase.execute({ limit: 30 });
|
|
101
|
+
if (repos.length === 0) {
|
|
102
|
+
throw new Error('No repositories found. Make sure you have repositories on GitHub.');
|
|
103
|
+
}
|
|
104
|
+
const choices = repos.map(formatRepoChoice);
|
|
105
|
+
const selected = await select({
|
|
106
|
+
message: 'Select a repository to import',
|
|
107
|
+
choices,
|
|
108
|
+
theme: shepTheme,
|
|
109
|
+
});
|
|
110
|
+
return selected;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Optionally prompt for a custom clone destination directory.
|
|
114
|
+
*/
|
|
115
|
+
async function promptForDestination() {
|
|
116
|
+
const dest = await input({
|
|
117
|
+
message: 'Clone destination (leave empty for default)',
|
|
118
|
+
theme: shepTheme,
|
|
119
|
+
});
|
|
120
|
+
return dest.trim() || undefined;
|
|
121
|
+
}
|