@leanspec/ui 0.2.5-dev.20251120070726 → 0.2.5-dev.20251120093243
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/.next/standalone/packages/ui/.next/BUILD_ID +1 -1
- package/.next/standalone/packages/ui/.next/app-path-routes-manifest.json +12 -0
- package/.next/standalone/packages/ui/.next/build-manifest.json +7 -6
- package/.next/standalone/packages/ui/.next/prerender-manifest.json +28 -3
- package/.next/standalone/packages/ui/.next/routes-manifest.json +91 -0
- package/.next/standalone/packages/ui/.next/server/app/_global-error/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/_global-error/page.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.html +2 -2
- package/.next/standalone/packages/ui/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_not-found/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/_not-found/page.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/packages/ui/.next/server/app/_not-found.rsc +20 -19
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_full.segment.rsc +20 -19
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_index.segment.rsc +26 -25
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_tree.segment.rsc +5 -5
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route.js +6 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route.js +6 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js +6 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route.js +6 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js +8 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js +9 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js +8 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/route.js +4 -2
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js +8 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/route.js +3 -2
- package/.next/standalone/packages/ui/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/revalidate/route.js +4 -2
- package/.next/standalone/packages/ui/.next/server/app/api/revalidate/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/dependency-graph/route.js +4 -2
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/dependency-graph/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/route.js +4 -2
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/status/route.js +4 -3
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/status/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/subspecs/[file]/route.js +4 -2
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/subspecs/[file]/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/stats/route.js +4 -2
- package/.next/standalone/packages/ui/.next/server/app/api/stats/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/page.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/build-manifest.json +18 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/next-font-manifest.json +6 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js +21 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/build-manifest.json +18 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/next-font-manifest.json +6 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js +21 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/build-manifest.json +18 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/next-font-manifest.json +6 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js +20 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/build-manifest.json +18 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/next-font-manifest.json +6 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page.js +19 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.html +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.meta +14 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.rsc +34 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/_full.segment.rsc +34 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/_index.segment.rsc +27 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/_tree.segment.rsc +9 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/projects/__PAGE__.segment.rsc +9 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/projects.segment.rsc +4 -0
- package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page.js +4 -4
- package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/specs/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/specs/page.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/specs/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/specs/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/stats/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/stats/page.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/stats/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/stats/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app-paths-manifest.json +12 -0
- package/.next/standalone/packages/ui/.next/server/chunks/6681a__next-internal_server_app_api_projects_[id]_specs_[spec]_route_actions_d018d9e0.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/730ea_ui__next-internal_server_app_api_local-projects_[id]_route_actions_664abe9c.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/730ea_ui__next-internal_server_app_api_local-projects_discover_route_actions_e6ec3fa7.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/730ea_ui__next-internal_server_app_api_projects_[id]_stats_route_actions_a0bb04a8.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__0fbfea15._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__126dea7b._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__1f037512._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__3559376c._.js +21 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__548e27d4._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__65667b70._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__675a763e._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__803d07f0._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__8075fe29._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__8233e09b._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__84cdc14a._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__9ce722b4._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__a2d7cbed._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__aa677b0d._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__ac744182._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__bb9fca84._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__bdc3963a._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__f5c6d6b8._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__fb91986f._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/f825c_server_app_api_local-projects_list-directory_route_actions_d620ec1a.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/f825c_server_app_api_projects_[id]_specs_[spec]_status_route_actions_e9f1bdc5.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/node_modules__pnpm_731b55aa._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui__next-internal_server_app_api_local-projects_route_actions_9142d5ad.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui__next-internal_server_app_api_projects_[id]_route_actions_bff49675.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_db_index_ts_556307fa._.js +64 -5
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_specs_sources_database-source_ts_0bd881ee._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_specs_sources_database-source_ts_baa0160d._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/38a22_sonner_dist_index_mjs_207730fe._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/6e9bd_next_dist_7af75658._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/{_a5b58449._.js → 6e9bd_next_dist_df5dcbe9._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/730ea_ui__next-internal_server_app_projects_[projectId]_specs_page_actions_82e32fe4.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__01bfc8ff._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__1d0c2012._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__41f5b5c0._.js → [root-of-the-server]__4ec37765._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__1af33d49._.js → [root-of-the-server]__50122e7e._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__5382b397._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__73f60f12._.js +7 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__88a691ee._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__a7ae8552._.js +7 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__bdbbba01._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__c592f5d1._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__cc589a54._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__ec5b96a5._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__cbbbfb5d._.js → [root-of-the-server]__fd80e4dd._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_000dd317._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_196b5a83._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_39562b2a._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_3b617676._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_4129cc0f._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6174313a._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6e4dd8b6._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_85effc18._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_ad8c1e99._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_bae6d2b8._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_c2f54661._.js +5 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_fdd7780b._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/f825c_server_app_projects_[projectId]_specs_[specId]_page_actions_22d9c35e.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_af9d3830._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui__next-internal_server_app_projects_[projectId]_page_actions_f2986585.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui__next-internal_server_app_projects_page_actions_715940ea.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_[projectId]_be242d6c._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_[projectId]_project-context-syncer_tsx_7954ea3b._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_page_tsx_6e166c8e._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_specs_specs-client_tsx_0bb8f8f8._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_components_ui_select_tsx_7e21d40f._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_lib_specs_sources_database-source_ts_f7186c2a._.js +60 -1
- package/.next/standalone/packages/ui/.next/server/middleware-build-manifest.js +5 -4
- package/.next/standalone/packages/ui/.next/server/pages/404.html +2 -2
- package/.next/standalone/packages/ui/.next/server/pages/500.html +2 -2
- package/.next/standalone/packages/ui/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/packages/ui/.next/static/chunks/07f48b316e895080.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/0a7be410b438418a.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/1089ca88f6bef846.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/17471c87082c392c.js +5 -0
- package/.next/standalone/packages/ui/.next/static/chunks/220ba5cb8fe4dd69.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/35ccd3286e538bd2.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/571033caca823138.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/5a6fc30cd64085b4.css +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/5c2072ad938de8ed.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/843e1dfdc28e1385.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/9dad7fd31627df80.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/{c3d4d07de959ecf1.js → a055d4b2866ff8d4.js} +1 -1
- package/.next/standalone/packages/ui/.next/static/chunks/afb7c5a4255f4081.js +3 -0
- package/.next/{static/chunks/c557ac675be79771.js → standalone/packages/ui/.next/static/chunks/b760a3a9c2c8be28.js} +1 -1
- package/.next/standalone/packages/ui/.next/static/chunks/dcdd95180149fa10.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/ebd89051637b9a47.js +4 -0
- package/.next/standalone/packages/ui/.next/static/chunks/f9db24028d8c058e.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/fb640f50455ba34f.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/turbopack-b9690cacbf9fe48c.js +3 -0
- package/.next/standalone/packages/ui/bin/ui.js +17 -7
- package/.next/standalone/packages/ui/package.json +3 -1
- package/.next/standalone/packages/ui/src/app/api/local-projects/[id]/route.ts +117 -0
- package/.next/standalone/packages/ui/src/app/api/local-projects/discover/route.ts +41 -0
- package/.next/standalone/packages/ui/src/app/api/local-projects/list-directory/route.ts +38 -0
- package/.next/standalone/packages/ui/src/app/api/local-projects/route.ts +63 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/route.ts +97 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/[spec]/route.ts +38 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/[spec]/status/route.ts +97 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/route.ts +7 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/stats/route.ts +19 -0
- package/.next/standalone/packages/ui/src/app/api/projects/route.ts +48 -1
- package/.next/standalone/packages/ui/src/app/dashboard-client.tsx +67 -6
- package/.next/standalone/packages/ui/src/app/layout.tsx +11 -8
- package/.next/standalone/packages/ui/src/app/not-found.tsx +1 -1
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/layout.tsx +18 -0
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/page.tsx +10 -0
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/project-context-syncer.tsx +16 -0
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/specs/[specId]/page.tsx +34 -0
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/specs/page.tsx +20 -0
- package/.next/standalone/packages/ui/src/app/projects/page.tsx +156 -0
- package/.next/standalone/packages/ui/src/app/specs/specs-client.tsx +7 -2
- package/.next/standalone/packages/ui/src/components/create-project-dialog.tsx +139 -0
- package/.next/standalone/packages/ui/src/components/directory-picker.tsx +191 -0
- package/.next/standalone/packages/ui/src/components/main-sidebar.tsx +4 -0
- package/.next/standalone/packages/ui/src/components/project-switcher.tsx +139 -0
- package/.next/standalone/packages/ui/src/components/ui/dropdown-menu.tsx +200 -0
- package/.next/standalone/packages/ui/src/components/ui/popover.tsx +31 -0
- package/.next/standalone/packages/ui/src/contexts/project-context.tsx +229 -0
- package/.next/standalone/packages/ui/src/lib/db/index.ts +100 -0
- package/.next/standalone/packages/ui/src/lib/projects/index.ts +7 -0
- package/.next/standalone/packages/ui/src/lib/projects/registry.ts +467 -0
- package/.next/standalone/packages/ui/src/lib/projects/types.ts +37 -0
- package/.next/standalone/packages/ui/src/lib/specs/service.ts +13 -1
- package/.next/standalone/packages/ui/src/lib/specs/sources/multi-project-source.ts +258 -0
- package/.next/standalone/packages/ui/tsconfig.tsbuildinfo +1 -1
- package/.next/static/chunks/07f48b316e895080.js +1 -0
- package/.next/static/chunks/0a7be410b438418a.js +1 -0
- package/.next/static/chunks/1089ca88f6bef846.js +1 -0
- package/.next/static/chunks/17471c87082c392c.js +5 -0
- package/.next/static/chunks/220ba5cb8fe4dd69.js +1 -0
- package/.next/static/chunks/35ccd3286e538bd2.js +1 -0
- package/.next/static/chunks/571033caca823138.js +1 -0
- package/.next/static/chunks/5a6fc30cd64085b4.css +1 -0
- package/.next/static/chunks/5c2072ad938de8ed.js +1 -0
- package/.next/static/chunks/843e1dfdc28e1385.js +1 -0
- package/.next/static/chunks/9dad7fd31627df80.js +1 -0
- package/.next/static/chunks/{c3d4d07de959ecf1.js → a055d4b2866ff8d4.js} +1 -1
- package/.next/static/chunks/afb7c5a4255f4081.js +3 -0
- package/.next/{standalone/packages/ui/.next/static/chunks/c557ac675be79771.js → static/chunks/b760a3a9c2c8be28.js} +1 -1
- package/.next/static/chunks/dcdd95180149fa10.js +1 -0
- package/.next/static/chunks/ebd89051637b9a47.js +4 -0
- package/.next/static/chunks/f9db24028d8c058e.js +1 -0
- package/.next/static/chunks/fb640f50455ba34f.js +1 -0
- package/.next/static/chunks/turbopack-b9690cacbf9fe48c.js +3 -0
- package/bin/ui.js +17 -7
- package/package.json +3 -1
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__175bef84._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__3971eae5._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__482b093a._.js +0 -21
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__6bca1621._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__87a3475a._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__9f0f4c0b._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__c1c9f5f5._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__c6689757._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__cd1fb0a2._.js +0 -4
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__e2071b2e._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__299c81cc._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__5ca2e973._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__b2fe773d._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__e79a982a._.js +0 -7
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__ff03fc1e._.js +0 -7
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_66209e84._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6cd9a5e0._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_b483c9fe._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_b5040d31._.js +0 -5
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_9710705b._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_b8ff10b9._.js +0 -3
- package/.next/standalone/packages/ui/.next/static/chunks/093ea4b175adb770.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/5f97d665a4d9dc62.js +0 -3
- package/.next/standalone/packages/ui/.next/static/chunks/9a80c22382ddcfaf.css +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/9b7b7024c39c5f99.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/aa47b212786d8695.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/ae04dcd433be6dab.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/c0fe4c94c7282ac0.js +0 -4
- package/.next/standalone/packages/ui/.next/static/chunks/c61cbb6a0ba3b6ab.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/d79bf953f0dfb650.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/e50fb8d0b728cd35.js +0 -5
- package/.next/standalone/packages/ui/.next/static/chunks/e6e238dbf1d3e740.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/turbopack-9cc79aa1b34ffcbe.js +0 -3
- package/.next/static/chunks/093ea4b175adb770.js +0 -1
- package/.next/static/chunks/5f97d665a4d9dc62.js +0 -3
- package/.next/static/chunks/9a80c22382ddcfaf.css +0 -1
- package/.next/static/chunks/9b7b7024c39c5f99.js +0 -1
- package/.next/static/chunks/aa47b212786d8695.js +0 -1
- package/.next/static/chunks/ae04dcd433be6dab.js +0 -1
- package/.next/static/chunks/c0fe4c94c7282ac0.js +0 -4
- package/.next/static/chunks/c61cbb6a0ba3b6ab.js +0 -1
- package/.next/static/chunks/d79bf953f0dfb650.js +0 -1
- package/.next/static/chunks/e50fb8d0b728cd35.js +0 -5
- package/.next/static/chunks/e6e238dbf1d3e740.js +0 -1
- package/.next/static/chunks/turbopack-9cc79aa1b34ffcbe.js +0 -3
- /package/.next/standalone/packages/ui/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_buildManifest.js +0 -0
- /package/.next/standalone/packages/ui/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_clientMiddlewareManifest.json +0 -0
- /package/.next/standalone/packages/ui/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_ssgManifest.js +0 -0
- /package/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_buildManifest.js +0 -0
- /package/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,17612,22453,e=>{"use strict";var t=e.i(90022),s=e.i(31231),i=e.i(87985);let l="u">typeof window?s.useLayoutEffect:s.useEffect;function n(e){if(void 0!==e)switch(typeof e){case"number":return e;case"string":if(e.endsWith("px"))return parseFloat(e)}}let r=null;function a({containerElement:e,direction:t,isRtl:s,scrollOffset:i}){if("horizontal"===t&&s)switch(function(e=!1){if(null===r||e){let e=document.createElement("div"),t=e.style;t.width="50px",t.height="50px",t.overflow="scroll",t.direction="rtl";let s=document.createElement("div"),i=s.style;return i.width="100px",i.height="100px",e.appendChild(s),document.body.appendChild(e),e.scrollLeft>0?r="positive-descending":(e.scrollLeft=1,r=0===e.scrollLeft?"negative":"positive-ascending"),document.body.removeChild(e),r}return r}()){case"negative":return-i;case"positive-descending":if(e){let{clientWidth:t,scrollLeft:s,scrollWidth:i}=e;return i-t-s}}return i}function o(e,t="Assertion error"){if(!e)throw console.error(t),Error(t)}function c(e,t){if(e===t)return!0;if(!!e!=!!t||(o(void 0!==e),o(void 0!==t),Object.keys(e).length!==Object.keys(t).length))return!1;for(let s in e)if(!Object.is(t[s],e[s]))return!1;return!0}function d({cachedBounds:e,itemCount:t,itemSize:s}){if(0===t)return 0;if("number"==typeof s)return t*s;{let s=e.get(0===e.size?0:e.size-1);return o(void 0!==s,"Unexpected bounds cache miss"),t*((s.scrollOffset+s.size)/e.size)}}function u({cachedBounds:e,containerScrollOffset:t,containerSize:s,itemCount:i,overscanCount:l}){let n=i-1,r=0,a=-1,o=0,c=-1,d=0;for(;d<n;){let s=e.get(d);if(s.scrollOffset+s.size>t)break;d++}for(o=Math.max(0,(r=d)-l);d<n;){let i=e.get(d);if(i.scrollOffset+i.size>=t+s)break;d++}return c=Math.min(i-1,(a=Math.min(n,d))+l),r<0&&(r=0,a=-1,o=0,c=-1),{startIndexVisible:r,stopIndexVisible:a,startIndexOverscan:o,stopIndexOverscan:c}}function h(e,t){let{ariaAttributes:s,style:i,...l}=e,{ariaAttributes:n,style:r,...a}=t;return c(s,n)&&c(i,r)&&c(l,a)}function f({children:e,className:i,defaultHeight:r=0,listRef:f,onResize:m,onRowsRendered:x,overscanCount:p=3,rowComponent:g,rowCount:v,rowHeight:S,rowProps:b,tagName:w="div",style:j,...y}){let N=(0,s.useMemo)(()=>b,Object.values(b)),C=(0,s.useMemo)(()=>(0,s.memo)(g,h),[g]),[I,z]=(0,s.useState)(null),T=null!=S&&"object"==typeof S&&"getAverageRowHeight"in S&&"function"==typeof S.getAverageRowHeight,{getCellBounds:O,getEstimatedSize:R,scrollToIndex:E,startIndexOverscan:A,startIndexVisible:M,stopIndexOverscan:k,stopIndexVisible:L}=function({containerElement:e,containerStyle:t,defaultContainerSize:i=0,direction:r,isRtl:h=!1,itemCount:f,itemProps:m,itemSize:x,onResize:p,overscanCount:g}){var v;let S,[b,w]=(0,s.useState)({startIndexVisible:0,startIndexOverscan:0,stopIndexVisible:-1,stopIndexOverscan:-1}),{startIndexVisible:j,startIndexOverscan:y,stopIndexVisible:N,stopIndexOverscan:C}={startIndexVisible:Math.min(f-1,b.startIndexVisible),startIndexOverscan:Math.min(f-1,b.startIndexOverscan),stopIndexVisible:Math.min(f-1,b.stopIndexVisible),stopIndexOverscan:Math.min(f-1,b.stopIndexOverscan)},{height:I=i,width:z=i}=function({box:e,defaultHeight:t,defaultWidth:i,disabled:r,element:a,mode:o,style:c}){let{styleHeight:d,styleWidth:u}=(0,s.useMemo)(()=>({styleHeight:n(c?.height),styleWidth:n(c?.width)}),[c?.height,c?.width]),[h,f]=(0,s.useState)({height:t,width:i}),m=r||"only-height"===o&&void 0!==d||"only-width"===o&&void 0!==u||void 0!==d&&void 0!==u;return l(()=>{if(null===a||m)return;let t=new ResizeObserver(e=>{for(let t of e){let{contentRect:e,target:s}=t;a===s&&f(t=>t.height===e.height&&t.width===e.width?t:{height:e.height,width:e.width})}});return t.observe(a,{box:e}),()=>{t?.unobserve(a)}},[e,m,a,d,u]),(0,s.useMemo)(()=>({height:d??h.height,width:u??h.width}),[h,d,u])}({defaultHeight:"vertical"===r?i:void 0,defaultWidth:"horizontal"===r?i:void 0,element:e,mode:"vertical"===r?"only-height":"only-width",style:t}),T=(0,s.useRef)({height:0,width:0}),O="vertical"===r?I:z,R=function({containerSize:e,itemSize:t}){let s;return"string"==typeof t?(o(t.endsWith("%"),`Invalid item size: "${t}"; string values must be percentages (e.g. "100%")`),o(void 0!==e,"Container size must be defined if a percentage item size is specified"),s=e*parseInt(t)/100):s=t,s}({containerSize:O,itemSize:x});(0,s.useLayoutEffect)(()=>{if("function"==typeof p){let e=T.current;(e.height!==I||e.width!==z)&&(p({height:I,width:z},{...e}),e.height=I,e.width=z)}},[I,p,z]);let E=function({itemCount:e,itemProps:t,itemSize:i}){return(0,s.useMemo)(()=>(function({itemCount:e,itemProps:t,itemSize:s}){let i=new Map;return{get(l){for(o(l<e,`Invalid index ${l}`);i.size-1<l;){let e,n=i.size;switch(typeof s){case"function":e=s(n,t);break;case"number":e=s}if(0===n)i.set(n,{size:e,scrollOffset:0});else{let t=i.get(n-1);o(void 0!==t,`Unexpected bounds cache miss for index ${l}`),i.set(n,{scrollOffset:t.scrollOffset+t.size,size:e})}}let n=i.get(l);return o(void 0!==n,`Unexpected bounds cache miss for index ${l}`),n},set(e,t){i.set(e,t)},get size(){return i.size}}})({itemCount:e,itemProps:t,itemSize:i}),[e,t,i])}({itemCount:f,itemProps:m,itemSize:R}),A=(0,s.useCallback)(e=>E.get(e),[E]),M=(0,s.useCallback)(()=>d({cachedBounds:E,itemCount:f,itemSize:R}),[E,f,R]),k=(0,s.useCallback)(t=>u({cachedBounds:E,containerScrollOffset:a({containerElement:e,direction:r,isRtl:h,scrollOffset:t}),containerSize:O,itemCount:f,overscanCount:g}),[E,e,O,r,h,f,g]);return l(()=>{w(k(("vertical"===r?e?.scrollTop:e?.scrollLeft)??0))},[e,r,k]),l(()=>{if(!e)return;let t=()=>{w(t=>{let{scrollLeft:s,scrollTop:i}=e,l=u({cachedBounds:E,containerScrollOffset:a({containerElement:e,direction:r,isRtl:h,scrollOffset:"vertical"===r?i:s}),containerSize:O,itemCount:f,overscanCount:g});return c(l,t)?t:l})};return e.addEventListener("scroll",t),()=>{e.removeEventListener("scroll",t)}},[E,e,O,r,f,g]),{getCellBounds:A,getEstimatedSize:M,scrollToIndex:(v=({align:t="auto",containerScrollOffset:s,index:i})=>{let l=function({align:e,cachedBounds:t,index:s,itemCount:i,itemSize:l,containerScrollOffset:n,containerSize:r}){if(s<0||s>=i)throw RangeError(`Invalid index specified: ${s}`,{cause:`Index ${s} is not within the range of 0 - ${i-1}`});let a=d({cachedBounds:t,itemCount:i,itemSize:l}),o=t.get(s),c=Math.max(0,Math.min(a-r,o.scrollOffset)),u=Math.max(0,o.scrollOffset-r+o.size);switch("smart"===e&&(e=n>=u&&n<=c?"auto":"center"),e){case"start":return c;case"end":return u;case"center":return o.scrollOffset<=r/2?0:o.scrollOffset+o.size/2>=a-r/2?a-r:o.scrollOffset+o.size/2-r/2;default:return n>=u&&n<=c?n:n<u?u:c}}({align:t,cachedBounds:E,containerScrollOffset:s,containerSize:O,index:i,itemCount:f,itemSize:R});if(e){if(l=a({containerElement:e,direction:r,isRtl:h,scrollOffset:l}),"function"!=typeof e.scrollTo){let e=k(l);c(b,e)||w(e)}return l}},S=(0,s.useRef)(()=>{throw Error("Cannot call during render.")}),l(()=>{S.current=v},[v]),(0,s.useCallback)(e=>S.current?.(e),[S])),startIndexOverscan:y,startIndexVisible:j,stopIndexOverscan:C,stopIndexVisible:N}}({containerElement:I,containerStyle:j,defaultContainerSize:r,direction:"vertical",itemCount:v,itemProps:N,itemSize:(0,s.useMemo)(()=>T?e=>S.getRowHeight(e)??S.getAverageRowHeight():S,[T,S]),onResize:m,overscanCount:p});(0,s.useImperativeHandle)(f,()=>({get element(){return I},scrollToRow({align:e="auto",behavior:t="auto",index:s}){let i=E({align:e,containerScrollOffset:I?.scrollTop??0,index:s});"function"==typeof I?.scrollTo&&I.scrollTo({behavior:t,top:i})}}),[I,E]),l(()=>{if(!I)return;let e=Array.from(I.children).filter((e,t)=>{if(e.hasAttribute("aria-hidden"))return!1;let s=`${A+t}`;return e.setAttribute("data-react-window-index",s),!0});if(T)return S.observeRowElements(e)},[I,T,S,A,k]),(0,s.useEffect)(()=>{A>=0&&k>=0&&x&&x({startIndex:M,stopIndex:L},{startIndex:A,stopIndex:k})},[x,A,M,k,L]);let B=(0,s.useMemo)(()=>{let e=[];if(v>0)for(let t=A;t<=k;t++){let i=O(t);e.push((0,s.createElement)(C,{...N,ariaAttributes:{"aria-posinset":t+1,"aria-setsize":v,role:"listitem"},key:t,index:t,style:{position:"absolute",left:0,transform:`translateY(${i.scrollOffset}px)`,height:T?void 0:i.size,width:"100%"}}))}return e},[C,O,T,v,N,A,k]),V=(0,t.jsx)("div",{"aria-hidden":!0,style:{height:R(),width:"100%",zIndex:-1}});return(0,s.createElement)(w,{role:"list",...y,className:i,ref:z,style:{position:"relative",maxHeight:"100%",flexGrow:1,overflowY:"auto",...j}},B,e,V)}s.useState,s.useRef,s.useState,s.useRef;var m=e.i(329),x=e.i(58362),p=e.i(25761),g=e.i(44021),v=e.i(22764);let S=(0,e.i(22436).default)("funnel",[["path",{d:"M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z",key:"sc7q7i"}]]);var b=e.i(21079),w=e.i(35893),j=e.i(68497),y=e.i(8402),N=e.i(8737),C=e.i(32137),I=e.i(97705),z=e.i(45878);let T={specs:[],signature:null,scrollTop:0,activeSpecId:null},O=[],R=new Set,E=new Set,A=new Set;function M(){for(let e of R)e()}function k(e){return R.add(e),()=>{R.delete(e)}}function L(){return T}function B(){return(0,s.useSyncExternalStore)(k,L,()=>T)}function V(){let e=s.useCallback(e=>(E.add(e),()=>{E.delete(e)}),[]);return(0,s.useSyncExternalStore)(e,()=>L().specs,()=>O)}function H(){let e=s.useCallback(e=>(A.add(e),()=>{A.delete(e)}),[]);return(0,s.useSyncExternalStore)(e,()=>L().activeSpecId,()=>null)}function P(e){if(0===e.length)return;let t=e.map(e=>[e.id,e.specNumber??"",e.title??"",e.status??"",e.priority??"",e.updatedAt?new Date(e.updatedAt).getTime():0].join(":")).join("|");if(t!==T.signature)for(let s of(T={...T,specs:e,signature:t},M(),E))s()}function $(e){if(T.activeSpecId!==e)for(let t of(T={...T,activeSpecId:e},M(),A))t()}function F(e){1>Math.abs(e-T.scrollTop)||(T={...T,scrollTop:e})}function W(){return T.scrollTop}e.s(["getSidebarScrollTop",()=>W,"primeSpecsSidebar",()=>P,"setActiveSidebarSpec",()=>$,"updateSidebarScrollTop",()=>F,"useSpecsSidebarActiveSpec",()=>H,"useSpecsSidebarSpecs",()=>V,"useSpecsSidebarState",()=>B],22453);let U=s.useLayoutEffect;function q({initialSpecs:e=[],currentSpecId:l,currentSubSpec:n,onSpecHover:r}){let[a,o]=s.useState(""),[c,d]=s.useState("all"),[u,h]=s.useState("all"),[T,O]=s.useState("all"),[R,E]=s.useState(!1),[A,M]=s.useState(()=>"true"===localStorage.getItem("specs-nav-sidebar-collapsed")),[k,L]=s.useState(!1),[B,P]=s.useState(!1),$=s.useRef(null),q=s.useRef(null),D=s.useRef(!1),K=s.useRef(null),Y=s.useRef(0),G=s.useRef(!1),X=s.useRef(!0),J=V(),Q=H(),Z=s.useMemo(()=>J.length>0?J:e,[J,e]),_=l||Q||"";s.useEffect(()=>{P(!0)},[]),s.useEffect(()=>{document.documentElement.style.setProperty("--specs-nav-sidebar-width",A?"0px":"280px"),localStorage.setItem("specs-nav-sidebar-collapsed",String(A))},[A]),s.useEffect(()=>{L(!1)},[_,n]);let ee=s.useMemo(()=>{let e=Z;if(a){let t=a.toLowerCase();e=e.filter(e=>e.title?.toLowerCase().includes(t)||e.specName.toLowerCase().includes(t)||e.specNumber?.toString().includes(t))}return"all"!==c&&(e=e.filter(e=>e.status===c)),"all"!==u&&(e=e.filter(e=>e.priority===u)),"all"!==T&&(e=e.filter(e=>e.tags?.includes(T))),console.debug(e),e},[Z,a,c,u,T]),et=s.useMemo(()=>{let e=new Set;return Z.forEach(t=>{t.tags?.forEach(t=>e.add(t))}),Array.from(e).sort()},[Z]),es="all"!==c||"all"!==u||"all"!==T,ei=s.useMemo(()=>[...ee].sort((e,t)=>(t.specNumber||0)-(e.specNumber||0)),[ee]);U(()=>{let e=null,t=null;Y.current=W(),G.current=Y.current>0;let s=()=>{let i=K.current?.element;if(!i){e=window.requestAnimationFrame(s);return}D.current||(Y.current>0&&(i.scrollTop=Y.current),D.current=!0);let l=()=>{null===q.current&&(q.current=window.requestAnimationFrame(()=>{q.current=null,Y.current=i.scrollTop,F(i.scrollTop)}))};i.addEventListener("scroll",l,{passive:!0}),t=()=>{i.removeEventListener("scroll",l)}};return s(),()=>{t&&t(),null!==e&&window.cancelAnimationFrame(e),null!==q.current&&(window.cancelAnimationFrame(q.current),q.current=null)}},[]),U(()=>{if(!X.current||(X.current=!1,G.current||!_))return;let e=null,t=()=>{if(G.current)return;if(!D.current||!K.current){e=window.requestAnimationFrame(t);return}let s=ei.findIndex(e=>e.id===_);-1!==s&&(G.current=!0,K.current.scrollToRow({index:s,align:"center"}))};return t(),()=>{null!==e&&window.cancelAnimationFrame(e)}},[ei,_]),s.useEffect(()=>(window.toggleSpecsSidebar=()=>L(e=>!e),()=>{window.toggleSpecsSidebar=void 0}),[]);let el=s.useCallback(e=>{let{index:s,style:l}=e,a=ei[s],o=a.id===_,c=(a.contentMd?(0,C.extractH1Title)(a.contentMd):null)||a.title||a.specName;return(0,t.jsx)("div",{style:l,className:"px-1",children:(0,t.jsx)("div",{className:"mb-0.5",children:(0,t.jsx)("div",{className:"flex items-center gap-0.5",children:(0,t.jsxs)(y.Tooltip,{children:[(0,t.jsx)(y.TooltipTrigger,{asChild:!0,children:(0,t.jsxs)(i.default,{ref:o&&!n?$:null,href:`/specs/${a.specNumber||a.id}`,onMouseEnter:()=>r?.(a.specNumber?.toString()||a.id),className:(0,C.cn)("w-full flex flex-col gap-1 p-1.5 rounded-md text-sm transition-colors",o?"bg-accent text-accent-foreground font-medium":"hover:bg-accent/50"),children:[(0,t.jsxs)("div",{className:"flex items-center gap-1.5",children:[a.specNumber&&(0,t.jsxs)("span",{className:"text-xs font-mono text-muted-foreground shrink-0",children:["#",a.specNumber.toString().padStart(3,"0")]}),(0,t.jsx)("span",{className:"truncate text-xs leading-relaxed",children:c})]}),(0,t.jsxs)("div",{className:"flex items-center gap-1.5 flex-wrap",children:[a.status&&(0,t.jsxs)(y.Tooltip,{children:[(0,t.jsx)(y.TooltipTrigger,{asChild:!0,children:(0,t.jsx)("div",{children:(0,t.jsx)(j.StatusBadge,{status:a.status,iconOnly:!0,className:"text-[10px] scale-90"})})}),(0,t.jsx)(y.TooltipContent,{side:"right",children:(0,j.getStatusLabel)(a.status)})]}),a.priority&&(0,t.jsxs)(y.Tooltip,{children:[(0,t.jsx)(y.TooltipTrigger,{asChild:!0,children:(0,t.jsx)("div",{children:(0,t.jsx)(I.PriorityBadge,{priority:a.priority,iconOnly:!0,className:"text-[10px] scale-90"})})}),(0,t.jsx)(y.TooltipContent,{side:"right",children:(0,I.getPriorityLabel)(a.priority)})]}),"number"==typeof a.subSpecsCount&&a.subSpecsCount>0&&(0,t.jsxs)("span",{className:"text-[10px] text-muted-foreground",children:["+",a.subSpecsCount," files"]}),a.updatedAt&&(0,t.jsx)("span",{className:"text-[10px] text-muted-foreground",children:(0,z.formatRelativeTime)(a.updatedAt)})]})]})}),(0,t.jsx)(y.TooltipContent,{side:"right",className:"max-w-[300px]",children:(0,t.jsxs)("div",{className:"space-y-1",children:[(0,t.jsx)("div",{className:"font-semibold",children:c}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:a.specName})]})})]})})})})},[ei,_,n,r]),en=s.useMemo(()=>window.innerHeight-56-180,[]),er=s.useMemo(()=>s.memo(f),[]);return(0,t.jsxs)(y.TooltipProvider,{delayDuration:700,children:[k&&(0,t.jsx)("div",{className:"fixed inset-0 bg-black/50 z-40 lg:hidden",onClick:()=>L(!1)}),(0,t.jsxs)("div",{className:"relative flex-shrink-0",children:[(0,t.jsxs)("aside",{className:(0,C.cn)("sticky top-14 h-[calc(100vh-3.5rem)] border-r border-border bg-background flex flex-col overflow-hidden transition-all duration-300","hidden lg:flex",B&&A?"lg:w-0 lg:border-r-0":"lg:w-[280px]",k&&"fixed left-0 top-14 z-50 flex w-[280px]"),children:[(0,t.jsxs)("div",{className:"p-4 border-b border-border",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,t.jsx)("h2",{className:"font-semibold text-sm",children:"Specifications"}),(0,t.jsxs)("div",{className:"flex items-center gap-1",children:[(0,t.jsxs)(y.Tooltip,{children:[(0,t.jsx)(y.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(w.Button,{variant:R||es?"default":"ghost",size:"sm",onClick:()=>E(!R),className:"h-6 w-6 p-0",children:(0,t.jsx)(S,{className:"h-4 w-4"})})}),(0,t.jsx)(y.TooltipContent,{side:"bottom",children:R?"Hide filters":"Show filters"})]}),(0,t.jsx)(w.Button,{variant:"ghost",size:"sm",onClick:()=>L(!1),className:"h-6 w-6 p-0 lg:hidden",children:(0,t.jsx)(g.X,{className:"h-4 w-4"})}),(0,t.jsx)(w.Button,{variant:"ghost",size:"sm",onClick:()=>M(!0),className:"h-6 w-6 p-0 hidden lg:flex lg:items-center lg:justify-center",children:(0,t.jsx)(x.ChevronLeft,{className:"h-4 w-4"})})]})]}),R&&(0,t.jsxs)("div",{className:"space-y-2 mb-3 pb-3 border-b border-border",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsx)("span",{className:"text-xs font-medium text-muted-foreground",children:"Filters"}),es&&(0,t.jsx)(w.Button,{variant:"ghost",size:"sm",onClick:()=>{d("all"),h("all"),O("all")},className:"h-5 text-xs px-2 py-0",children:"Clear"})]}),(0,t.jsxs)(N.Select,{value:c,onValueChange:d,children:[(0,t.jsx)(N.SelectTrigger,{className:"h-8 text-xs",children:(0,t.jsx)(N.SelectValue,{placeholder:"Status"})}),(0,t.jsxs)(N.SelectContent,{children:[(0,t.jsx)(N.SelectItem,{value:"all",children:"All Status"}),(0,t.jsx)(N.SelectItem,{value:"planned",children:"Planned"}),(0,t.jsx)(N.SelectItem,{value:"in-progress",children:"In Progress"}),(0,t.jsx)(N.SelectItem,{value:"complete",children:"Complete"}),(0,t.jsx)(N.SelectItem,{value:"archived",children:"Archived"})]})]}),(0,t.jsxs)(N.Select,{value:u,onValueChange:h,children:[(0,t.jsx)(N.SelectTrigger,{className:"h-8 text-xs",children:(0,t.jsx)(N.SelectValue,{placeholder:"Priority"})}),(0,t.jsxs)(N.SelectContent,{children:[(0,t.jsx)(N.SelectItem,{value:"all",children:"All Priority"}),(0,t.jsx)(N.SelectItem,{value:"low",children:"Low"}),(0,t.jsx)(N.SelectItem,{value:"medium",children:"Medium"}),(0,t.jsx)(N.SelectItem,{value:"high",children:"High"}),(0,t.jsx)(N.SelectItem,{value:"critical",children:"Critical"})]})]}),et.length>0&&(0,t.jsxs)(N.Select,{value:T,onValueChange:O,children:[(0,t.jsx)(N.SelectTrigger,{className:"h-8 text-xs",children:(0,t.jsx)(N.SelectValue,{placeholder:"Tag"})}),(0,t.jsxs)(N.SelectContent,{children:[(0,t.jsx)(N.SelectItem,{value:"all",children:"All Tags"}),et.map(e=>(0,t.jsx)(N.SelectItem,{value:e,children:e},e))]})]})]}),(0,t.jsxs)("div",{className:"relative",children:[(0,t.jsx)(m.Search,{className:"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground"}),(0,t.jsx)(b.Input,{placeholder:"Search specs...",value:a,onChange:e=>o(e.target.value),className:"pl-8 h-9 border-border"})]})]}),(0,t.jsx)("div",{className:"flex-1 overflow-hidden",children:0===ei.length?(0,t.jsx)("div",{className:"text-center py-8 text-sm text-muted-foreground",children:"No specs found"}):(0,t.jsx)(er,{listRef:K,defaultHeight:en,rowCount:ei.length,rowHeight:72,overscanCount:5,rowComponent:el,rowProps:{}})})]}),B&&A&&(0,t.jsx)(w.Button,{variant:"ghost",size:"sm",onClick:()=>M(!1),className:"hidden lg:items-center lg:justify-center lg:flex h-6 w-6 p-0 fixed z-50 top-20 -translate-y-1 -translate-x-1/2 left-[calc(var(--main-sidebar-width,240px))] bg-background border",children:(0,t.jsx)(p.ChevronRight,{className:"h-4 w-4"})}),(0,t.jsx)(w.Button,{onClick:()=>L(!0),size:"icon",className:"lg:hidden fixed bottom-6 left-6 h-12 w-12 rounded-full shadow-lg z-40 hover:scale-110 transition-transform","aria-label":"Show specifications list",children:(0,t.jsx)(v.List,{className:"h-5 w-5"})})]})]})}e.s(["SpecsNavSidebar",()=>q],17612)},53213,e=>{"use strict";var t=e.i(90022),s=e.i(17612),i=e.i(32137);function l({className:e,...s}){return(0,t.jsx)("div",{className:(0,i.cn)("animate-pulse rounded-md bg-muted",e),...s})}var n=e.i(22453);function r(){let e=(0,n.useSpecsSidebarState)(),i=e.specs,r=e.activeSpecId||"";return(0,t.jsxs)("div",{className:"flex min-h-[calc(100vh-3.5rem)] w-full min-w-0",children:[(0,t.jsx)(s.SpecsNavSidebar,{initialSpecs:i,currentSpecId:r}),(0,t.jsx)("div",{className:"flex-1 min-w-0 px-4 py-6 sm:px-8 sm:py-10",children:(0,t.jsxs)("div",{className:"space-y-6",children:[(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsx)(l,{className:"h-7 w-56"}),(0,t.jsxs)("div",{className:"flex flex-wrap gap-3",children:[(0,t.jsx)(l,{className:"h-6 w-24"}),(0,t.jsx)(l,{className:"h-6 w-24"}),(0,t.jsx)(l,{className:"h-6 w-20"})]}),(0,t.jsx)(l,{className:"h-4 w-64"})]}),(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsx)(l,{className:"h-5 w-40"}),(0,t.jsx)(l,{className:"h-32 w-full"})]}),(0,t.jsx)("div",{className:"space-y-4",children:[...Array(6)].map((e,s)=>(0,t.jsx)(l,{className:"h-4 w-full"},s))})]})})]})}e.s(["SpecDetailLoadingShell",()=>r],53213)}]);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/b760a3a9c2c8be28.js","static/chunks/ebd89051637b9a47.js","static/chunks/7f732ea69e643219.js","static/chunks/f3ec9fd77a8618b1.js","static/chunks/5c2072ad938de8ed.js"],runtimeModuleIds:[79757]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=new WeakMap;function n(e,t){this.m=e,this.e=t}let o=n.prototype,l=Object.prototype.hasOwnProperty,i="undefined"!=typeof Symbol&&Symbol.toStringTag;function s(e,t,r){l.call(e,t)||Object.defineProperty(e,t,r)}function u(e,t){let r=e[t];return r||(r=a(t),e[t]=r),r}function a(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function c(e,t){s(e,"__esModule",{value:!0}),i&&s(e,i,{value:"Module"});let r=0;for(;r<t.length;){let n=t[r++],o=t[r++];if("number"==typeof o)if(0===o)s(e,n,{value:t[r++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[r]?s(e,n,{get:o,set:t[r++],enumerable:!0}):s(e,n,{get:o,enumerable:!0})}Object.seal(e)}o.s=function(e,t){let r,n;null!=t?n=(r=u(this.c,t)).exports:(r=this.m,n=this.e),r.namespaceObject=n,c(n,e)},o.j=function(e,t){var n,o;let i,s,a;null!=t?s=(i=u(this.c,t)).exports:(i=this.m,s=this.e);let c=(n=i,o=s,(a=r.get(n))||(r.set(n,a=[]),n.exports=n.namespaceObject=new Proxy(o,{get(e,t){if(l.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);for(let e of a){let r=Reflect.get(e,t);if(void 0!==r)return r}},ownKeys(e){let t=Reflect.ownKeys(e);for(let e of a)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t}})),a);"object"==typeof e&&null!==e&&c.push(e)},o.v=function(e,t){(null!=t?u(this.c,t):this.m).exports=e},o.n=function(e,t){let r;(r=null!=t?u(this.c,t):this.m).exports=r.namespaceObject=e};let f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,p=[null,f({}),f([]),f(f)];function h(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!p.includes(t);t=f(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),c(t,n),t}function d(e){let t=N(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=h(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function m(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}o.i=d,o.A=function(e){return this.r(e)(d.bind(this))},o.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},o.r=function(e){return N(e,this.m).exports},o.f=function(e){function t(t){if(l.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(l.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let b=Symbol("turbopack queues"),y=Symbol("turbopack exports"),O=Symbol("turbopack error");function g(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}o.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:l,reject:i,promise:s}=m(),u=Object.assign(s,{[y]:r.exports,[b]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[y]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(b in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[y]:{},[b]:e=>e(t)};return e.then(e=>{r[y]=e,g(t)},e=>{r[O]=e,g(t)}),r}}return{[y]:e,[b]:()=>{}}}),r=()=>t.map(e=>{if(e[O])throw e[O];return e[y]}),{promise:l,resolve:i}=m(),s=Object.assign(()=>i(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[b](u)),s.queueCount?l:r()},function(e){e?i(u[O]=e):l(u[y]),g(n)}),n&&-1===n.status&&(n.status=0)};let w=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function j(e,t){throw Error(`Invariant: ${t(e)}`)}w.prototype=URL.prototype,o.U=w,o.z=function(e){throw Error("dynamic usage of require is not supported")},o.g=globalThis;let R=n.prototype;var C,U=((C=U||{})[C.Runtime=0]="Runtime",C[C.Parent=1]="Parent",C[C.Update=2]="Update",C);let k=new Map;o.M=k;let v=new Map,_=new Map;async function P(e,t,r){let n;if("string"==typeof r)return A(e,t,S(r));let o=r.included||[],l=o.map(e=>!!k.has(e)||v.get(e));if(l.length>0&&l.every(e=>e))return void await Promise.all(l);let i=r.moduleChunks||[],s=i.map(e=>_.get(e)).filter(e=>e);if(s.length>0){if(s.length===i.length)return void await Promise.all(s);let r=new Set;for(let e of i)_.has(e)||r.add(e);for(let n of r){let r=A(e,t,S(n));_.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=A(e,t,S(r.path)),i))_.has(o)||_.set(o,n)}for(let e of o)v.has(e)||v.set(e,n);await n}R.l=function(e){return P(1,this.m.id,e)};let $=Promise.resolve(void 0),T=new WeakMap;function A(t,r,n){let o=e.loadChunkCached(t,n),l=T.get(o);if(void 0===l){let e=T.set.bind(T,o,$);l=o.then(e).catch(e=>{let o;switch(t){case 0:o=`as a runtime dependency of chunk ${r}`;break;case 1:o=`from module ${r}`;break;case 2:o="from an HMR update";break;default:j(t,e=>`Unknown source type: ${e}`)}throw Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0)}),T.set(o,l)}return l}function S(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}`}R.L=function(e){return A(1,this.m.id,e)},R.R=function(e){let t=this.r(e);return t?.default??t},R.P=function(e){return`/ROOT/${e??""}`},R.b=function(e){let t=new Blob([`self.TURBOPACK_WORKER_LOCATION = ${JSON.stringify(location.origin)};
|
|
2
|
+
self.TURBOPACK_NEXT_CHUNK_URLS = ${JSON.stringify(e.reverse().map(S),null,2)};
|
|
3
|
+
importScripts(...self.TURBOPACK_NEXT_CHUNK_URLS.map(c => self.TURBOPACK_WORKER_LOCATION + c).reverse());`],{type:"text/javascript"});return URL.createObjectURL(t)};let E=/\.js(?:\?[^#]*)?(?:#.*)?$/,K=/\.css(?:\?[^#]*)?(?:#.*)?$/;function x(e){return K.test(e)}o.w=function(t,r,n){return e.loadWebAssembly(1,this.m.id,t,r,n)},o.u=function(t,r){return e.loadWebAssemblyModule(1,this.m.id,t,r)};let M={};o.c=M;let N=(e,t)=>{let r=M[e];if(r){if(r.error)throw r.error;return r}return L(e,U.Parent,t.id)};function L(e,t,r){let o=k.get(e);if("function"!=typeof o)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:j(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let l=a(e),i=l.exports;M[e]=l;let s=new n(l,i);try{o(s,l,i)}catch(e){throw l.error=e,e}return l.namespaceObject&&l.exports!==l.namespaceObject&&h(l.exports,l.namespaceObject),l}function q(r){let n,o=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(("undefined"!=typeof TURBOPACK_NEXT_CHUNK_URLS?TURBOPACK_NEXT_CHUNK_URLS.pop():e.getAttribute("src")).replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(r[0]);return 2===r.length?n=r[1]:(n=void 0,!function(e,t,r,n){let o=1;for(;o<e.length;){let t=e[o],n=o+1;for(;n<e.length&&"function"!=typeof e[n];)n++;if(n===e.length)throw Error("malformed chunk format, expected a factory function");if(!r.has(t)){let l=e[n];for(Object.defineProperty(l,"name",{value:"module evaluation"});o<n;o++)t=e[o],r.set(t,l)}o=n+1}}(r,0,k)),e.registerChunk(o,n)}let B=new Map;function W(e){let t=B.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},B.set(e,t)}return t}e={async registerChunk(e,t){if(W(S(e)).resolve(),null!=t){for(let e of t.otherChunks)W(S("string"==typeof e?e:e.path));if(await Promise.all(t.otherChunks.map(t=>P(0,e,t))),t.runtimeModuleIds.length>0)for(let r of t.runtimeModuleIds)!function(e,t){let r=M[t];if(r){if(r.error)throw r.error;return}L(t,U.Runtime,e)}(e,r)}},loadChunkCached:(e,t)=>(function(e,t){let r=W(t);if(r.loadingStarted)return r.promise;if(e===U.Runtime)return r.loadingStarted=!0,x(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(x(t));else if(E.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(TURBOPACK_WORKER_LOCATION+t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(x(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(E.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let l=fetch(S(r)),{instance:i}=await WebAssembly.instantiateStreaming(l,o);return i.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(S(r));return await WebAssembly.compileStreaming(o)}};let I=globalThis.TURBOPACK;globalThis.TURBOPACK={push:q},I.forEach(q)})();
|
|
@@ -17,6 +17,7 @@ program
|
|
|
17
17
|
.option('-s, --specs <dir>', 'Specs directory (auto-detected if omitted)')
|
|
18
18
|
.option('-p, --port <port>', 'Port to run on', '3000')
|
|
19
19
|
.option('--no-open', "Don't open the browser automatically")
|
|
20
|
+
.option('--multi-project', 'Enable multi-project mode')
|
|
20
21
|
.option('--dry-run', 'Show what would run without executing')
|
|
21
22
|
.action(async (options) => {
|
|
22
23
|
try {
|
|
@@ -33,15 +34,24 @@ program.parseAsync(process.argv);
|
|
|
33
34
|
async function startUi(options) {
|
|
34
35
|
const cwd = process.cwd();
|
|
35
36
|
const port = validatePort(options.port);
|
|
36
|
-
|
|
37
|
+
|
|
38
|
+
let specsDir = '';
|
|
39
|
+
let specsMode = 'filesystem';
|
|
40
|
+
|
|
41
|
+
if (options.multiProject) {
|
|
42
|
+
specsMode = 'multi-project';
|
|
43
|
+
} else {
|
|
44
|
+
specsDir = resolveSpecsDirectory(cwd, options.specs);
|
|
45
|
+
}
|
|
46
|
+
|
|
37
47
|
const serverPath = getServerPath();
|
|
38
48
|
|
|
39
49
|
if (options.dryRun) {
|
|
40
|
-
printDryRun({ port, specsDir, serverPath, openBrowser: options.open });
|
|
50
|
+
printDryRun({ port, specsDir, specsMode, serverPath, openBrowser: options.open });
|
|
41
51
|
return;
|
|
42
52
|
}
|
|
43
53
|
|
|
44
|
-
await launchServer({ port, specsDir, serverPath, openBrowser: options.open });
|
|
54
|
+
await launchServer({ port, specsDir, specsMode, serverPath, openBrowser: options.open });
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
function validatePort(value) {
|
|
@@ -134,22 +144,22 @@ function getServerPath() {
|
|
|
134
144
|
throw new Error('LeanSpec UI build not found. Reinstall @leanspec/ui or run pnpm --filter @leanspec/ui build.');
|
|
135
145
|
}
|
|
136
146
|
|
|
137
|
-
function printDryRun({ port, specsDir, serverPath, openBrowser }) {
|
|
147
|
+
function printDryRun({ port, specsDir, specsMode, serverPath, openBrowser }) {
|
|
138
148
|
console.log(chalk.cyan('Would run:'));
|
|
139
|
-
console.log(chalk.dim(` SPECS_MODE
|
|
149
|
+
console.log(chalk.dim(` SPECS_MODE=${specsMode} SPECS_DIR=${specsDir} PORT=${port} node ${serverPath}`));
|
|
140
150
|
if (openBrowser) {
|
|
141
151
|
console.log(chalk.dim(` open http://localhost:${port}`));
|
|
142
152
|
}
|
|
143
153
|
}
|
|
144
154
|
|
|
145
|
-
async function launchServer({ port, specsDir, serverPath, openBrowser }) {
|
|
155
|
+
async function launchServer({ port, specsDir, specsMode, serverPath, openBrowser }) {
|
|
146
156
|
const spinner = ora('Starting LeanSpec UI...').start();
|
|
147
157
|
const serverDir = dirname(serverPath);
|
|
148
158
|
const env = {
|
|
149
159
|
...process.env,
|
|
150
160
|
NODE_ENV: 'production',
|
|
151
161
|
NEXT_TELEMETRY_DISABLED: '1',
|
|
152
|
-
SPECS_MODE:
|
|
162
|
+
SPECS_MODE: specsMode,
|
|
153
163
|
SPECS_DIR: specsDir,
|
|
154
164
|
PORT: port,
|
|
155
165
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leanspec/ui",
|
|
3
|
-
"version": "0.2.5-dev.
|
|
3
|
+
"version": "0.2.5-dev.20251120093243",
|
|
4
4
|
"description": "LeanSpec web UI launcher for visual spec management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"@radix-ui/react-avatar": "^1.1.11",
|
|
58
58
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
59
59
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
60
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
60
61
|
"@radix-ui/react-progress": "^1.1.8",
|
|
61
62
|
"@radix-ui/react-select": "^2.1.14",
|
|
62
63
|
"@radix-ui/react-separator": "^1.1.8",
|
|
@@ -101,6 +102,7 @@
|
|
|
101
102
|
"@leanspec/core": "workspace:*",
|
|
102
103
|
"@tailwindcss/typography": "^0.5.15",
|
|
103
104
|
"@types/better-sqlite3": "^7.6.12",
|
|
105
|
+
"@types/js-yaml": "^4.0.9",
|
|
104
106
|
"@types/mdast": "^4.0.4",
|
|
105
107
|
"@types/node": "^20",
|
|
106
108
|
"@types/react": "^19",
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Routes for individual project management
|
|
3
|
+
*
|
|
4
|
+
* GET /api/local-projects/[id] - Get project details
|
|
5
|
+
* PATCH /api/local-projects/[id] - Update project
|
|
6
|
+
* DELETE /api/local-projects/[id] - Remove project
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
10
|
+
import { projectRegistry } from '@/lib/projects';
|
|
11
|
+
|
|
12
|
+
interface RouteContext {
|
|
13
|
+
params: Promise<{ id: string }>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* GET /api/local-projects/[id]
|
|
18
|
+
* Get project details and touch lastAccessed
|
|
19
|
+
*/
|
|
20
|
+
export async function GET(
|
|
21
|
+
request: NextRequest,
|
|
22
|
+
context: RouteContext
|
|
23
|
+
) {
|
|
24
|
+
try {
|
|
25
|
+
const { id } = await context.params;
|
|
26
|
+
|
|
27
|
+
const project = await projectRegistry.getProject(id);
|
|
28
|
+
if (!project) {
|
|
29
|
+
return NextResponse.json(
|
|
30
|
+
{ error: 'Project not found' },
|
|
31
|
+
{ status: 404 }
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Touch project to update lastAccessed
|
|
36
|
+
await projectRegistry.touchProject(id);
|
|
37
|
+
|
|
38
|
+
return NextResponse.json({ project });
|
|
39
|
+
} catch (error: any) {
|
|
40
|
+
console.error('Error fetching project:', error);
|
|
41
|
+
return NextResponse.json(
|
|
42
|
+
{ error: 'Failed to fetch project', details: error.message },
|
|
43
|
+
{ status: 500 }
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* PATCH /api/local-projects/[id]
|
|
50
|
+
* Update project metadata
|
|
51
|
+
*
|
|
52
|
+
* Body: { name?: string, color?: string, description?: string, favorite?: boolean }
|
|
53
|
+
*/
|
|
54
|
+
export async function PATCH(
|
|
55
|
+
request: NextRequest,
|
|
56
|
+
context: RouteContext
|
|
57
|
+
) {
|
|
58
|
+
try {
|
|
59
|
+
const { id } = await context.params;
|
|
60
|
+
const body = await request.json();
|
|
61
|
+
|
|
62
|
+
// Handle favorite toggle separately
|
|
63
|
+
if ('favorite' in body && Object.keys(body).length === 1) {
|
|
64
|
+
const favorite = await projectRegistry.toggleFavorite(id);
|
|
65
|
+
const project = await projectRegistry.getProject(id);
|
|
66
|
+
return NextResponse.json({ project, favorite });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const { name, color, description } = body;
|
|
70
|
+
const updates: any = {};
|
|
71
|
+
|
|
72
|
+
if (name !== undefined) updates.name = name;
|
|
73
|
+
if (color !== undefined) updates.color = color;
|
|
74
|
+
if (description !== undefined) updates.description = description;
|
|
75
|
+
|
|
76
|
+
const project = await projectRegistry.updateProject(id, updates);
|
|
77
|
+
|
|
78
|
+
return NextResponse.json({ project });
|
|
79
|
+
} catch (error: any) {
|
|
80
|
+
console.error('Error updating project:', error);
|
|
81
|
+
|
|
82
|
+
if (error.message === 'Project not found') {
|
|
83
|
+
return NextResponse.json(
|
|
84
|
+
{ error: 'Project not found' },
|
|
85
|
+
{ status: 404 }
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return NextResponse.json(
|
|
90
|
+
{ error: 'Failed to update project', details: error.message },
|
|
91
|
+
{ status: 500 }
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* DELETE /api/local-projects/[id]
|
|
98
|
+
* Remove project from registry (doesn't delete files)
|
|
99
|
+
*/
|
|
100
|
+
export async function DELETE(
|
|
101
|
+
request: NextRequest,
|
|
102
|
+
context: RouteContext
|
|
103
|
+
) {
|
|
104
|
+
try {
|
|
105
|
+
const { id } = await context.params;
|
|
106
|
+
|
|
107
|
+
await projectRegistry.removeProject(id);
|
|
108
|
+
|
|
109
|
+
return NextResponse.json({ success: true });
|
|
110
|
+
} catch (error: any) {
|
|
111
|
+
console.error('Error removing project:', error);
|
|
112
|
+
return NextResponse.json(
|
|
113
|
+
{ error: 'Failed to remove project', details: error.message },
|
|
114
|
+
{ status: 500 }
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Route for project discovery
|
|
3
|
+
*
|
|
4
|
+
* POST /api/local-projects/discover - Discover projects in a directory
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
8
|
+
import { projectRegistry } from '@/lib/projects';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* POST /api/local-projects/discover
|
|
12
|
+
* Discover LeanSpec projects in a directory tree
|
|
13
|
+
*
|
|
14
|
+
* Body: { path: string, maxDepth?: number }
|
|
15
|
+
*/
|
|
16
|
+
export async function POST(request: NextRequest) {
|
|
17
|
+
try {
|
|
18
|
+
const body = await request.json();
|
|
19
|
+
const { path, maxDepth = 3 } = body;
|
|
20
|
+
|
|
21
|
+
if (!path || typeof path !== 'string') {
|
|
22
|
+
return NextResponse.json(
|
|
23
|
+
{ error: 'Invalid request: path is required' },
|
|
24
|
+
{ status: 400 }
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const discovered = await projectRegistry.discoverProjects(path, maxDepth);
|
|
29
|
+
|
|
30
|
+
return NextResponse.json({
|
|
31
|
+
discovered,
|
|
32
|
+
count: discovered.length,
|
|
33
|
+
});
|
|
34
|
+
} catch (error: any) {
|
|
35
|
+
console.error('Error discovering projects:', error);
|
|
36
|
+
return NextResponse.json(
|
|
37
|
+
{ error: 'Failed to discover projects', details: error.message },
|
|
38
|
+
{ status: 500 }
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Route for listing directory contents
|
|
3
|
+
*
|
|
4
|
+
* POST /api/local-projects/list-directory - List directories in a path
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
8
|
+
import { projectRegistry } from '@/lib/projects';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* POST /api/local-projects/list-directory
|
|
13
|
+
* List directories in a given path
|
|
14
|
+
*
|
|
15
|
+
* Body: { path?: string }
|
|
16
|
+
*/
|
|
17
|
+
export async function POST(request: NextRequest) {
|
|
18
|
+
try {
|
|
19
|
+
const body = await request.json();
|
|
20
|
+
const { path } = body;
|
|
21
|
+
|
|
22
|
+
// Use CWD if path is not provided, falling back to homedir
|
|
23
|
+
const targetPath = path || process.cwd() || homedir();
|
|
24
|
+
|
|
25
|
+
const items = await projectRegistry.listDirectory(targetPath);
|
|
26
|
+
|
|
27
|
+
return NextResponse.json({
|
|
28
|
+
path: targetPath,
|
|
29
|
+
items,
|
|
30
|
+
});
|
|
31
|
+
} catch (error: any) {
|
|
32
|
+
console.error('Error listing directory:', error);
|
|
33
|
+
return NextResponse.json(
|
|
34
|
+
{ error: 'Failed to list directory', details: error.message },
|
|
35
|
+
{ status: 500 }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Routes for local project management
|
|
3
|
+
*
|
|
4
|
+
* GET /api/local-projects - List all local projects
|
|
5
|
+
* POST /api/local-projects - Add a new project
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
9
|
+
import { projectRegistry } from '@/lib/projects';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* GET /api/local-projects
|
|
13
|
+
* Returns all registered local projects
|
|
14
|
+
*/
|
|
15
|
+
export async function GET() {
|
|
16
|
+
try {
|
|
17
|
+
const projects = await projectRegistry.getProjects();
|
|
18
|
+
const recentProjects = await projectRegistry.getRecentProjects();
|
|
19
|
+
const favoriteProjects = await projectRegistry.getFavoriteProjects();
|
|
20
|
+
|
|
21
|
+
return NextResponse.json({
|
|
22
|
+
projects,
|
|
23
|
+
recentProjects,
|
|
24
|
+
favoriteProjects,
|
|
25
|
+
});
|
|
26
|
+
} catch (error: any) {
|
|
27
|
+
console.error('Error fetching local projects:', error);
|
|
28
|
+
return NextResponse.json(
|
|
29
|
+
{ error: 'Failed to fetch local projects', details: error.message },
|
|
30
|
+
{ status: 500 }
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* POST /api/local-projects
|
|
37
|
+
* Add a new project to the registry
|
|
38
|
+
*
|
|
39
|
+
* Body: { path: string, favorite?: boolean, color?: string }
|
|
40
|
+
*/
|
|
41
|
+
export async function POST(request: NextRequest) {
|
|
42
|
+
try {
|
|
43
|
+
const body = await request.json();
|
|
44
|
+
const { path, favorite, color } = body;
|
|
45
|
+
|
|
46
|
+
if (!path || typeof path !== 'string') {
|
|
47
|
+
return NextResponse.json(
|
|
48
|
+
{ error: 'Invalid request: path is required' },
|
|
49
|
+
{ status: 400 }
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const project = await projectRegistry.addProject(path, { favorite, color });
|
|
54
|
+
|
|
55
|
+
return NextResponse.json({ project }, { status: 201 });
|
|
56
|
+
} catch (error: any) {
|
|
57
|
+
console.error('Error adding project:', error);
|
|
58
|
+
return NextResponse.json(
|
|
59
|
+
{ error: 'Failed to add project', details: error.message },
|
|
60
|
+
{ status: 500 }
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getProjectById } from '@/lib/db/queries';
|
|
3
|
+
import { projectRegistry } from '@/lib/projects/registry';
|
|
4
|
+
|
|
5
|
+
export async function GET(
|
|
6
|
+
request: Request,
|
|
7
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
8
|
+
) {
|
|
9
|
+
try {
|
|
10
|
+
const { id } = await params;
|
|
11
|
+
|
|
12
|
+
if (process.env.SPECS_MODE === 'multi-project') {
|
|
13
|
+
const project = await projectRegistry.getProject(id);
|
|
14
|
+
if (!project) {
|
|
15
|
+
return NextResponse.json(
|
|
16
|
+
{ error: 'Project not found' },
|
|
17
|
+
{ status: 404 }
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
// Touch project to update lastAccessed
|
|
21
|
+
await projectRegistry.touchProject(id);
|
|
22
|
+
return NextResponse.json({ project });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const project = await getProjectById(id);
|
|
26
|
+
if (!project) {
|
|
27
|
+
return NextResponse.json(
|
|
28
|
+
{ error: 'Project not found' },
|
|
29
|
+
{ status: 404 }
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return NextResponse.json({ project });
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error('Error fetching project:', error);
|
|
35
|
+
return NextResponse.json(
|
|
36
|
+
{ error: 'Failed to fetch project' },
|
|
37
|
+
{ status: 500 }
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function DELETE(
|
|
43
|
+
request: Request,
|
|
44
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
45
|
+
) {
|
|
46
|
+
try {
|
|
47
|
+
if (process.env.SPECS_MODE !== 'multi-project') {
|
|
48
|
+
return NextResponse.json(
|
|
49
|
+
{ error: 'Multi-project mode is not enabled' },
|
|
50
|
+
{ status: 400 }
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { id } = await params;
|
|
55
|
+
await projectRegistry.removeProject(id);
|
|
56
|
+
return NextResponse.json({ success: true });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error('Error deleting project:', error);
|
|
59
|
+
return NextResponse.json(
|
|
60
|
+
{ error: 'Failed to delete project' },
|
|
61
|
+
{ status: 500 }
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function PATCH(
|
|
67
|
+
request: Request,
|
|
68
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
69
|
+
) {
|
|
70
|
+
try {
|
|
71
|
+
if (process.env.SPECS_MODE !== 'multi-project') {
|
|
72
|
+
return NextResponse.json(
|
|
73
|
+
{ error: 'Multi-project mode is not enabled' },
|
|
74
|
+
{ status: 400 }
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const { id } = await params;
|
|
79
|
+
const body = await request.json();
|
|
80
|
+
|
|
81
|
+
// Handle favorite toggle separately
|
|
82
|
+
if ('favorite' in body) {
|
|
83
|
+
const favorite = await projectRegistry.toggleFavorite(id);
|
|
84
|
+
const project = await projectRegistry.getProject(id);
|
|
85
|
+
return NextResponse.json({ project, favorite });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const project = await projectRegistry.updateProject(id, body);
|
|
89
|
+
return NextResponse.json({ project });
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('Error updating project:', error);
|
|
92
|
+
return NextResponse.json(
|
|
93
|
+
{ error: 'Failed to update project' },
|
|
94
|
+
{ status: 500 }
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getSpecById } from '@/lib/db/queries';
|
|
3
|
+
import { specsService } from '@/lib/specs/service';
|
|
4
|
+
|
|
5
|
+
export async function GET(
|
|
6
|
+
request: Request,
|
|
7
|
+
{ params }: { params: Promise<{ id: string; spec: string }> }
|
|
8
|
+
) {
|
|
9
|
+
try {
|
|
10
|
+
const { id, spec: specId } = await params;
|
|
11
|
+
|
|
12
|
+
if (process.env.SPECS_MODE === 'multi-project') {
|
|
13
|
+
const spec = await specsService.getSpec(specId, id);
|
|
14
|
+
if (!spec) {
|
|
15
|
+
return NextResponse.json(
|
|
16
|
+
{ error: 'Spec not found' },
|
|
17
|
+
{ status: 404 }
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return NextResponse.json({ spec });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const spec = await getSpecById(specId);
|
|
24
|
+
if (!spec) {
|
|
25
|
+
return NextResponse.json(
|
|
26
|
+
{ error: 'Spec not found' },
|
|
27
|
+
{ status: 404 }
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return NextResponse.json({ spec });
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Error fetching spec:', error);
|
|
33
|
+
return NextResponse.json(
|
|
34
|
+
{ error: 'Failed to fetch spec' },
|
|
35
|
+
{ status: 500 }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { createUpdatedFrontmatter } from '@leanspec/core';
|
|
6
|
+
import { projectRegistry } from '@/lib/projects/registry';
|
|
7
|
+
|
|
8
|
+
const ALLOWED_STATUSES = ['planned', 'in-progress', 'complete', 'archived'] as const;
|
|
9
|
+
type AllowedStatus = (typeof ALLOWED_STATUSES)[number];
|
|
10
|
+
|
|
11
|
+
async function findSpecDirectory(specsDir: string, specIdentifier: string): Promise<string | null> {
|
|
12
|
+
if (!existsSync(specsDir)) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { readdir } = await import('node:fs/promises');
|
|
17
|
+
const entries = await readdir(specsDir, { withFileTypes: true });
|
|
18
|
+
|
|
19
|
+
// Match by spec number or full directory name
|
|
20
|
+
const specPattern = /^(\d{2,})-/;
|
|
21
|
+
const specNum = parseInt(specIdentifier.split('-')[0], 10);
|
|
22
|
+
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
if (!entry.isDirectory()) continue;
|
|
25
|
+
|
|
26
|
+
// Match by full name or by spec number
|
|
27
|
+
if (entry.name === specIdentifier) {
|
|
28
|
+
return path.join(specsDir, entry.name);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!isNaN(specNum) && specPattern.test(entry.name)) {
|
|
32
|
+
const dirNum = parseInt(entry.name.split('-')[0], 10);
|
|
33
|
+
if (dirNum === specNum) {
|
|
34
|
+
return path.join(specsDir, entry.name);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function PATCH(
|
|
43
|
+
request: Request,
|
|
44
|
+
{ params }: { params: Promise<{ id: string; spec: string }> }
|
|
45
|
+
) {
|
|
46
|
+
try {
|
|
47
|
+
const { id: projectId, spec: specId } = await params;
|
|
48
|
+
|
|
49
|
+
if (process.env.SPECS_MODE !== 'multi-project') {
|
|
50
|
+
return NextResponse.json({ error: 'Multi-project mode not enabled' }, { status: 400 });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const project = await projectRegistry.getProject(projectId);
|
|
54
|
+
if (!project) {
|
|
55
|
+
return NextResponse.json({ error: 'Project not found' }, { status: 404 });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let payload: { status?: AllowedStatus } = {};
|
|
59
|
+
try {
|
|
60
|
+
payload = await request.json();
|
|
61
|
+
} catch {
|
|
62
|
+
return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { status } = payload;
|
|
66
|
+
if (!status || !ALLOWED_STATUSES.includes(status)) {
|
|
67
|
+
return NextResponse.json({ error: 'Invalid status value' }, { status: 400 });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const specIdentifier = decodeURIComponent(specId);
|
|
71
|
+
const specDir = await findSpecDirectory(project.specsDir, specIdentifier);
|
|
72
|
+
|
|
73
|
+
if (!specDir) {
|
|
74
|
+
return NextResponse.json({ error: 'Spec not found' }, { status: 404 });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const readmePath = path.join(specDir, 'README.md');
|
|
78
|
+
|
|
79
|
+
if (!existsSync(readmePath)) {
|
|
80
|
+
return NextResponse.json({ error: 'Spec README.md not found' }, { status: 404 });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Read current content
|
|
84
|
+
const currentContent = await readFile(readmePath, 'utf-8');
|
|
85
|
+
|
|
86
|
+
// Update frontmatter using @leanspec/core
|
|
87
|
+
const { content: updatedContent } = createUpdatedFrontmatter(currentContent, { status });
|
|
88
|
+
|
|
89
|
+
// Write back to file
|
|
90
|
+
await writeFile(readmePath, updatedContent, 'utf-8');
|
|
91
|
+
|
|
92
|
+
return NextResponse.json({ success: true });
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('Failed to update spec status:', error);
|
|
95
|
+
return NextResponse.json({ error: 'Failed to update spec status' }, { status: 500 });
|
|
96
|
+
}
|
|
97
|
+
}
|