prime-dev-cli 2.0.6 → 2.0.8
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/dist/server/.next/BUILD_ID +1 -1
- package/dist/server/.next/app-build-manifest.json +8 -8
- package/dist/server/.next/app-path-routes-manifest.json +7 -0
- package/dist/server/.next/build-manifest.json +6 -6
- package/dist/server/.next/cache/.rscinfo +1 -1
- package/dist/server/.next/cache/.tsbuildinfo +1 -1
- package/dist/server/.next/cache/eslint/.cache_1qa5vxt +1 -1
- package/dist/server/.next/fallback-build-manifest.json +6 -6
- package/dist/server/.next/next-minimal-server.js.nft.json +1 -1
- package/dist/server/.next/next-server.js.nft.json +1 -1
- package/dist/server/.next/prerender-manifest.json +9 -9
- package/dist/server/.next/server/app/_not-found/page/app-build-manifest.json +1 -1
- package/dist/server/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app/_not-found.html +1 -1
- package/dist/server/.next/server/app/_not-found.rsc +2 -2
- package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route.js +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-delete-branch/route.js +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-delete-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-merge/route.js +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-merge/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-probe-remote-branch/route.js +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-probe-remote-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/all-projects-envs/route.js +1 -1
- package/dist/server/.next/server/app/api/all-projects-envs/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/batch-list-branches/route/app-build-manifest.json +10 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route/app-paths-manifest.json +3 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route/build-manifest.json +16 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route/next-font-manifest.json +6 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route/react-loadable-manifest.json +1 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route/server-reference-manifest.json +4 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route.js +8 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route.js.map +5 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route.js.nft.json +1 -0
- package/dist/server/.next/server/app/api/batch-list-branches/route_client-reference-manifest.js +2 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route/app-build-manifest.json +10 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route/app-paths-manifest.json +3 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route/build-manifest.json +16 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route/next-font-manifest.json +6 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route/react-loadable-manifest.json +1 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route/server-reference-manifest.json +4 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route.js +8 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route.js.map +5 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route.js.nft.json +1 -0
- package/dist/server/.next/server/app/api/batch-list-submodule-branches/route_client-reference-manifest.js +2 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route/app-build-manifest.json +10 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route/app-paths-manifest.json +3 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route/build-manifest.json +16 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route/next-font-manifest.json +6 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route/react-loadable-manifest.json +1 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route/server-reference-manifest.json +4 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route.js +8 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route.js.map +5 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route.js.nft.json +1 -0
- package/dist/server/.next/server/app/api/batch-switch-branch/route_client-reference-manifest.js +2 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route/app-build-manifest.json +10 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route/app-paths-manifest.json +3 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route/build-manifest.json +16 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route/next-font-manifest.json +6 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route/react-loadable-manifest.json +1 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route/server-reference-manifest.json +4 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route.js +8 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route.js.map +5 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route.js.nft.json +1 -0
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route_client-reference-manifest.js +2 -0
- package/dist/server/.next/server/app/api/branch/switch/route/app-build-manifest.json +10 -0
- package/dist/server/.next/server/app/api/branch/switch/route/app-paths-manifest.json +3 -0
- package/dist/server/.next/server/app/api/branch/switch/route/build-manifest.json +16 -0
- package/dist/server/.next/server/app/api/branch/switch/route/next-font-manifest.json +6 -0
- package/dist/server/.next/server/app/api/branch/switch/route/react-loadable-manifest.json +1 -0
- package/dist/server/.next/server/app/api/branch/switch/route/server-reference-manifest.json +4 -0
- package/dist/server/.next/server/app/api/branch/switch/route.js +8 -0
- package/dist/server/.next/server/app/api/branch/switch/route.js.map +5 -0
- package/dist/server/.next/server/app/api/branch/switch/route.js.nft.json +1 -0
- package/dist/server/.next/server/app/api/branch/switch/route_client-reference-manifest.js +2 -0
- package/dist/server/.next/server/app/api/branches/route/app-build-manifest.json +10 -0
- package/dist/server/.next/server/app/api/branches/route/app-paths-manifest.json +3 -0
- package/dist/server/.next/server/app/api/branches/route/build-manifest.json +16 -0
- package/dist/server/.next/server/app/api/branches/route/next-font-manifest.json +6 -0
- package/dist/server/.next/server/app/api/branches/route/react-loadable-manifest.json +1 -0
- package/dist/server/.next/server/app/api/branches/route/server-reference-manifest.json +4 -0
- package/dist/server/.next/server/app/api/branches/route.js +8 -0
- package/dist/server/.next/server/app/api/branches/route.js.map +5 -0
- package/dist/server/.next/server/app/api/branches/route.js.nft.json +1 -0
- package/dist/server/.next/server/app/api/branches/route_client-reference-manifest.js +2 -0
- package/dist/server/.next/server/app/api/check-mock-intercept/route.js +1 -1
- package/dist/server/.next/server/app/api/check-mock-intercept/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/check-workspace/route.js +1 -1
- package/dist/server/.next/server/app/api/check-workspace/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/cleanup-mock/route.js +1 -1
- package/dist/server/.next/server/app/api/cleanup-mock/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/delete-mock-api/route.js +1 -1
- package/dist/server/.next/server/app/api/delete-mock-api/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/get-mock-data/route.js +1 -1
- package/dist/server/.next/server/app/api/get-mock-data/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/gwh-git-flow/route.js +1 -1
- package/dist/server/.next/server/app/api/gwh-git-flow/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/initialize-workspace/route.js +1 -1
- package/dist/server/.next/server/app/api/initialize-workspace/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/memory-status/route.js +1 -1
- package/dist/server/.next/server/app/api/memory-status/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-change-stream/route.js +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-change-stream/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-config/route.js +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-config/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/mock-file/route.js +1 -1
- package/dist/server/.next/server/app/api/mock-file/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/mock-file-content/route.js +1 -1
- package/dist/server/.next/server/app/api/mock-file-content/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/mock-open-status/route.js +1 -1
- package/dist/server/.next/server/app/api/mock-open-status/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/mock-setting/route.js +1 -1
- package/dist/server/.next/server/app/api/mock-setting/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/open-all-mock/route.js +1 -1
- package/dist/server/.next/server/app/api/open-all-mock/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/open-project/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/process/start/route.js +1 -1
- package/dist/server/.next/server/app/api/process/start/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/process/status/route.js +1 -1
- package/dist/server/.next/server/app/api/process/status/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/project-config/route.js +1 -1
- package/dist/server/.next/server/app/api/project-config/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/retry-project/route.js +1 -1
- package/dist/server/.next/server/app/api/retry-project/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/submodule-info/route/app-build-manifest.json +10 -0
- package/dist/server/.next/server/app/api/submodule-info/route/app-paths-manifest.json +3 -0
- package/dist/server/.next/server/app/api/submodule-info/route/build-manifest.json +16 -0
- package/dist/server/.next/server/app/api/submodule-info/route/next-font-manifest.json +6 -0
- package/dist/server/.next/server/app/api/submodule-info/route/react-loadable-manifest.json +1 -0
- package/dist/server/.next/server/app/api/submodule-info/route/server-reference-manifest.json +4 -0
- package/dist/server/.next/server/app/api/submodule-info/route.js +8 -0
- package/dist/server/.next/server/app/api/submodule-info/route.js.map +5 -0
- package/dist/server/.next/server/app/api/submodule-info/route.js.nft.json +1 -0
- package/dist/server/.next/server/app/api/submodule-info/route_client-reference-manifest.js +2 -0
- package/dist/server/.next/server/app/api/uat-git-flow/route.js +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/step/route.js +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/step/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/workspace/create/route.js +1 -1
- package/dist/server/.next/server/app/api/workspace/create/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/configuration/page/app-build-manifest.json +3 -3
- package/dist/server/.next/server/app/configuration/page.js.nft.json +1 -1
- package/dist/server/.next/server/app/configuration/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app/configuration.html +1 -1
- package/dist/server/.next/server/app/configuration.rsc +3 -3
- package/dist/server/.next/server/app/index.html +1 -1
- package/dist/server/.next/server/app/index.rsc +2 -2
- package/dist/server/.next/server/app/initialization/page/app-build-manifest.json +3 -3
- package/dist/server/.next/server/app/initialization/page.js.nft.json +1 -1
- package/dist/server/.next/server/app/initialization/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app/initialization.html +1 -1
- package/dist/server/.next/server/app/initialization.rsc +3 -3
- package/dist/server/.next/server/app/page/app-build-manifest.json +1 -1
- package/dist/server/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app-paths-manifest.json +7 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__dda45cac._.js → [root-of-the-server]__061fab1d._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__dda45cac._.js.map → [root-of-the-server]__061fab1d._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__4ec3205b._.js → [root-of-the-server]__09313e5e._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__4ec3205b._.js.map → [root-of-the-server]__09313e5e._.js.map} +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__0c170d21._.js +3 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__0c170d21._.js.map +1 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__139ed483._.js +3 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__139ed483._.js.map +1 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__37bfbf6b._.js → [root-of-the-server]__1ebda8c2._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__37bfbf6b._.js.map → [root-of-the-server]__1ebda8c2._.js.map} +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__326fc423._.js +3 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__2a78acef._.js.map → [root-of-the-server]__326fc423._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__ec681197._.js → [root-of-the-server]__32f4379a._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__ec681197._.js.map → [root-of-the-server]__32f4379a._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__e0b7050d._.js → [root-of-the-server]__36b796c6._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__e0b7050d._.js.map → [root-of-the-server]__36b796c6._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__2f8b52da._.js → [root-of-the-server]__3987d53e._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__2f8b52da._.js.map → [root-of-the-server]__3987d53e._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__9e44bbc8._.js → [root-of-the-server]__3f941970._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__9e44bbc8._.js.map → [root-of-the-server]__3f941970._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__d3078133._.js → [root-of-the-server]__5a926dad._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__d3078133._.js.map → [root-of-the-server]__5a926dad._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__0d56f35b._.js → [root-of-the-server]__5d6739e4._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__0d56f35b._.js.map → [root-of-the-server]__5d6739e4._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__3952b86e._.js → [root-of-the-server]__6004758a._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__3952b86e._.js.map → [root-of-the-server]__6004758a._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__54f2f032._.js → [root-of-the-server]__6496ee9b._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__54f2f032._.js.map → [root-of-the-server]__6496ee9b._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__c18498ef._.js → [root-of-the-server]__66952f53._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__c18498ef._.js.map → [root-of-the-server]__66952f53._.js.map} +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__6bf6dd19._.js +3 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__6bf6dd19._.js.map +1 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__6c7b8215._.js +3 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__6c7b8215._.js.map +1 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__4fd52ac1._.js → [root-of-the-server]__72882dad._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__4fd52ac1._.js.map → [root-of-the-server]__72882dad._.js.map} +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__77a38b01._.js +16 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__77a38b01._.js.map +1 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__5c9f62f9._.js → [root-of-the-server]__7f6ec3b4._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__5c9f62f9._.js.map → [root-of-the-server]__7f6ec3b4._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__2ffbf0d3._.js → [root-of-the-server]__86c123b3._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__2ffbf0d3._.js.map → [root-of-the-server]__86c123b3._.js.map} +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__8713ccda._.js +16 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__8713ccda._.js.map +1 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__0e8a08fc._.js → [root-of-the-server]__9d9f55dd._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__0e8a08fc._.js.map → [root-of-the-server]__9d9f55dd._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__452b5f9c._.js → [root-of-the-server]__a75af746._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__452b5f9c._.js.map → [root-of-the-server]__a75af746._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__0879b2d6._.js → [root-of-the-server]__ae9fe9b7._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__0879b2d6._.js.map → [root-of-the-server]__ae9fe9b7._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__2a29597f._.js → [root-of-the-server]__b49d8c86._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__2a29597f._.js.map → [root-of-the-server]__b49d8c86._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__c43cf810._.js → [root-of-the-server]__b96ce42e._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__c43cf810._.js.map → [root-of-the-server]__b96ce42e._.js.map} +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__c52380bc._.js +3 -0
- package/dist/server/.next/server/chunks/[root-of-the-server]__c52380bc._.js.map +1 -0
- package/dist/server/.next/server/chunks/{[root-of-the-server]__8637b7f1._.js → [root-of-the-server]__e2654a76._.js} +2 -2
- package/dist/server/.next/server/chunks/{[root-of-the-server]__8637b7f1._.js.map → [root-of-the-server]__e2654a76._.js.map} +1 -1
- package/dist/server/.next/server/chunks/{[root-of-the-server]__4b595942._.js → [root-of-the-server]__e96f0857._.js} +2 -2
- package/dist/server/.next/server/chunks/ssr/{_a1ab1c09._.js → _283bdc73._.js} +2 -2
- package/dist/server/.next/server/chunks/ssr/_283bdc73._.js.map +1 -0
- package/dist/server/.next/server/chunks/ssr/_89496b8a._.js +1 -1
- package/dist/server/.next/server/chunks/ssr/_89496b8a._.js.map +1 -1
- package/dist/server/.next/server/chunks/ssr/_9f432559._.js +1 -1
- package/dist/server/.next/server/chunks/ssr/_9f432559._.js.map +1 -1
- package/dist/server/.next/server/chunks/ssr/{_ee0c9da0._.js → _c7905e3c._.js} +2 -2
- package/dist/server/.next/server/chunks/ssr/_c7905e3c._.js.map +1 -0
- package/dist/server/.next/server/chunks/ssr/packages_server_src_65e3de99._.js +3 -0
- package/dist/server/.next/server/chunks/ssr/packages_server_src_65e3de99._.js.map +1 -0
- package/dist/server/.next/server/middleware-build-manifest.js +4 -4
- package/dist/server/.next/server/pages/404.html +1 -1
- package/dist/server/.next/server/pages/500.html +1 -1
- package/dist/server/.next/server/pages/_app/build-manifest.json +2 -2
- package/dist/server/.next/server/pages/_error/build-manifest.json +2 -2
- package/dist/server/.next/server/server-reference-manifest.js +1 -1
- package/dist/server/.next/server/server-reference-manifest.json +1 -1
- package/dist/server/.next/static/chunks/{923f67dbd9f9897e.js → 063f4e9959195b1d.js} +3 -3
- package/dist/server/.next/static/chunks/09cba5d1f6b48977.js.map +1 -0
- package/dist/server/.next/static/chunks/{aa6cbf0011bc69d5.js → 0c6009607901038e.js} +2 -2
- package/dist/server/.next/{server/chunks/ssr/_ee0c9da0._.js.map → static/chunks/0e959ec3ce9fc799.js.map} +1 -1
- package/dist/server/.next/static/chunks/1427afaf93da978b.css +3 -0
- package/dist/server/.next/static/chunks/{9148331cad3a934e.js → 45543bd9f83f509f.js} +2 -2
- package/dist/server/.next/static/chunks/4608598ca6cc0991.js.map +1 -0
- package/dist/server/.next/static/chunks/{43c514797c454939.js → 4c54a6f1b63a5c72.js} +2 -2
- package/dist/server/.next/static/chunks/{b18e8b227375accd.js.map → 6a92a3cb924fd124.js.map} +1 -1
- package/dist/server/.next/{server/chunks/ssr/_a1ab1c09._.js.map → static/chunks/8e1056102ab0be45.js.map} +1 -1
- package/dist/server/.next/static/chunks/{8ade09a4b436cb9d.js → 9793bc87a71ec278.js} +2 -2
- package/dist/server/.next/static/chunks/{cf8cd3228a692db3.js → dad6616f7b6f4060.js} +1 -1
- package/dist/server/.next/static/chunks/e0fb1a1f78246e35.css.map +1 -0
- package/dist/server/.next/static/chunks/fce82d5fa17f0367.js +3 -0
- package/dist/server/.next/static/chunks/pages/_app.js +2 -2
- package/dist/server/.next/static/chunks/pages/_error.js +2 -2
- package/dist/server/.next/trace +2 -2
- package/package.json +1 -1
- package/dist/server/.next/server/chunks/[root-of-the-server]__2a78acef._.js +0 -3
- package/dist/server/.next/server/chunks/ssr/packages_server_src_7cef6dbd._.js +0 -3
- package/dist/server/.next/server/chunks/ssr/packages_server_src_7cef6dbd._.js.map +0 -1
- package/dist/server/.next/static/chunks/3dc9d6a79fb35214.js.map +0 -1
- package/dist/server/.next/static/chunks/45e30917848bc72f.js +0 -3
- package/dist/server/.next/static/chunks/4738c58ccb7b92a0.js.map +0 -1
- package/dist/server/.next/static/chunks/5ae25dc5b211a319.css +0 -3
- package/dist/server/.next/static/chunks/888146b3e75fe817.js.map +0 -1
- package/dist/server/.next/static/chunks/d10e7ab50988a39e.css.map +0 -1
- package/dist/server/.next/static/chunks/e70508cc9f59709d.js.map +0 -1
- /package/dist/server/.next/server/chunks/{[root-of-the-server]__4b595942._.js.map → [root-of-the-server]__e96f0857._.js.map} +0 -0
- /package/dist/server/.next/static/{CSWsqwtWCRONg1gSmV6NV → TtpaZZwrnzkXloBpwEr24}/_buildManifest.js +0 -0
- /package/dist/server/.next/static/{CSWsqwtWCRONg1gSmV6NV → TtpaZZwrnzkXloBpwEr24}/_clientMiddlewareManifest.json +0 -0
- /package/dist/server/.next/static/{CSWsqwtWCRONg1gSmV6NV → TtpaZZwrnzkXloBpwEr24}/_ssgManifest.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
module.exports={
|
|
1
|
+
module.exports={45935:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},30331:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("path",()=>require("path"))},29549:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},83943:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},86103:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},23430:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},52670:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js"))},13442:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("os",()=>require("os"))},88941:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({PROJECT_CONFIG_PATH:()=>t,ProjectStatus:()=>s,WORKSPACE_CONFIG:()=>r});var o=e.i(13442),n=e.i(30331);let r={WORKSPACE_ROOT:(0,n.join)((0,o.homedir)(),"Documents","prime-workspace"),GIT_TIMEOUT:3e5,MAX_CONCURRENT_CLONES:Math.max(2,Math.min((0,o.cpus)().length,8)),MAX_RETRY_ATTEMPTS:3},t=(0,n.join)((0,o.homedir)(),".prime-projects.json");var s=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e.INCOMPLETE="incomplete",e}({})}},83886:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("fs",()=>require("fs"))},9892:function(e){var{g:r,__dirname:t,m:o,e:n}=e;o.exports=e.x("fs/promises",()=>require("fs/promises"))},35692:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({ProjectStatus:()=>c,getProjectsConfig:()=>s,saveProjectsConfig:()=>i});var o=e.i(9892),n=e.i(88941);async function s(){try{await (0,o.access)(n.PROJECT_CONFIG_PATH,o.constants.F_OK)}catch{return await i({}),{}}try{let e=await (0,o.readFile)(n.PROJECT_CONFIG_PATH,"utf-8");if(!e)return{};return JSON.parse(e)}catch(e){throw console.error("读取或解析项目配置文件失败:",e),Error("无法加载项目配置")}}async function i(e){let r=n.PROJECT_CONFIG_PATH+".tmp";try{await (0,o.writeFile)(r,JSON.stringify(e,null,2),"utf-8"),await (0,o.rename)(r,n.PROJECT_CONFIG_PATH)}catch(e){throw console.error("保存项目配置文件失败:",e),Error("无法保存项目配置")}}var c=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e}({})},94722:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({sseConnectionManager:()=>t});class r{connections=new Map;encoder=new TextEncoder;heartbeatInterval=null;HEARTBEAT_INTERVAL=3e4;CONNECTION_TIMEOUT=12e4;MAX_CONNECTIONS_PER_ENV=10;constructor(){this.startHeartbeat()}clearAllConnections(){console.log("[SSE] 开始清理所有连接...");let e=Array.from(this.connections.values()).reduce((e,r)=>e+r.size,0);this.connections.forEach(e=>{e.forEach(e=>{try{e.controller.close()}catch{}})}),this.connections.clear(),console.log(`[SSE] 已清理 ${e} 个连接`)}addConnection(e,r,t){console.log(`[SSE] 添加连接: 环境=${e}, 客户端=${t}`),this.connections.has(e)||this.connections.set(e,new Set);let o=this.connections.get(e);if(o.size>=this.MAX_CONNECTIONS_PER_ENV){console.warn(`[SSE] 环境 ${e} 连接数已达上限,清理最旧的连接`);let r=Array.from(o).sort((e,r)=>e.timestamp-r.timestamp)[0];if(r){try{r.controller.close()}catch{}o.delete(r)}}let n={controller:r,timestamp:Date.now(),clientId:t,envName:e};o.add(n),this.sendToConnection(n,{type:"heartbeat",timestamp:Date.now()}),console.log(`[SSE] 当前连接统计: ${this.getConnectionStats()}`)}removeConnection(e,r){console.log(`[SSE] 移除连接: 环境=${e}, 客户端=${r}`);let t=this.connections.get(e);if(t){let o=Array.from(t).find(e=>e.clientId===r);o&&(t.delete(o),0===t.size&&this.connections.delete(e))}console.log(`[SSE] 当前连接统计: ${this.getConnectionStats()}`)}broadcastToEnv(e,r){console.log(`[SSE] 向环境 ${e} 广播配置变化消息`);let t=this.connections.get(e);if(!t||0===t.size)return void console.log(`[SSE] 环境 ${e} 没有活跃连接,跳过广播`);let o=[];t.forEach(e=>{try{this.sendToConnection(e,r)}catch(r){console.error(`[SSE] 发送消息到客户端 ${e.clientId} 失败:`,r),o.push(e)}}),o.forEach(e=>{t.delete(e),console.log(`[SSE] 清理无效连接: 客户端=${e.clientId}`)}),console.log(`[SSE] 成功发送给 ${t.size} 个连接`)}sendToConnection(e,r){let t=`data: ${JSON.stringify(r)}
|
|
2
2
|
|
|
3
3
|
`,o=this.encoder.encode(t);try{e.controller.enqueue(o),e.timestamp=Date.now()}catch(e){throw console.error(`[SSE] 发送消息失败:`,e),e}}startHeartbeat(){this.heartbeatInterval=setInterval(()=>{this.sendHeartbeat(),this.cleanupStaleConnections()},this.HEARTBEAT_INTERVAL),console.log(`[SSE] 心跳机制已启动,间隔: ${this.HEARTBEAT_INTERVAL}ms`)}sendHeartbeat(){let e={type:"heartbeat",timestamp:Date.now()},r=0;this.connections.forEach(t=>{r+=t.size;let o=[];t.forEach(r=>{try{this.sendToConnection(r,e)}catch{o.push(r)}}),o.forEach(e=>t.delete(e))}),r>0&&console.log(`[SSE] 心跳发送完成,活跃连接数: ${r}`)}cleanupStaleConnections(){let e=Date.now(),r=0;this.connections.forEach((t,o)=>{let n=[];t.forEach(r=>{e-r.timestamp>this.CONNECTION_TIMEOUT&&n.push(r)}),n.forEach(e=>{t.delete(e),r++,console.log(`[SSE] 清理过期连接: 环境=${o}, 客户端=${e.clientId}`)}),0===t.size&&this.connections.delete(o)}),r>0&&console.log(`[SSE] 连接清理完成,清理数量: ${r}`)}getConnectionStats(){let e=[],r=0;return this.connections.forEach((t,o)=>{let n=t.size;r+=n,e.push(`${o}: ${n}`)}),`总计 ${r} 个连接 (${e.join(", ")})`}stop(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null,console.log(`[SSE] 心跳机制已停止`)),this.connections.forEach(e=>{e.forEach(e=>{try{e.controller.close()}catch(e){console.error(`[SSE] 关闭连接失败:`,e)}})}),this.connections.clear(),console.log(`[SSE] 所有连接已关闭`)}}let t=new r;process.on("SIGINT",()=>{console.log("[SSE] 收到退出信号,正在清理连接..."),t.stop(),process.exit(0)}),process.on("SIGTERM",()=>{console.log("[SSE] 收到终止信号,正在清理连接..."),t.stop(),process.exit(0)})}},50948:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({PRIME_PROXY_PREFIX_MAP_KEY:()=>r,PRIME_PROXY_REWRITE_MAP_KEY:()=>t,buildEnvFileContent:()=>c,deriveProxyKey:()=>n,normalizeApiProxyItem:()=>i,normalizePrefix:()=>o,validateApiProxies:()=>s});let r="PRIME_PROXY_PREFIX_MAP",t="PRIME_PROXY_REWRITE_MAP";function o(e){let r=e.trim();return r.startsWith("/")&&r.length>1?r.replace(/\/+$/,""):r}function n(e,r){if(r&&r.trim())return r.trim();let t=o(e);if("/api"===t)return"PROXY_URL";let n=t.replace(/^\//,"").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"").toUpperCase();return`PROXY_${n}_URL`}function s(e){if(!Array.isArray(e)||0===e.length)return{valid:!1,error:"apiProxies 不能为空"};let r=new Set;for(let t of e){let e=function(e){if(!e||!e.trim())return"prefix 不能为空";let r=o(e);return r.startsWith("/")?/\s/.test(r)?`prefix ${e} 不能包含空白字符`:null:`prefix ${e} 必须以 / 开头`}(t.prefix);if(e)return{valid:!1,error:e};let n=o(t.prefix);if(r.has(n))return{valid:!1,error:`prefix ${n} 重复`};if(r.add(n),!t.currentProxy||!t.currentProxy.trim())return{valid:!1,error:`prefix ${n} 缺少 currentProxy`};if(!t.proxyEnv||"object"!=typeof t.proxyEnv)return{valid:!1,error:`prefix ${n} 缺少 proxyEnv`};let s=t.proxyEnv[t.currentProxy];if("string"!=typeof s)return{valid:!1,error:`prefix ${n} 的 currentProxy 不存在于 proxyEnv 中`};if("custom"===t.currentProxy&&!s.trim())return{valid:!1,error:`prefix ${n} 选择 custom 时必须提供 URL`};if(!s.trim())return{valid:!1,error:`prefix ${n} 的 currentProxy URL 不能为空`};let i=function(e,r){if(!e.rewrite)return null;let{mode:t,targetPrefix:o}=e.rewrite;if(!["none","remove","replace"].includes(t))return`prefix ${r} 的 rewrite.mode 仅支持 none/remove/replace`;let n="string"==typeof o&&o.length>0;if("remove"===t&&n)return`prefix ${r} 的 rewrite.mode 为 remove 时不允许 targetPrefix`;if("replace"===t){let e=(o||"").trim();if(!e||!e.startsWith("/")||/\s/.test(e))return`prefix ${r} 的 rewrite.mode 为 replace 时 targetPrefix 必须以 / 开头且不能包含空白字符`}return null}(t,n);if(i)return{valid:!1,error:i}}return{valid:!0}}function i(e){let r=o(e.prefix),t=e.rewrite;return t&&(t="replace"===t.mode?{mode:"replace",targetPrefix:(t.targetPrefix||"").trim().replace(/\/+$/,"")||"/"}:"remove"===t.mode?{mode:"remove"}:{mode:"none"}),{...e,prefix:r,rewrite:t,proxyKey:n(r,e.proxyKey)}}function c(e){let o=s(e);if(!o.valid)return{error:o.error};let n=e.map(i),c=n.reduce((e,r)=>(e[r.prefix]=r.proxyKey,e),{}),a=n.reduce((e,r)=>(r.rewrite&&"none"!==r.rewrite.mode&&("remove"===r.rewrite.mode?e[r.prefix]="":"replace"===r.rewrite.mode&&(e[r.prefix]=r.rewrite.targetPrefix)),e),{});return{content:[`${r}=${JSON.stringify(c)}`,...Object.keys(a).length>0?[`${t}=${JSON.stringify(a)}`]:[],...n.map(e=>`${e.proxyKey}=${e.proxyEnv[e.currentProxy].trim()}`)].join("\n")}}}},15079:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({createProjectEnvFiles:()=>i,createProjectMockDirectories:()=>c,updateProjectEnvFile:()=>a});var o=e.i(83886),n=e.i(30331),s=e.i(50948);async function i(e,r,t){let i=(0,n.join)(t,e),c=[],a=[];try{await o.promises.mkdir(i,{recursive:!0});let e=r.envs||{};for(let r in e){let t=e[r];if(t.envFileName&&t.apiProxies?.length){let e=(0,n.join)(i,t.envFileName);try{await o.promises.access(e),a.push(t.envFileName)}catch{let n=(0,s.buildEnvFileContent)(t.apiProxies);if("error"in n)return{success:!1,createdFiles:c,skippedFiles:a,error:`环境 ${r} 配置无效: ${n.error}`};await o.promises.writeFile(e,n.content,"utf-8"),c.push(t.envFileName)}}}return{success:!0,createdFiles:c,skippedFiles:a}}catch(t){let r=t instanceof Error?t.message:String(t);return console.error(`在为项目 ${e} 创建环境文件时出错:`,t),{success:!1,createdFiles:c,skippedFiles:a,error:r}}}async function c(e,r){let t=(0,n.join)(r,e),s=(0,n.join)(t,".mock"),i=[],c=[];try{try{await o.promises.access(s),c.push(".mock")}catch{await o.promises.mkdir(s,{recursive:!0}),i.push(".mock")}return{success:!0,createdDirectories:i,skippedDirectories:c}}catch(t){let r=t instanceof Error?t.message:String(t);return console.error(`在为项目 ${e} 创建Mock目录时出错:`,t),{success:!1,createdDirectories:i,skippedDirectories:c,error:r}}}async function a(e,r,t,i){try{let c=t.envs[r];if(!c)return{success:!1,error:`环境 ${r} 不存在于项目 ${e} 配置中`};if(!c.envFileName||!c.apiProxies?.length)return{success:!1,error:`环境 ${r} 缺少 envFileName 或 apiProxies 配置`};let a=(0,s.buildEnvFileContent)(c.apiProxies);if("error"in a)return{success:!1,error:a.error};let l=(0,n.join)(i,e),p=(0,n.join)(l,c.envFileName);return await o.promises.writeFile(p,a.content,"utf-8"),console.log(`已更新环境文件: ${p}, 内容: ${a.content}`),{success:!0,updatedFile:c.envFileName}}catch(o){let t=o instanceof Error?o.message:String(o);return console.error(`更新项目 ${e} 环境 ${r} 的环境文件时出错:`,o),{success:!1,error:t}}}},57606:function(e){var{g:r,__dirname:t,m:o,e:n}=e},67375:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({PUT:()=>a});var o=e.i(15494),n=e.i(35692),s=e.i(15079),i=e.i(88941),c=e.i(94722);async function a(e){try{let{envName:r,projectName:t,selectedItems:a}=await e.json();if(!r||!t||!Array.isArray(a))return o.NextResponse.json({success:!1,error:"缺少必要参数:envName, projectName, selectedItems"},{status:400});let l=await (0,n.getProjectsConfig)();if(!l[t])return o.NextResponse.json({success:!1,error:`项目 ${t} 不存在`},{status:404});if(!l[t].envs[r])return o.NextResponse.json({success:!1,error:`项目 ${t} 中不存在环境 ${r}`},{status:404});let p=l[t].envs[r].host,u=l[t].envs[r].subApps||[];l[t].envs[r].subApps=a;let f=[];if(a.forEach(e=>{Object.keys(l).forEach(r=>{if(l[r].envs[e]){let t=l[r].envs[e],o=t.apiProxies?.find(e=>"/api"===e.prefix);o&&(o.currentProxy="custom",o.proxyEnv.custom=p),f.push({projectName:r,envName:e})}})}),await (0,n.saveProjectsConfig)(l),JSON.stringify(u.sort())!==JSON.stringify(a.sort())){console.log(`[配置变化] 环境 ${r} 的 MicroApp 代理配置发生变化`),console.log(`[配置变化] 变化前: ${JSON.stringify(u)}`),console.log(`[配置变化] 变化后: ${JSON.stringify(a)}`);let e=new Set(u),o=new Set(a),n=a.filter(r=>!e.has(r)),s=u.filter(e=>!o.has(e)),i={type:"microapp-proxy-config-change",envName:r,timestamp:Date.now(),changes:{before:u,after:a,added:n,removed:s},projectName:t,message:`环境 ${r} 的 MicroApp 代理配置已更新`};try{c.sseConnectionManager.broadcastToEnv(r,i),console.log(`[推送成功] 已向环境 ${r} 推送配置变化通知`)}catch(e){console.error(`[推送失败] 向环境 ${r} 推送通知失败:`,e)}}else console.log(`[配置未变化] 环境 ${r} 的 MicroApp 代理配置无变化,跳过推送`);let m=(await Promise.allSettled(f.map(async({projectName:e,envName:r})=>(0,s.updateProjectEnvFile)(e,r,l[e],i.WORKSPACE_CONFIG.WORKSPACE_ROOT)))).map((e,r)=>({result:e,project:f[r]})).filter(({result:e})=>"rejected"===e.status||"fulfilled"===e.status&&!e.value.success),d="MicroApp代理配置保存成功,已更新选中环境的代理地址";return m.length>0&&(d+=`,但有 ${m.length} 个环境文件更新失败`),o.NextResponse.json({success:!0,message:d,data:{projectName:t,envName:r,subApps:a,currentHost:p,updatedProjects:f.length,envFileUpdateFailures:m.length}})}catch(r){let e=r instanceof Error?r.message:"保存MicroApp代理配置失败";return console.error("保存MicroApp代理配置失败:",r),o.NextResponse.json({success:!1,error:e},{status:500})}}},30280:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({patchFetch:()=>c,routeModule:()=>r,serverHooks:()=>l,workAsyncStorage:()=>t,workUnitAsyncStorage:()=>a});var o=e.i(45746),n=e.i(93828),s=e.i(18250),i=e.i(67375);let r=new o.AppRouteRouteModule({definition:{kind:n.RouteKind.APP_ROUTE,page:"/api/microapp-proxy-config/route",pathname:"/api/microapp-proxy-config",filename:"route",bundlePath:""},resolvedPagePath:"[project]/packages/server/src/app/api/microapp-proxy-config/route.ts",nextConfigOutput:"",userland:i}),{workAsyncStorage:t,workUnitAsyncStorage:a,serverHooks:l}=r;function c(){return(0,s.patchFetch)({workAsyncStorage:t,workUnitAsyncStorage:a})}}}};
|
|
4
4
|
|
|
5
|
-
//# sourceMappingURL=%5Broot-of-the-server%
|
|
5
|
+
//# sourceMappingURL=%5Broot-of-the-server%5D__b96ce42e._.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/sse-connection-manager.ts","turbopack:///[project]/packages/server/src/lib/api-proxy.ts","turbopack:///[project]/packages/server/src/lib/env-file-operations.ts","turbopack:///[project]/packages/server/src/app/api/microapp-proxy-config/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: string;\n /**\n * 微应用路径标识:用于在共享宿主(micro-app 域名)下区分兄弟子应用。\n * 插件按 micro-app 元素的 default-page / url 是否“包含”该值来选中对应本地 host。\n * 例如 micro-components 为 \"/micro/components\"、360-icrc-site 为 \"/micro/360-icrc-site\"。\n */\n microPath?: string;\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n}\n","import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","/**\n * SSE连接管理器\n * 用于管理MicroApp代理配置变化推送的SSE连接\n */\n\nexport interface ConnectionInfo {\n controller: ReadableStreamDefaultController<Uint8Array>;\n timestamp: number;\n clientId: string;\n envName: string;\n}\n\nexport interface ConfigChangeMessage {\n type: 'microapp-proxy-config-change';\n envName: string;\n timestamp: number;\n changes: {\n before: string[];\n after: string[];\n added: string[];\n removed: string[];\n };\n projectName: string;\n message: string;\n}\n\nexport interface HeartbeatMessage {\n type: 'heartbeat';\n timestamp: number;\n}\n\ntype SSEMessage = ConfigChangeMessage | HeartbeatMessage;\n\n/**\n * SSE连接管理器类\n */\nclass SSEConnectionManager {\n private connections = new Map<string, Set<ConnectionInfo>>();\n private encoder = new TextEncoder();\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private readonly HEARTBEAT_INTERVAL = 30000; // 30秒心跳\n private readonly CONNECTION_TIMEOUT = 120000; // 2分钟连接超时\n private readonly MAX_CONNECTIONS_PER_ENV = 10; // 每个环境最多10个连接\n\n constructor() {\n this.startHeartbeat();\n }\n \n /**\n * 清理所有连接(用于内存清理)\n */\n clearAllConnections(): void {\n console.log('[SSE] 开始清理所有连接...');\n const totalConnections = Array.from(this.connections.values()).reduce((sum, set) => sum + set.size, 0);\n \n this.connections.forEach((connections) => {\n connections.forEach(conn => {\n try {\n conn.controller.close();\n } catch {\n // 忽略关闭错误\n }\n });\n });\n \n this.connections.clear();\n console.log(`[SSE] 已清理 ${totalConnections} 个连接`);\n }\n\n /**\n * 添加新的SSE连接\n */\n addConnection(envName: string, controller: ReadableStreamDefaultController<Uint8Array>, clientId: string): void {\n console.log(`[SSE] 添加连接: 环境=${envName}, 客户端=${clientId}`);\n \n if (!this.connections.has(envName)) {\n this.connections.set(envName, new Set());\n }\n \n const connections = this.connections.get(envName)!;\n \n // 检查连接数限制\n if (connections.size >= this.MAX_CONNECTIONS_PER_ENV) {\n console.warn(`[SSE] 环境 ${envName} 连接数已达上限,清理最旧的连接`);\n // 找到最旧的连接并关闭\n const oldestConn = Array.from(connections).sort((a, b) => a.timestamp - b.timestamp)[0];\n if (oldestConn) {\n try {\n oldestConn.controller.close();\n } catch {\n // 忽略关闭错误\n }\n connections.delete(oldestConn);\n }\n }\n \n const connectionInfo: ConnectionInfo = {\n controller,\n timestamp: Date.now(),\n clientId,\n envName,\n };\n \n connections.add(connectionInfo);\n \n // 发送连接确认消息\n this.sendToConnection(connectionInfo, {\n type: 'heartbeat',\n timestamp: Date.now(),\n });\n\n console.log(`[SSE] 当前连接统计: ${this.getConnectionStats()}`);\n }\n\n /**\n * 移除SSE连接\n */\n removeConnection(envName: string, clientId: string): void {\n console.log(`[SSE] 移除连接: 环境=${envName}, 客户端=${clientId}`);\n \n const connections = this.connections.get(envName);\n if (connections) {\n const connectionToRemove = Array.from(connections).find(conn => conn.clientId === clientId);\n if (connectionToRemove) {\n connections.delete(connectionToRemove);\n \n // 如果该环境没有连接了,删除整个entry\n if (connections.size === 0) {\n this.connections.delete(envName);\n }\n }\n }\n\n console.log(`[SSE] 当前连接统计: ${this.getConnectionStats()}`);\n }\n\n /**\n * 向指定环境广播消息\n */\n broadcastToEnv(envName: string, message: ConfigChangeMessage): void {\n console.log(`[SSE] 向环境 ${envName} 广播配置变化消息`);\n \n const connections = this.connections.get(envName);\n if (!connections || connections.size === 0) {\n console.log(`[SSE] 环境 ${envName} 没有活跃连接,跳过广播`);\n return;\n }\n\n const deadConnections: ConnectionInfo[] = [];\n \n connections.forEach(connectionInfo => {\n try {\n this.sendToConnection(connectionInfo, message);\n } catch (error) {\n console.error(`[SSE] 发送消息到客户端 ${connectionInfo.clientId} 失败:`, error);\n deadConnections.push(connectionInfo);\n }\n });\n\n // 清理无效连接\n deadConnections.forEach(conn => {\n connections.delete(conn);\n console.log(`[SSE] 清理无效连接: 客户端=${conn.clientId}`);\n });\n\n console.log(`[SSE] 成功发送给 ${connections.size} 个连接`);\n }\n\n /**\n * 向单个连接发送消息\n */\n private sendToConnection(connectionInfo: ConnectionInfo, message: SSEMessage): void {\n const data = `data: ${JSON.stringify(message)}\\n\\n`;\n const encodedData = this.encoder.encode(data);\n \n try {\n connectionInfo.controller.enqueue(encodedData);\n connectionInfo.timestamp = Date.now(); // 更新最后活跃时间\n } catch (error) {\n console.error(`[SSE] 发送消息失败:`, error);\n throw error;\n }\n }\n\n /**\n * 启动心跳机制\n */\n private startHeartbeat(): void {\n this.heartbeatInterval = setInterval(() => {\n this.sendHeartbeat();\n this.cleanupStaleConnections();\n }, this.HEARTBEAT_INTERVAL);\n \n console.log(`[SSE] 心跳机制已启动,间隔: ${this.HEARTBEAT_INTERVAL}ms`);\n }\n\n /**\n * 发送心跳消息\n */\n private sendHeartbeat(): void {\n const heartbeatMessage: HeartbeatMessage = {\n type: 'heartbeat',\n timestamp: Date.now(),\n };\n\n let totalConnections = 0;\n this.connections.forEach((connections) => {\n totalConnections += connections.size;\n const deadConnections: ConnectionInfo[] = [];\n \n connections.forEach(connectionInfo => {\n try {\n this.sendToConnection(connectionInfo, heartbeatMessage);\n } catch {\n deadConnections.push(connectionInfo);\n }\n });\n\n // 清理无效连接\n deadConnections.forEach(conn => connections.delete(conn));\n });\n\n if (totalConnections > 0) {\n console.log(`[SSE] 心跳发送完成,活跃连接数: ${totalConnections}`);\n }\n }\n\n /**\n * 清理过期连接\n */\n private cleanupStaleConnections(): void {\n const now = Date.now();\n let cleanedCount = 0;\n\n this.connections.forEach((connections, envName) => {\n const staleConnections: ConnectionInfo[] = [];\n \n connections.forEach(connectionInfo => {\n if (now - connectionInfo.timestamp > this.CONNECTION_TIMEOUT) {\n staleConnections.push(connectionInfo);\n }\n });\n\n staleConnections.forEach(conn => {\n connections.delete(conn);\n cleanedCount++;\n console.log(`[SSE] 清理过期连接: 环境=${envName}, 客户端=${conn.clientId}`);\n });\n\n // 如果该环境没有连接了,删除整个entry\n if (connections.size === 0) {\n this.connections.delete(envName);\n }\n });\n\n if (cleanedCount > 0) {\n console.log(`[SSE] 连接清理完成,清理数量: ${cleanedCount}`);\n }\n }\n\n /**\n * 获取连接统计信息\n */\n getConnectionStats(): string {\n const stats: string[] = [];\n let totalConnections = 0;\n \n this.connections.forEach((connections, envName) => {\n const count = connections.size;\n totalConnections += count;\n stats.push(`${envName}: ${count}`);\n });\n\n return `总计 ${totalConnections} 个连接 (${stats.join(', ')})`;\n }\n\n /**\n * 停止连接管理器\n */\n stop(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n console.log(`[SSE] 心跳机制已停止`);\n }\n\n // 关闭所有连接\n this.connections.forEach((connections) => {\n connections.forEach(connectionInfo => {\n try {\n connectionInfo.controller.close();\n } catch (error) {\n console.error(`[SSE] 关闭连接失败:`, error);\n }\n });\n });\n\n this.connections.clear();\n console.log(`[SSE] 所有连接已关闭`);\n }\n}\n\n// 创建全局实例\nexport const sseConnectionManager = new SSEConnectionManager();\n\n// 在进程退出时清理资源\nprocess.on('SIGINT', () => {\n console.log('[SSE] 收到退出信号,正在清理连接...');\n sseConnectionManager.stop();\n process.exit(0);\n});\n\nprocess.on('SIGTERM', () => {\n console.log('[SSE] 收到终止信号,正在清理连接...');\n sseConnectionManager.stop();\n process.exit(0);\n}); ","import type { ApiProxyItem } from './workspace-types';\n\nexport const PRIME_PROXY_PREFIX_MAP_KEY = 'PRIME_PROXY_PREFIX_MAP';\nexport const PRIME_PROXY_REWRITE_MAP_KEY = 'PRIME_PROXY_REWRITE_MAP';\n\nexport function normalizePrefix(prefix: string): string {\n const trimmed = prefix.trim();\n if (!trimmed.startsWith('/')) {\n return trimmed;\n }\n if (trimmed.length > 1) {\n return trimmed.replace(/\\/+$/, '');\n }\n return trimmed;\n}\n\nfunction toProxyName(prefix: string): string {\n return prefix\n .replace(/^\\//, '')\n .replace(/[^a-zA-Z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .toUpperCase();\n}\n\nexport function deriveProxyKey(prefix: string, proxyKey?: string): string {\n if (proxyKey && proxyKey.trim()) {\n return proxyKey.trim();\n }\n\n const normalizedPrefix = normalizePrefix(prefix);\n if (normalizedPrefix === '/api') {\n return 'PROXY_URL';\n }\n\n const proxyName = toProxyName(normalizedPrefix);\n return `PROXY_${proxyName}_URL`;\n}\n\nfunction validatePrefix(prefix: string): string | null {\n if (!prefix || !prefix.trim()) {\n return 'prefix 不能为空';\n }\n\n const normalizedPrefix = normalizePrefix(prefix);\n if (!normalizedPrefix.startsWith('/')) {\n return `prefix ${prefix} 必须以 / 开头`;\n }\n\n if (/\\s/.test(normalizedPrefix)) {\n return `prefix ${prefix} 不能包含空白字符`;\n }\n\n return null;\n}\n\nfunction validateRewrite(item: ApiProxyItem, normalizedPrefix: string): string | null {\n if (!item.rewrite) {\n return null;\n }\n\n const { mode, targetPrefix } = item.rewrite;\n\n if (!['none', 'remove', 'replace'].includes(mode)) {\n return `prefix ${normalizedPrefix} 的 rewrite.mode 仅支持 none/remove/replace`;\n }\n\n const hasTargetPrefix = typeof targetPrefix === 'string' && targetPrefix.length > 0;\n\n if (mode === 'remove' && hasTargetPrefix) {\n return `prefix ${normalizedPrefix} 的 rewrite.mode 为 remove 时不允许 targetPrefix`;\n }\n\n if (mode === 'replace') {\n const normalizedTargetPrefix = (targetPrefix || '').trim();\n if (!normalizedTargetPrefix || !normalizedTargetPrefix.startsWith('/') || /\\s/.test(normalizedTargetPrefix)) {\n return `prefix ${normalizedPrefix} 的 rewrite.mode 为 replace 时 targetPrefix 必须以 / 开头且不能包含空白字符`;\n }\n }\n\n return null;\n}\n\nexport function validateApiProxies(apiProxies: ApiProxyItem[]): { valid: true } | { valid: false; error: string } {\n if (!Array.isArray(apiProxies) || apiProxies.length === 0) {\n return { valid: false, error: 'apiProxies 不能为空' };\n }\n\n const seen = new Set<string>();\n\n for (const item of apiProxies) {\n const prefixError = validatePrefix(item.prefix);\n if (prefixError) {\n return { valid: false, error: prefixError };\n }\n\n const normalizedPrefix = normalizePrefix(item.prefix);\n if (seen.has(normalizedPrefix)) {\n return { valid: false, error: `prefix ${normalizedPrefix} 重复` };\n }\n seen.add(normalizedPrefix);\n\n if (!item.currentProxy || !item.currentProxy.trim()) {\n return { valid: false, error: `prefix ${normalizedPrefix} 缺少 currentProxy` };\n }\n\n if (!item.proxyEnv || typeof item.proxyEnv !== 'object') {\n return { valid: false, error: `prefix ${normalizedPrefix} 缺少 proxyEnv` };\n }\n\n const currentProxyUrl = item.proxyEnv[item.currentProxy];\n if (typeof currentProxyUrl !== 'string') {\n return { valid: false, error: `prefix ${normalizedPrefix} 的 currentProxy 不存在于 proxyEnv 中` };\n }\n\n if (item.currentProxy === 'custom' && !currentProxyUrl.trim()) {\n return { valid: false, error: `prefix ${normalizedPrefix} 选择 custom 时必须提供 URL` };\n }\n\n if (!currentProxyUrl.trim()) {\n return { valid: false, error: `prefix ${normalizedPrefix} 的 currentProxy URL 不能为空` };\n }\n\n const rewriteError = validateRewrite(item, normalizedPrefix);\n if (rewriteError) {\n return { valid: false, error: rewriteError };\n }\n }\n\n return { valid: true };\n}\n\nexport function normalizeApiProxyItem(item: ApiProxyItem): ApiProxyItem {\n const prefix = normalizePrefix(item.prefix);\n\n let rewrite = item.rewrite;\n if (rewrite) {\n if (rewrite.mode === 'replace') {\n rewrite = {\n mode: 'replace',\n targetPrefix: (rewrite.targetPrefix || '').trim().replace(/\\/+$/, '') || '/',\n };\n } else if (rewrite.mode === 'remove') {\n rewrite = {\n mode: 'remove',\n };\n } else {\n rewrite = {\n mode: 'none',\n };\n }\n }\n\n return {\n ...item,\n prefix,\n rewrite,\n proxyKey: deriveProxyKey(prefix, item.proxyKey),\n };\n}\n\nexport function buildEnvFileContent(apiProxies: ApiProxyItem[]): { content: string } | { error: string } {\n const validationResult = validateApiProxies(apiProxies);\n if (!validationResult.valid) {\n return { error: validationResult.error };\n }\n\n const normalizedItems = apiProxies.map(normalizeApiProxyItem);\n const prefixMap = normalizedItems.reduce<Record<string, string>>((acc, item) => {\n acc[item.prefix] = item.proxyKey as string;\n return acc;\n }, {});\n\n const rewriteMap = normalizedItems.reduce<Record<string, string>>((acc, item) => {\n if (!item.rewrite || item.rewrite.mode === 'none') {\n return acc;\n }\n\n if (item.rewrite.mode === 'remove') {\n acc[item.prefix] = '';\n return acc;\n }\n\n if (item.rewrite.mode === 'replace') {\n acc[item.prefix] = item.rewrite.targetPrefix as string;\n }\n\n return acc;\n }, {});\n\n const lines = [\n `${PRIME_PROXY_PREFIX_MAP_KEY}=${JSON.stringify(prefixMap)}`,\n ...(Object.keys(rewriteMap).length > 0 ? [`${PRIME_PROXY_REWRITE_MAP_KEY}=${JSON.stringify(rewriteMap)}`] : []),\n ...normalizedItems.map((item) => `${item.proxyKey}=${item.proxyEnv[item.currentProxy].trim()}`),\n ];\n\n return {\n content: lines.join('\\n'),\n };\n}\n","import { promises as fs } from 'fs';\nimport { join } from 'path';\nimport type { ProjectConfig } from './workspace-types';\nimport { buildEnvFileContent } from './api-proxy';\n\n/**\n * 为指定项目创建环境文件,如果文件已存在则跳过。\n * @param projectName - 项目名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 一个包含已创建和已跳过文件列表的对象\n */\nexport async function createProjectEnvFiles(\n projectName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdFiles: string[];\n skippedFiles: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const createdFiles: string[] = [];\n const skippedFiles: string[] = [];\n\n try {\n await fs.mkdir(projectPath, { recursive: true });\n\n const envs = projectConfig.envs || {};\n for (const envName in envs) {\n const envConfig = envs[envName];\n if (envConfig.envFileName && envConfig.apiProxies?.length) {\n const filePath = join(projectPath, envConfig.envFileName);\n\n try {\n await fs.access(filePath);\n // 文件已存在,跳过\n skippedFiles.push(envConfig.envFileName);\n } catch {\n const built = buildEnvFileContent(envConfig.apiProxies);\n if ('error' in built) {\n return {\n success: false,\n createdFiles,\n skippedFiles,\n error: `环境 ${envName} 配置无效: ${built.error}`,\n };\n }\n\n await fs.writeFile(filePath, built.content, 'utf-8');\n createdFiles.push(envConfig.envFileName);\n }\n }\n }\n return { success: true, createdFiles, skippedFiles };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建环境文件时出错:`, error);\n return { success: false, createdFiles, skippedFiles, error: errorMessage };\n }\n}\n\n/**\n * 为指定项目创建.mock文件夹\n * @param projectName - 项目名称\n * @param workspacePath - 工作空间根路径\n * @returns 创建结果\n */\nexport async function createProjectMockDirectories(\n projectName: string,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdDirectories: string[];\n skippedDirectories: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const mockPath = join(projectPath, '.mock');\n const createdDirectories: string[] = [];\n const skippedDirectories: string[] = [];\n\n try {\n // 创建 .mock 文件夹\n try {\n await fs.access(mockPath);\n skippedDirectories.push('.mock');\n } catch {\n await fs.mkdir(mockPath, { recursive: true });\n createdDirectories.push('.mock');\n }\n\n return { success: true, createdDirectories, skippedDirectories };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建Mock目录时出错:`, error);\n return { success: false, createdDirectories, skippedDirectories, error: errorMessage };\n }\n}\n\n/**\n * 更新指定项目环境的环境文件内容\n * @param projectName - 项目名称\n * @param envName - 环境名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 更新结果\n */\nexport async function updateProjectEnvFile(\n projectName: string,\n envName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n updatedFile?: string;\n error?: string;\n}> {\n try {\n const envConfig = projectConfig.envs[envName];\n \n if (!envConfig) {\n return {\n success: false,\n error: `环境 ${envName} 不存在于项目 ${projectName} 配置中`,\n };\n }\n\n if (!envConfig.envFileName || !envConfig.apiProxies?.length) {\n return {\n success: false,\n error: `环境 ${envName} 缺少 envFileName 或 apiProxies 配置`,\n };\n }\n\n const built = buildEnvFileContent(envConfig.apiProxies);\n if ('error' in built) {\n return {\n success: false,\n error: built.error,\n };\n }\n\n const projectPath = join(workspacePath, projectName);\n const filePath = join(projectPath, envConfig.envFileName);\n\n // 写入文件内容\n await fs.writeFile(filePath, built.content, 'utf-8');\n\n console.log(`已更新环境文件: ${filePath}, 内容: ${built.content}`);\n \n return {\n success: true,\n updatedFile: envConfig.envFileName,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`更新项目 ${projectName} 环境 ${envName} 的环境文件时出错:`, error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n} ","import { NextRequest, NextResponse } from 'next/server';\nimport {\n getProjectsConfig,\n saveProjectsConfig,\n} from '@/lib/workspace-config';\nimport { updateProjectEnvFile } from '@/lib/env-file-operations';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\nimport { sseConnectionManager } from '@/lib/sse-connection-manager';\nimport type { ConfigChangeMessage } from '@/lib/sse-connection-manager';\n\nexport async function PUT(request: NextRequest) {\n try {\n // 解析请求体\n const { envName, projectName, selectedItems } = await request.json();\n\n // 参数验证\n if (!envName || !projectName || !Array.isArray(selectedItems)) {\n return NextResponse.json(\n {\n success: false,\n error: '缺少必要参数:envName, projectName, selectedItems',\n },\n { status: 400 },\n );\n }\n\n // 读取当前配置文件\n const projectsConfig = await getProjectsConfig();\n\n // 检查项目是否存在\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 检查环境是否存在\n if (!projectsConfig[projectName].envs[envName]) {\n return NextResponse.json(\n {\n success: false,\n error: `项目 ${projectName} 中不存在环境 ${envName}`,\n },\n { status: 404 },\n );\n }\n\n // 获取当前环境的host\n const currentHost = projectsConfig[projectName].envs[envName].host;\n\n // 保存更新前的配置用于变化检测\n const beforeSubApps = projectsConfig[projectName].envs[envName].subApps || [];\n\n // 更新 subApps 配置\n projectsConfig[projectName].envs[envName].subApps = selectedItems;\n\n // 记录更新的项目和环境,用于后续更新环境文件\n const updatedProjects: Array<{projectName: string, envName: string}> = [];\n\n // 将选中的环境的代理改为当前环境的host\n selectedItems.forEach((selectedEnvName: string) => {\n // 遍历所有项目,找到包含该环境的项目并更新其代理配置\n Object.keys(projectsConfig).forEach(projName => {\n if (projectsConfig[projName].envs[selectedEnvName]) {\n // 找到匹配的环境,更新其代理配置\n const targetEnv = projectsConfig[projName].envs[selectedEnvName];\n\n // 将选中环境中 /api 前缀代理设置为 custom 并指向当前环境 host\n const apiProxy = targetEnv.apiProxies?.find((item) => item.prefix === '/api');\n if (apiProxy) {\n apiProxy.currentProxy = 'custom';\n apiProxy.proxyEnv.custom = currentHost;\n }\n \n // 记录需要更新环境文件的项目和环境\n updatedProjects.push({\n projectName: projName,\n envName: selectedEnvName\n });\n }\n });\n });\n\n // 保存更新后的配置\n await saveProjectsConfig(projectsConfig);\n\n // 检测配置变化并推送通知\n const afterSubApps = selectedItems;\n const hasChanges = JSON.stringify(beforeSubApps.sort()) !== JSON.stringify(afterSubApps.sort());\n \n if (hasChanges) {\n console.log(`[配置变化] 环境 ${envName} 的 MicroApp 代理配置发生变化`);\n console.log(`[配置变化] 变化前: ${JSON.stringify(beforeSubApps)}`);\n console.log(`[配置变化] 变化后: ${JSON.stringify(afterSubApps)}`);\n\n // 计算具体变化\n const beforeSet = new Set(beforeSubApps);\n const afterSet = new Set(afterSubApps);\n const added = afterSubApps.filter(item => !beforeSet.has(item));\n const removed = beforeSubApps.filter(item => !afterSet.has(item));\n\n // 构建推送消息\n const changeMessage: ConfigChangeMessage = {\n type: 'microapp-proxy-config-change',\n envName,\n timestamp: Date.now(),\n changes: {\n before: beforeSubApps,\n after: afterSubApps,\n added,\n removed,\n },\n projectName,\n message: `环境 ${envName} 的 MicroApp 代理配置已更新`\n };\n\n // 推送给相关环境的连接\n try {\n sseConnectionManager.broadcastToEnv(envName, changeMessage);\n console.log(`[推送成功] 已向环境 ${envName} 推送配置变化通知`);\n } catch (pushError) {\n console.error(`[推送失败] 向环境 ${envName} 推送通知失败:`, pushError);\n // 推送失败不影响主要功能,只记录错误\n }\n } else {\n console.log(`[配置未变化] 环境 ${envName} 的 MicroApp 代理配置无变化,跳过推送`);\n }\n\n // 更新相关项目的环境文件\n const envFileUpdates = await Promise.allSettled(\n updatedProjects.map(async ({ projectName: projName, envName: envNameToUpdate }) => {\n return updateProjectEnvFile(\n projName,\n envNameToUpdate,\n projectsConfig[projName],\n WORKSPACE_CONFIG.WORKSPACE_ROOT,\n );\n })\n );\n\n // 检查环境文件更新结果\n const failedUpdates = envFileUpdates\n .map((result, index) => ({ result, project: updatedProjects[index] }))\n .filter(({ result }) => result.status === 'rejected' || (result.status === 'fulfilled' && !result.value.success));\n\n // 构建响应消息\n let message = 'MicroApp代理配置保存成功,已更新选中环境的代理地址';\n if (failedUpdates.length > 0) {\n message += `,但有 ${failedUpdates.length} 个环境文件更新失败`;\n }\n\n return NextResponse.json({\n success: true,\n message,\n data: {\n projectName,\n envName,\n subApps: selectedItems,\n currentHost,\n updatedProjects: updatedProjects.length,\n envFileUpdateFailures: failedUpdates.length,\n },\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : '保存MicroApp代理配置失败';\n console.error('保存MicroApp代理配置失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n} ","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[6]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/sse-connection-manager.ts","turbopack:///[project]/packages/server/src/lib/api-proxy.ts","turbopack:///[project]/packages/server/src/lib/env-file-operations.ts","turbopack:///[project]/packages/server/src/app/api/microapp-proxy-config/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: string;\n /**\n * 微应用路径标识:用于在共享宿主(micro-app 域名)下区分兄弟子应用。\n * 插件按 micro-app 元素的 default-page / url 是否“包含”该值来选中对应本地 host。\n * 例如 micro-components 为 \"/micro/components\"、360-icrc-site 为 \"/micro/360-icrc-site\"。\n */\n microPath?: string;\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n}\n","import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","/**\n * SSE连接管理器\n * 用于管理MicroApp代理配置变化推送的SSE连接\n */\n\nexport interface ConnectionInfo {\n controller: ReadableStreamDefaultController<Uint8Array>;\n timestamp: number;\n clientId: string;\n envName: string;\n}\n\nexport interface ConfigChangeMessage {\n type: 'microapp-proxy-config-change';\n envName: string;\n timestamp: number;\n changes: {\n before: string[];\n after: string[];\n added: string[];\n removed: string[];\n };\n projectName: string;\n message: string;\n}\n\nexport interface HeartbeatMessage {\n type: 'heartbeat';\n timestamp: number;\n}\n\ntype SSEMessage = ConfigChangeMessage | HeartbeatMessage;\n\n/**\n * SSE连接管理器类\n */\nclass SSEConnectionManager {\n private connections = new Map<string, Set<ConnectionInfo>>();\n private encoder = new TextEncoder();\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private readonly HEARTBEAT_INTERVAL = 30000; // 30秒心跳\n private readonly CONNECTION_TIMEOUT = 120000; // 2分钟连接超时\n private readonly MAX_CONNECTIONS_PER_ENV = 10; // 每个环境最多10个连接\n\n constructor() {\n this.startHeartbeat();\n }\n \n /**\n * 清理所有连接(用于内存清理)\n */\n clearAllConnections(): void {\n console.log('[SSE] 开始清理所有连接...');\n const totalConnections = Array.from(this.connections.values()).reduce((sum, set) => sum + set.size, 0);\n \n this.connections.forEach((connections) => {\n connections.forEach(conn => {\n try {\n conn.controller.close();\n } catch {\n // 忽略关闭错误\n }\n });\n });\n \n this.connections.clear();\n console.log(`[SSE] 已清理 ${totalConnections} 个连接`);\n }\n\n /**\n * 添加新的SSE连接\n */\n addConnection(envName: string, controller: ReadableStreamDefaultController<Uint8Array>, clientId: string): void {\n console.log(`[SSE] 添加连接: 环境=${envName}, 客户端=${clientId}`);\n \n if (!this.connections.has(envName)) {\n this.connections.set(envName, new Set());\n }\n \n const connections = this.connections.get(envName)!;\n \n // 检查连接数限制\n if (connections.size >= this.MAX_CONNECTIONS_PER_ENV) {\n console.warn(`[SSE] 环境 ${envName} 连接数已达上限,清理最旧的连接`);\n // 找到最旧的连接并关闭\n const oldestConn = Array.from(connections).sort((a, b) => a.timestamp - b.timestamp)[0];\n if (oldestConn) {\n try {\n oldestConn.controller.close();\n } catch {\n // 忽略关闭错误\n }\n connections.delete(oldestConn);\n }\n }\n \n const connectionInfo: ConnectionInfo = {\n controller,\n timestamp: Date.now(),\n clientId,\n envName,\n };\n \n connections.add(connectionInfo);\n \n // 发送连接确认消息\n this.sendToConnection(connectionInfo, {\n type: 'heartbeat',\n timestamp: Date.now(),\n });\n\n console.log(`[SSE] 当前连接统计: ${this.getConnectionStats()}`);\n }\n\n /**\n * 移除SSE连接\n */\n removeConnection(envName: string, clientId: string): void {\n console.log(`[SSE] 移除连接: 环境=${envName}, 客户端=${clientId}`);\n \n const connections = this.connections.get(envName);\n if (connections) {\n const connectionToRemove = Array.from(connections).find(conn => conn.clientId === clientId);\n if (connectionToRemove) {\n connections.delete(connectionToRemove);\n \n // 如果该环境没有连接了,删除整个entry\n if (connections.size === 0) {\n this.connections.delete(envName);\n }\n }\n }\n\n console.log(`[SSE] 当前连接统计: ${this.getConnectionStats()}`);\n }\n\n /**\n * 向指定环境广播消息\n */\n broadcastToEnv(envName: string, message: ConfigChangeMessage): void {\n console.log(`[SSE] 向环境 ${envName} 广播配置变化消息`);\n \n const connections = this.connections.get(envName);\n if (!connections || connections.size === 0) {\n console.log(`[SSE] 环境 ${envName} 没有活跃连接,跳过广播`);\n return;\n }\n\n const deadConnections: ConnectionInfo[] = [];\n \n connections.forEach(connectionInfo => {\n try {\n this.sendToConnection(connectionInfo, message);\n } catch (error) {\n console.error(`[SSE] 发送消息到客户端 ${connectionInfo.clientId} 失败:`, error);\n deadConnections.push(connectionInfo);\n }\n });\n\n // 清理无效连接\n deadConnections.forEach(conn => {\n connections.delete(conn);\n console.log(`[SSE] 清理无效连接: 客户端=${conn.clientId}`);\n });\n\n console.log(`[SSE] 成功发送给 ${connections.size} 个连接`);\n }\n\n /**\n * 向单个连接发送消息\n */\n private sendToConnection(connectionInfo: ConnectionInfo, message: SSEMessage): void {\n const data = `data: ${JSON.stringify(message)}\\n\\n`;\n const encodedData = this.encoder.encode(data);\n \n try {\n connectionInfo.controller.enqueue(encodedData);\n connectionInfo.timestamp = Date.now(); // 更新最后活跃时间\n } catch (error) {\n console.error(`[SSE] 发送消息失败:`, error);\n throw error;\n }\n }\n\n /**\n * 启动心跳机制\n */\n private startHeartbeat(): void {\n this.heartbeatInterval = setInterval(() => {\n this.sendHeartbeat();\n this.cleanupStaleConnections();\n }, this.HEARTBEAT_INTERVAL);\n \n console.log(`[SSE] 心跳机制已启动,间隔: ${this.HEARTBEAT_INTERVAL}ms`);\n }\n\n /**\n * 发送心跳消息\n */\n private sendHeartbeat(): void {\n const heartbeatMessage: HeartbeatMessage = {\n type: 'heartbeat',\n timestamp: Date.now(),\n };\n\n let totalConnections = 0;\n this.connections.forEach((connections) => {\n totalConnections += connections.size;\n const deadConnections: ConnectionInfo[] = [];\n \n connections.forEach(connectionInfo => {\n try {\n this.sendToConnection(connectionInfo, heartbeatMessage);\n } catch {\n deadConnections.push(connectionInfo);\n }\n });\n\n // 清理无效连接\n deadConnections.forEach(conn => connections.delete(conn));\n });\n\n if (totalConnections > 0) {\n console.log(`[SSE] 心跳发送完成,活跃连接数: ${totalConnections}`);\n }\n }\n\n /**\n * 清理过期连接\n */\n private cleanupStaleConnections(): void {\n const now = Date.now();\n let cleanedCount = 0;\n\n this.connections.forEach((connections, envName) => {\n const staleConnections: ConnectionInfo[] = [];\n \n connections.forEach(connectionInfo => {\n if (now - connectionInfo.timestamp > this.CONNECTION_TIMEOUT) {\n staleConnections.push(connectionInfo);\n }\n });\n\n staleConnections.forEach(conn => {\n connections.delete(conn);\n cleanedCount++;\n console.log(`[SSE] 清理过期连接: 环境=${envName}, 客户端=${conn.clientId}`);\n });\n\n // 如果该环境没有连接了,删除整个entry\n if (connections.size === 0) {\n this.connections.delete(envName);\n }\n });\n\n if (cleanedCount > 0) {\n console.log(`[SSE] 连接清理完成,清理数量: ${cleanedCount}`);\n }\n }\n\n /**\n * 获取连接统计信息\n */\n getConnectionStats(): string {\n const stats: string[] = [];\n let totalConnections = 0;\n \n this.connections.forEach((connections, envName) => {\n const count = connections.size;\n totalConnections += count;\n stats.push(`${envName}: ${count}`);\n });\n\n return `总计 ${totalConnections} 个连接 (${stats.join(', ')})`;\n }\n\n /**\n * 停止连接管理器\n */\n stop(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n console.log(`[SSE] 心跳机制已停止`);\n }\n\n // 关闭所有连接\n this.connections.forEach((connections) => {\n connections.forEach(connectionInfo => {\n try {\n connectionInfo.controller.close();\n } catch (error) {\n console.error(`[SSE] 关闭连接失败:`, error);\n }\n });\n });\n\n this.connections.clear();\n console.log(`[SSE] 所有连接已关闭`);\n }\n}\n\n// 创建全局实例\nexport const sseConnectionManager = new SSEConnectionManager();\n\n// 在进程退出时清理资源\nprocess.on('SIGINT', () => {\n console.log('[SSE] 收到退出信号,正在清理连接...');\n sseConnectionManager.stop();\n process.exit(0);\n});\n\nprocess.on('SIGTERM', () => {\n console.log('[SSE] 收到终止信号,正在清理连接...');\n sseConnectionManager.stop();\n process.exit(0);\n}); ","import type { ApiProxyItem } from './workspace-types';\n\nexport const PRIME_PROXY_PREFIX_MAP_KEY = 'PRIME_PROXY_PREFIX_MAP';\nexport const PRIME_PROXY_REWRITE_MAP_KEY = 'PRIME_PROXY_REWRITE_MAP';\n\nexport function normalizePrefix(prefix: string): string {\n const trimmed = prefix.trim();\n if (!trimmed.startsWith('/')) {\n return trimmed;\n }\n if (trimmed.length > 1) {\n return trimmed.replace(/\\/+$/, '');\n }\n return trimmed;\n}\n\nfunction toProxyName(prefix: string): string {\n return prefix\n .replace(/^\\//, '')\n .replace(/[^a-zA-Z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .toUpperCase();\n}\n\nexport function deriveProxyKey(prefix: string, proxyKey?: string): string {\n if (proxyKey && proxyKey.trim()) {\n return proxyKey.trim();\n }\n\n const normalizedPrefix = normalizePrefix(prefix);\n if (normalizedPrefix === '/api') {\n return 'PROXY_URL';\n }\n\n const proxyName = toProxyName(normalizedPrefix);\n return `PROXY_${proxyName}_URL`;\n}\n\nfunction validatePrefix(prefix: string): string | null {\n if (!prefix || !prefix.trim()) {\n return 'prefix 不能为空';\n }\n\n const normalizedPrefix = normalizePrefix(prefix);\n if (!normalizedPrefix.startsWith('/')) {\n return `prefix ${prefix} 必须以 / 开头`;\n }\n\n if (/\\s/.test(normalizedPrefix)) {\n return `prefix ${prefix} 不能包含空白字符`;\n }\n\n return null;\n}\n\nfunction validateRewrite(item: ApiProxyItem, normalizedPrefix: string): string | null {\n if (!item.rewrite) {\n return null;\n }\n\n const { mode, targetPrefix } = item.rewrite;\n\n if (!['none', 'remove', 'replace'].includes(mode)) {\n return `prefix ${normalizedPrefix} 的 rewrite.mode 仅支持 none/remove/replace`;\n }\n\n const hasTargetPrefix = typeof targetPrefix === 'string' && targetPrefix.length > 0;\n\n if (mode === 'remove' && hasTargetPrefix) {\n return `prefix ${normalizedPrefix} 的 rewrite.mode 为 remove 时不允许 targetPrefix`;\n }\n\n if (mode === 'replace') {\n const normalizedTargetPrefix = (targetPrefix || '').trim();\n if (!normalizedTargetPrefix || !normalizedTargetPrefix.startsWith('/') || /\\s/.test(normalizedTargetPrefix)) {\n return `prefix ${normalizedPrefix} 的 rewrite.mode 为 replace 时 targetPrefix 必须以 / 开头且不能包含空白字符`;\n }\n }\n\n return null;\n}\n\nexport function validateApiProxies(apiProxies: ApiProxyItem[]): { valid: true } | { valid: false; error: string } {\n if (!Array.isArray(apiProxies) || apiProxies.length === 0) {\n return { valid: false, error: 'apiProxies 不能为空' };\n }\n\n const seen = new Set<string>();\n\n for (const item of apiProxies) {\n const prefixError = validatePrefix(item.prefix);\n if (prefixError) {\n return { valid: false, error: prefixError };\n }\n\n const normalizedPrefix = normalizePrefix(item.prefix);\n if (seen.has(normalizedPrefix)) {\n return { valid: false, error: `prefix ${normalizedPrefix} 重复` };\n }\n seen.add(normalizedPrefix);\n\n if (!item.currentProxy || !item.currentProxy.trim()) {\n return { valid: false, error: `prefix ${normalizedPrefix} 缺少 currentProxy` };\n }\n\n if (!item.proxyEnv || typeof item.proxyEnv !== 'object') {\n return { valid: false, error: `prefix ${normalizedPrefix} 缺少 proxyEnv` };\n }\n\n const currentProxyUrl = item.proxyEnv[item.currentProxy];\n if (typeof currentProxyUrl !== 'string') {\n return { valid: false, error: `prefix ${normalizedPrefix} 的 currentProxy 不存在于 proxyEnv 中` };\n }\n\n if (item.currentProxy === 'custom' && !currentProxyUrl.trim()) {\n return { valid: false, error: `prefix ${normalizedPrefix} 选择 custom 时必须提供 URL` };\n }\n\n if (!currentProxyUrl.trim()) {\n return { valid: false, error: `prefix ${normalizedPrefix} 的 currentProxy URL 不能为空` };\n }\n\n const rewriteError = validateRewrite(item, normalizedPrefix);\n if (rewriteError) {\n return { valid: false, error: rewriteError };\n }\n }\n\n return { valid: true };\n}\n\nexport function normalizeApiProxyItem(item: ApiProxyItem): ApiProxyItem {\n const prefix = normalizePrefix(item.prefix);\n\n let rewrite = item.rewrite;\n if (rewrite) {\n if (rewrite.mode === 'replace') {\n rewrite = {\n mode: 'replace',\n targetPrefix: (rewrite.targetPrefix || '').trim().replace(/\\/+$/, '') || '/',\n };\n } else if (rewrite.mode === 'remove') {\n rewrite = {\n mode: 'remove',\n };\n } else {\n rewrite = {\n mode: 'none',\n };\n }\n }\n\n return {\n ...item,\n prefix,\n rewrite,\n proxyKey: deriveProxyKey(prefix, item.proxyKey),\n };\n}\n\nexport function buildEnvFileContent(apiProxies: ApiProxyItem[]): { content: string } | { error: string } {\n const validationResult = validateApiProxies(apiProxies);\n if (!validationResult.valid) {\n return { error: validationResult.error };\n }\n\n const normalizedItems = apiProxies.map(normalizeApiProxyItem);\n const prefixMap = normalizedItems.reduce<Record<string, string>>((acc, item) => {\n acc[item.prefix] = item.proxyKey as string;\n return acc;\n }, {});\n\n const rewriteMap = normalizedItems.reduce<Record<string, string>>((acc, item) => {\n if (!item.rewrite || item.rewrite.mode === 'none') {\n return acc;\n }\n\n if (item.rewrite.mode === 'remove') {\n acc[item.prefix] = '';\n return acc;\n }\n\n if (item.rewrite.mode === 'replace') {\n acc[item.prefix] = item.rewrite.targetPrefix as string;\n }\n\n return acc;\n }, {});\n\n const lines = [\n `${PRIME_PROXY_PREFIX_MAP_KEY}=${JSON.stringify(prefixMap)}`,\n ...(Object.keys(rewriteMap).length > 0 ? [`${PRIME_PROXY_REWRITE_MAP_KEY}=${JSON.stringify(rewriteMap)}`] : []),\n ...normalizedItems.map((item) => `${item.proxyKey}=${item.proxyEnv[item.currentProxy].trim()}`),\n ];\n\n return {\n content: lines.join('\\n'),\n };\n}\n","import { promises as fs } from 'fs';\nimport { join } from 'path';\nimport type { ProjectConfig } from './workspace-types';\nimport { buildEnvFileContent } from './api-proxy';\n\n/**\n * 为指定项目创建环境文件,如果文件已存在则跳过。\n * @param projectName - 项目名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 一个包含已创建和已跳过文件列表的对象\n */\nexport async function createProjectEnvFiles(\n projectName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdFiles: string[];\n skippedFiles: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const createdFiles: string[] = [];\n const skippedFiles: string[] = [];\n\n try {\n await fs.mkdir(projectPath, { recursive: true });\n\n const envs = projectConfig.envs || {};\n for (const envName in envs) {\n const envConfig = envs[envName];\n if (envConfig.envFileName && envConfig.apiProxies?.length) {\n const filePath = join(projectPath, envConfig.envFileName);\n\n try {\n await fs.access(filePath);\n // 文件已存在,跳过\n skippedFiles.push(envConfig.envFileName);\n } catch {\n const built = buildEnvFileContent(envConfig.apiProxies);\n if ('error' in built) {\n return {\n success: false,\n createdFiles,\n skippedFiles,\n error: `环境 ${envName} 配置无效: ${built.error}`,\n };\n }\n\n await fs.writeFile(filePath, built.content, 'utf-8');\n createdFiles.push(envConfig.envFileName);\n }\n }\n }\n return { success: true, createdFiles, skippedFiles };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建环境文件时出错:`, error);\n return { success: false, createdFiles, skippedFiles, error: errorMessage };\n }\n}\n\n/**\n * 为指定项目创建.mock文件夹\n * @param projectName - 项目名称\n * @param workspacePath - 工作空间根路径\n * @returns 创建结果\n */\nexport async function createProjectMockDirectories(\n projectName: string,\n workspacePath: string,\n): Promise<{\n success: boolean;\n createdDirectories: string[];\n skippedDirectories: string[];\n error?: string;\n}> {\n const projectPath = join(workspacePath, projectName);\n const mockPath = join(projectPath, '.mock');\n const createdDirectories: string[] = [];\n const skippedDirectories: string[] = [];\n\n try {\n // 创建 .mock 文件夹\n try {\n await fs.access(mockPath);\n skippedDirectories.push('.mock');\n } catch {\n await fs.mkdir(mockPath, { recursive: true });\n createdDirectories.push('.mock');\n }\n\n return { success: true, createdDirectories, skippedDirectories };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`在为项目 ${projectName} 创建Mock目录时出错:`, error);\n return { success: false, createdDirectories, skippedDirectories, error: errorMessage };\n }\n}\n\n/**\n * 更新指定项目环境的环境文件内容\n * @param projectName - 项目名称\n * @param envName - 环境名称\n * @param projectConfig - 项目配置\n * @param workspacePath - 工作空间根路径\n * @returns 更新结果\n */\nexport async function updateProjectEnvFile(\n projectName: string,\n envName: string,\n projectConfig: ProjectConfig,\n workspacePath: string,\n): Promise<{\n success: boolean;\n updatedFile?: string;\n error?: string;\n}> {\n try {\n const envConfig = projectConfig.envs[envName];\n \n if (!envConfig) {\n return {\n success: false,\n error: `环境 ${envName} 不存在于项目 ${projectName} 配置中`,\n };\n }\n\n if (!envConfig.envFileName || !envConfig.apiProxies?.length) {\n return {\n success: false,\n error: `环境 ${envName} 缺少 envFileName 或 apiProxies 配置`,\n };\n }\n\n const built = buildEnvFileContent(envConfig.apiProxies);\n if ('error' in built) {\n return {\n success: false,\n error: built.error,\n };\n }\n\n const projectPath = join(workspacePath, projectName);\n const filePath = join(projectPath, envConfig.envFileName);\n\n // 写入文件内容\n await fs.writeFile(filePath, built.content, 'utf-8');\n\n console.log(`已更新环境文件: ${filePath}, 内容: ${built.content}`);\n \n return {\n success: true,\n updatedFile: envConfig.envFileName,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`更新项目 ${projectName} 环境 ${envName} 的环境文件时出错:`, error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n} ","import { NextRequest, NextResponse } from 'next/server';\nimport {\n getProjectsConfig,\n saveProjectsConfig,\n} from '@/lib/workspace-config';\nimport { updateProjectEnvFile } from '@/lib/env-file-operations';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\nimport { sseConnectionManager } from '@/lib/sse-connection-manager';\nimport type { ConfigChangeMessage } from '@/lib/sse-connection-manager';\n\nexport async function PUT(request: NextRequest) {\n try {\n // 解析请求体\n const { envName, projectName, selectedItems } = await request.json();\n\n // 参数验证\n if (!envName || !projectName || !Array.isArray(selectedItems)) {\n return NextResponse.json(\n {\n success: false,\n error: '缺少必要参数:envName, projectName, selectedItems',\n },\n { status: 400 },\n );\n }\n\n // 读取当前配置文件\n const projectsConfig = await getProjectsConfig();\n\n // 检查项目是否存在\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 检查环境是否存在\n if (!projectsConfig[projectName].envs[envName]) {\n return NextResponse.json(\n {\n success: false,\n error: `项目 ${projectName} 中不存在环境 ${envName}`,\n },\n { status: 404 },\n );\n }\n\n // 获取当前环境的host\n const currentHost = projectsConfig[projectName].envs[envName].host;\n\n // 保存更新前的配置用于变化检测\n const beforeSubApps = projectsConfig[projectName].envs[envName].subApps || [];\n\n // 更新 subApps 配置\n projectsConfig[projectName].envs[envName].subApps = selectedItems;\n\n // 记录更新的项目和环境,用于后续更新环境文件\n const updatedProjects: Array<{projectName: string, envName: string}> = [];\n\n // 将选中的环境的代理改为当前环境的host\n selectedItems.forEach((selectedEnvName: string) => {\n // 遍历所有项目,找到包含该环境的项目并更新其代理配置\n Object.keys(projectsConfig).forEach(projName => {\n if (projectsConfig[projName].envs[selectedEnvName]) {\n // 找到匹配的环境,更新其代理配置\n const targetEnv = projectsConfig[projName].envs[selectedEnvName];\n\n // 将选中环境中 /api 前缀代理设置为 custom 并指向当前环境 host\n const apiProxy = targetEnv.apiProxies?.find((item) => item.prefix === '/api');\n if (apiProxy) {\n apiProxy.currentProxy = 'custom';\n apiProxy.proxyEnv.custom = currentHost;\n }\n \n // 记录需要更新环境文件的项目和环境\n updatedProjects.push({\n projectName: projName,\n envName: selectedEnvName\n });\n }\n });\n });\n\n // 保存更新后的配置\n await saveProjectsConfig(projectsConfig);\n\n // 检测配置变化并推送通知\n const afterSubApps = selectedItems;\n const hasChanges = JSON.stringify(beforeSubApps.sort()) !== JSON.stringify(afterSubApps.sort());\n \n if (hasChanges) {\n console.log(`[配置变化] 环境 ${envName} 的 MicroApp 代理配置发生变化`);\n console.log(`[配置变化] 变化前: ${JSON.stringify(beforeSubApps)}`);\n console.log(`[配置变化] 变化后: ${JSON.stringify(afterSubApps)}`);\n\n // 计算具体变化\n const beforeSet = new Set(beforeSubApps);\n const afterSet = new Set(afterSubApps);\n const added = afterSubApps.filter(item => !beforeSet.has(item));\n const removed = beforeSubApps.filter(item => !afterSet.has(item));\n\n // 构建推送消息\n const changeMessage: ConfigChangeMessage = {\n type: 'microapp-proxy-config-change',\n envName,\n timestamp: Date.now(),\n changes: {\n before: beforeSubApps,\n after: afterSubApps,\n added,\n removed,\n },\n projectName,\n message: `环境 ${envName} 的 MicroApp 代理配置已更新`\n };\n\n // 推送给相关环境的连接\n try {\n sseConnectionManager.broadcastToEnv(envName, changeMessage);\n console.log(`[推送成功] 已向环境 ${envName} 推送配置变化通知`);\n } catch (pushError) {\n console.error(`[推送失败] 向环境 ${envName} 推送通知失败:`, pushError);\n // 推送失败不影响主要功能,只记录错误\n }\n } else {\n console.log(`[配置未变化] 环境 ${envName} 的 MicroApp 代理配置无变化,跳过推送`);\n }\n\n // 更新相关项目的环境文件\n const envFileUpdates = await Promise.allSettled(\n updatedProjects.map(async ({ projectName: projName, envName: envNameToUpdate }) => {\n return updateProjectEnvFile(\n projName,\n envNameToUpdate,\n projectsConfig[projName],\n WORKSPACE_CONFIG.WORKSPACE_ROOT,\n );\n })\n );\n\n // 检查环境文件更新结果\n const failedUpdates = envFileUpdates\n .map((result, index) => ({ result, project: updatedProjects[index] }))\n .filter(({ result }) => result.status === 'rejected' || (result.status === 'fulfilled' && !result.value.success));\n\n // 构建响应消息\n let message = 'MicroApp代理配置保存成功,已更新选中环境的代理地址';\n if (failedUpdates.length > 0) {\n message += `,但有 ${failedUpdates.length} 个环境文件更新失败`;\n }\n\n return NextResponse.json({\n success: true,\n message,\n data: {\n projectName,\n envName,\n subApps: selectedItems,\n currentHost,\n updatedProjects: updatedProjects.length,\n envFileUpdateFailures: failedUpdates.length,\n },\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : '保存MicroApp代理配置失败';\n console.error('保存MicroApp代理配置失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n} ","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[6]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
module.exports={45935:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},30331:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("path",()=>require("path"))},29549:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},83943:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},86103:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},23430:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},52670:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js"))},13442:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("os",()=>require("os"))},88941:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({PROJECT_CONFIG_PATH:()=>t,ProjectStatus:()=>o,WORKSPACE_CONFIG:()=>r});var s=e.i(13442),n=e.i(30331);let r={WORKSPACE_ROOT:(0,n.join)((0,s.homedir)(),"Documents","prime-workspace"),GIT_TIMEOUT:3e5,MAX_CONCURRENT_CLONES:Math.max(2,Math.min((0,s.cpus)().length,8)),MAX_RETRY_ATTEMPTS:3},t=(0,n.join)((0,s.homedir)(),".prime-projects.json");var o=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e.INCOMPLETE="incomplete",e}({})}},83886:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("fs",()=>require("fs"))},87485:function(e){var{g:r,__dirname:t,m:s,e:n}=e;s.exports=e.x("child_process",()=>require("child_process"))},47025:function(e){var{g:r,__dirname:t,m:s,e:n}=e},16020:e=>{"use strict";var{g:r,__dirname:t}=e;e.s({POST:()=>c});var s=e.i(15494),n=e.i(87485),o=e.i(83886),a=e.i(30331),i=e.i(88941);async function c(e){try{let r=await e.json(),t=(Array.isArray(r.projects)?r.projects:[]).map(e=>String(e).trim()).filter(Boolean);if(0===t.length)return s.NextResponse.json({success:!1,error:"缺少项目列表参数"},{status:400});let c=i.WORKSPACE_CONFIG.WORKSPACE_ROOT,p=await Promise.all(t.map(async e=>{let r=(0,a.join)(c,e);if(!(0,o.existsSync)(r)||!(0,o.existsSync)((0,a.join)(r,".git")))return{projectName:e,branches:[],error:"项目不存在或不是Git仓库"};try{var t;let s=await (t=["ls-remote","--heads","origin"],new Promise((e,s)=>{let o=(0,n.spawn)("git",t,{cwd:r,stdio:["ignore","pipe","pipe"]}),a="",i="";o.stdout?.on("data",e=>{a+=e.toString()}),o.stderr?.on("data",e=>{i+=e.toString()}),o.on("close",r=>{e({code:r,stdout:a,stderr:i})}),o.on("error",e=>{s(e)})}));if(0!==s.code){let r=s.stderr.trim()||s.stdout.trim();return{projectName:e,branches:[],error:r.slice(0,150)||"获取远程分支失败"}}let o=[];return s.stdout.split("\n").forEach(e=>{let r=e.trim().match(/^[0-9a-f]+\trefs\/heads\/(.+)$/);if(r){let e=r[1].trim();e&&o.push(e)}}),{projectName:e,branches:o,error:null}}catch(r){return{projectName:e,branches:[],error:r instanceof Error?r.message:"执行失败"}}})),u=new Set,d=[];return p.forEach(e=>{e.error&&d.push({projectName:e.projectName,reason:e.error}),e.branches.forEach(e=>u.add(e))}),s.NextResponse.json({success:!0,branches:Array.from(u).sort((e,r)=>e.localeCompare(r)),failedProjects:d})}catch(e){return console.error("批量获取远程分支失败:",e),s.NextResponse.json({success:!1,error:e instanceof Error?e.message:"批量获取远程分支失败"},{status:500})}}},62234:e=>{"use strict";var{g:r,__dirname:t}=e;{e.s({patchFetch:()=>i,routeModule:()=>r,serverHooks:()=>p,workAsyncStorage:()=>t,workUnitAsyncStorage:()=>c});var s=e.i(45746),n=e.i(93828),o=e.i(18250),a=e.i(16020);let r=new s.AppRouteRouteModule({definition:{kind:n.RouteKind.APP_ROUTE,page:"/api/batch-list-branches/route",pathname:"/api/batch-list-branches",filename:"route",bundlePath:""},resolvedPagePath:"[project]/packages/server/src/app/api/batch-list-branches/route.ts",nextConfigOutput:"",userland:a}),{workAsyncStorage:t,workUnitAsyncStorage:c,serverHooks:p}=r;function i(){return(0,o.patchFetch)({workAsyncStorage:t,workUnitAsyncStorage:c})}}}};
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=%5Broot-of-the-server%5D__c52380bc._.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/app/api/batch-list-branches/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: string;\n /**\n * 微应用路径标识:用于在共享宿主(micro-app 域名)下区分兄弟子应用。\n * 插件按 micro-app 元素的 default-page / url 是否“包含”该值来选中对应本地 host。\n * 例如 micro-components 为 \"/micro/components\"、360-icrc-site 为 \"/micro/360-icrc-site\"。\n */\n microPath?: string;\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { spawn } from 'child_process';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\n\ntype GitResult = {\n code: number | null;\n stdout: string;\n stderr: string;\n};\n\nfunction runGitCommand(cwd: string, args: string[]): Promise<GitResult> {\n return new Promise((resolve, reject) => {\n const child = spawn('git', args, {\n cwd,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout?.on('data', (data: Buffer) => {\n stdout += data.toString();\n });\n\n child.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n\n child.on('close', (code) => {\n resolve({ code, stdout, stderr });\n });\n\n child.on('error', (error) => {\n reject(error);\n });\n });\n}\n\n/**\n * 批量获取多个项目所有远程分支的聚合去重列表。\n * 每次调用都会重新执行 git ls-remote,保证分支列表最新。\n */\nexport async function POST(request: NextRequest) {\n try {\n const body = await request.json();\n const rawProjects: unknown = Array.isArray(body.projects) ? body.projects : [];\n const projects = (rawProjects as unknown[])\n .map((item) => String(item).trim())\n .filter(Boolean);\n\n if (projects.length === 0) {\n return NextResponse.json({\n success: false,\n error: '缺少项目列表参数'\n }, { status: 400 });\n }\n\n const workspacePath = WORKSPACE_CONFIG.WORKSPACE_ROOT;\n\n // 并发获取所有项目的远程分支\n const results = await Promise.all(\n projects.map(async (projectName: string) => {\n const projectPath = join(workspacePath, projectName);\n\n if (!existsSync(projectPath) || !existsSync(join(projectPath, '.git'))) {\n return { projectName, branches: [] as string[], error: '项目不存在或不是Git仓库' };\n }\n\n try {\n const result = await runGitCommand(projectPath, ['ls-remote', '--heads', 'origin']);\n if (result.code !== 0) {\n const rawError = result.stderr.trim() || result.stdout.trim();\n return { projectName, branches: [] as string[], error: rawError.slice(0, 150) || '获取远程分支失败' };\n }\n\n const branches: string[] = [];\n result.stdout.split('\\n').forEach((line) => {\n const match = line.trim().match(/^[0-9a-f]+\\trefs\\/heads\\/(.+)$/);\n if (match) {\n const branchName = match[1].trim();\n if (branchName) branches.push(branchName);\n }\n });\n return { projectName, branches, error: null };\n } catch (err) {\n return { projectName, branches: [] as string[], error: err instanceof Error ? err.message : '执行失败' };\n }\n }),\n );\n\n // 聚合去重\n const branchSet = new Set<string>();\n const failedProjects: Array<{ projectName: string; reason: string }> = [];\n results.forEach((result) => {\n if (result.error) {\n failedProjects.push({ projectName: result.projectName, reason: result.error });\n }\n result.branches.forEach((branch: string) => branchSet.add(branch));\n });\n\n return NextResponse.json({\n success: true,\n branches: Array.from(branchSet).sort((a, b) => a.localeCompare(b)),\n failedProjects,\n });\n } catch (error) {\n console.error('批量获取远程分支失败:', error);\n return NextResponse.json({\n success: false,\n error: error instanceof Error ? error.message : '批量获取远程分支失败'\n }, { status: 500 });\n }\n}\n","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[2]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module.exports={
|
|
1
|
+
module.exports={45935:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},30331:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("path",()=>require("path"))},29549:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},83943:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},86103:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},23430:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},52670:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js"))},13442:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("os",()=>require("os"))},88941:e=>{"use strict";var{g:t,__dirname:r}=e;{e.s({PROJECT_CONFIG_PATH:()=>r,ProjectStatus:()=>n,WORKSPACE_CONFIG:()=>t});var s=e.i(13442),o=e.i(30331);let t={WORKSPACE_ROOT:(0,o.join)((0,s.homedir)(),"Documents","prime-workspace"),GIT_TIMEOUT:3e5,MAX_CONCURRENT_CLONES:Math.max(2,Math.min((0,s.cpus)().length,8)),MAX_RETRY_ATTEMPTS:3},r=(0,o.join)((0,s.homedir)(),".prime-projects.json");var n=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e.INCOMPLETE="incomplete",e}({})}},83886:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("fs",()=>require("fs"))},9892:function(e){var{g:t,__dirname:r,m:s,e:o}=e;s.exports=e.x("fs/promises",()=>require("fs/promises"))},35692:e=>{"use strict";var{g:t,__dirname:r}=e;e.s({ProjectStatus:()=>i,getProjectsConfig:()=>n,saveProjectsConfig:()=>a});var s=e.i(9892),o=e.i(88941);async function n(){try{await (0,s.access)(o.PROJECT_CONFIG_PATH,s.constants.F_OK)}catch{return await a({}),{}}try{let e=await (0,s.readFile)(o.PROJECT_CONFIG_PATH,"utf-8");if(!e)return{};return JSON.parse(e)}catch(e){throw console.error("读取或解析项目配置文件失败:",e),Error("无法加载项目配置")}}async function a(e){let t=o.PROJECT_CONFIG_PATH+".tmp";try{await (0,s.writeFile)(t,JSON.stringify(e,null,2),"utf-8"),await (0,s.rename)(t,o.PROJECT_CONFIG_PATH)}catch(e){throw console.error("保存项目配置文件失败:",e),Error("无法保存项目配置")}}var i=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e}({})},8773:function(e){var{g:t,__dirname:r,m:s,e:o}=e},55859:e=>{"use strict";var{g:t,__dirname:r}=e;e.s({GET:()=>c,PUT:()=>u});var s=e.i(15494),o=e.i(83886),n=e.i(30331),a=e.i(35692),i=e.i(88941);async function c(e){try{let{searchParams:t}=new URL(e.url),r=t.get("project"),c=t.get("apiName"),u=t.get("method"),p=t.get("siteName");if(!r||!c||!u||!p)return s.NextResponse.json({success:!1,error:"缺少必要参数:project, apiName, method, siteName"},{status:400});if(!(await (0,a.getProjectsConfig)())[r])return s.NextResponse.json({success:!1,error:`项目 ${r} 不存在`},{status:404});let m=(0,n.join)(i.WORKSPACE_CONFIG.WORKSPACE_ROOT,r),x=(0,n.join)(m,".mock",c,u.toLowerCase(),`${p}.cjs`);try{await o.promises.access(x)}catch{return s.NextResponse.json({success:!1,error:"Mock文件不存在"},{status:404})}let d=await o.promises.readFile(x,"utf-8");return s.NextResponse.json({success:!0,data:{projectName:r,apiName:c,method:u.toLowerCase(),siteName:p,content:d,filePath:(0,n.join)(".mock",c,u.toLowerCase(),`${p}.cjs`)},message:"获取Mock文件内容成功"})}catch(t){let e=t instanceof Error?t.message:"获取Mock文件内容失败";return console.error("获取Mock文件内容失败:",t),s.NextResponse.json({success:!1,error:e},{status:500})}}async function u(e){try{let{projectName:t,apiName:r,method:c,siteName:u,content:p}=await e.json();if(!t||!r||!c||!u||void 0===p)return s.NextResponse.json({success:!1,error:"缺少必要参数:projectName, apiName, method, siteName, content"},{status:400});if(!(await (0,a.getProjectsConfig)())[t])return s.NextResponse.json({success:!1,error:`项目 ${t} 不存在`},{status:404});let m=(0,n.join)(i.WORKSPACE_CONFIG.WORKSPACE_ROOT,t),x=(0,n.join)(m,".mock",r,c.toLowerCase(),`${u}.cjs`);try{await o.promises.access(x)}catch{return s.NextResponse.json({success:!1,error:"Mock文件不存在"},{status:404})}return await o.promises.writeFile(x,p,"utf-8"),s.NextResponse.json({success:!0,message:"Mock文件内容更新成功",data:{projectName:t,apiName:r,method:c.toLowerCase(),siteName:u,filePath:(0,n.join)(".mock",r,c.toLowerCase(),`${u}.cjs`),updatedAt:new Date().toISOString()}})}catch(t){let e=t instanceof Error?t.message:"更新Mock文件内容失败";return console.error("更新Mock文件内容失败:",t),s.NextResponse.json({success:!1,error:e},{status:500})}}},19627:e=>{"use strict";var{g:t,__dirname:r}=e;{e.s({patchFetch:()=>i,routeModule:()=>t,serverHooks:()=>u,workAsyncStorage:()=>r,workUnitAsyncStorage:()=>c});var s=e.i(45746),o=e.i(93828),n=e.i(18250),a=e.i(55859);let t=new s.AppRouteRouteModule({definition:{kind:o.RouteKind.APP_ROUTE,page:"/api/mock-file-content/route",pathname:"/api/mock-file-content",filename:"route",bundlePath:""},resolvedPagePath:"[project]/packages/server/src/app/api/mock-file-content/route.ts",nextConfigOutput:"",userland:a}),{workAsyncStorage:r,workUnitAsyncStorage:c,serverHooks:u}=t;function i(){return(0,n.patchFetch)({workAsyncStorage:r,workUnitAsyncStorage:c})}}}};
|
|
2
2
|
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%
|
|
3
|
+
//# sourceMappingURL=%5Broot-of-the-server%5D__e2654a76._.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/app/api/mock-file-content/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: string;\n /**\n * 微应用路径标识:用于在共享宿主(micro-app 域名)下区分兄弟子应用。\n * 插件按 micro-app 元素的 default-page / url 是否“包含”该值来选中对应本地 host。\n * 例如 micro-components 为 \"/micro/components\"、360-icrc-site 为 \"/micro/360-icrc-site\"。\n */\n microPath?: string;\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n}\n","import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { promises as fs } from 'fs';\nimport { join } from 'path';\nimport { getProjectsConfig } from '@/lib/workspace-config';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\n\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('project');\n const apiName = searchParams.get('apiName');\n const method = searchParams.get('method');\n const siteName = searchParams.get('siteName');\n\n if (!projectName || !apiName || !method || !siteName) {\n return NextResponse.json(\n { success: false, error: '缺少必要参数:project, apiName, method, siteName' },\n { status: 400 },\n );\n }\n\n // 验证项目是否存在\n const projectsConfig = await getProjectsConfig();\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 构建文件路径\n const projectPath = join(WORKSPACE_CONFIG.WORKSPACE_ROOT, projectName);\n const filePath = join(projectPath, '.mock', apiName, method.toLowerCase(), `${siteName}.cjs`);\n\n // 检查文件是否存在\n try {\n await fs.access(filePath);\n } catch {\n return NextResponse.json(\n { success: false, error: 'Mock文件不存在' },\n { status: 404 },\n );\n }\n\n // 读取文件内容\n const content = await fs.readFile(filePath, 'utf-8');\n\n return NextResponse.json({\n success: true,\n data: {\n projectName,\n apiName,\n method: method.toLowerCase(),\n siteName,\n content,\n filePath: join('.mock', apiName, method.toLowerCase(), `${siteName}.cjs`),\n },\n message: '获取Mock文件内容成功',\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : '获取Mock文件内容失败';\n console.error('获取Mock文件内容失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n}\n\nexport async function PUT(request: NextRequest) {\n try {\n // 解析请求体\n const { projectName, apiName, method, siteName, content } = await request.json();\n\n // 参数验证\n if (!projectName || !apiName || !method || !siteName || content === undefined) {\n return NextResponse.json(\n {\n success: false,\n error: '缺少必要参数:projectName, apiName, method, siteName, content',\n },\n { status: 400 },\n );\n }\n\n // 验证项目是否存在\n const projectsConfig = await getProjectsConfig();\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 构建文件路径\n const projectPath = join(WORKSPACE_CONFIG.WORKSPACE_ROOT, projectName);\n const filePath = join(projectPath, '.mock', apiName, method.toLowerCase(), `${siteName}.cjs`);\n\n // 检查文件是否存在\n try {\n await fs.access(filePath);\n } catch {\n return NextResponse.json(\n { success: false, error: 'Mock文件不存在' },\n { status: 404 },\n );\n }\n\n // 写入文件内容\n await fs.writeFile(filePath, content, 'utf-8');\n\n return NextResponse.json({\n success: true,\n message: 'Mock文件内容更新成功',\n data: {\n projectName,\n apiName,\n method: method.toLowerCase(),\n siteName,\n filePath: join('.mock', apiName, method.toLowerCase(), `${siteName}.cjs`),\n updatedAt: new Date().toISOString(),\n },\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : '更新Mock文件内容失败';\n console.error('更新Mock文件内容失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n} ","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[3]}
|
|
1
|
+
{"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/app/api/mock-file-content/route.ts","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/src/build/templates/app-route.ts"],"sourcesContent":["import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ApiProxyRewrite {\n mode: 'none' | 'remove' | 'replace';\n targetPrefix?: string;\n}\n\nexport interface ApiProxyItem {\n prefix: string;\n proxyKey?: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n rewrite?: ApiProxyRewrite;\n}\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n envFileName: string;\n apiProxies: ApiProxyItem[];\n subApps?: string[];\n startCommand?: string;\n /**\n * 微应用路径标识:用于在共享宿主(micro-app 域名)下区分兄弟子应用。\n * 插件按 micro-app 元素的 default-page / url 是否“包含”该值来选中对应本地 host。\n * 例如 micro-components 为 \"/micro/components\"、360-icrc-site 为 \"/micro/360-icrc-site\"。\n */\n microPath?: string;\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n}\n","import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n projectName?: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { promises as fs } from 'fs';\nimport { join } from 'path';\nimport { getProjectsConfig } from '@/lib/workspace-config';\nimport { WORKSPACE_CONFIG } from '@/lib/workspace-types';\n\nexport async function GET(request: NextRequest) {\n try {\n const { searchParams } = new URL(request.url);\n const projectName = searchParams.get('project');\n const apiName = searchParams.get('apiName');\n const method = searchParams.get('method');\n const siteName = searchParams.get('siteName');\n\n if (!projectName || !apiName || !method || !siteName) {\n return NextResponse.json(\n { success: false, error: '缺少必要参数:project, apiName, method, siteName' },\n { status: 400 },\n );\n }\n\n // 验证项目是否存在\n const projectsConfig = await getProjectsConfig();\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 构建文件路径\n const projectPath = join(WORKSPACE_CONFIG.WORKSPACE_ROOT, projectName);\n const filePath = join(projectPath, '.mock', apiName, method.toLowerCase(), `${siteName}.cjs`);\n\n // 检查文件是否存在\n try {\n await fs.access(filePath);\n } catch {\n return NextResponse.json(\n { success: false, error: 'Mock文件不存在' },\n { status: 404 },\n );\n }\n\n // 读取文件内容\n const content = await fs.readFile(filePath, 'utf-8');\n\n return NextResponse.json({\n success: true,\n data: {\n projectName,\n apiName,\n method: method.toLowerCase(),\n siteName,\n content,\n filePath: join('.mock', apiName, method.toLowerCase(), `${siteName}.cjs`),\n },\n message: '获取Mock文件内容成功',\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : '获取Mock文件内容失败';\n console.error('获取Mock文件内容失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n}\n\nexport async function PUT(request: NextRequest) {\n try {\n // 解析请求体\n const { projectName, apiName, method, siteName, content } = await request.json();\n\n // 参数验证\n if (!projectName || !apiName || !method || !siteName || content === undefined) {\n return NextResponse.json(\n {\n success: false,\n error: '缺少必要参数:projectName, apiName, method, siteName, content',\n },\n { status: 400 },\n );\n }\n\n // 验证项目是否存在\n const projectsConfig = await getProjectsConfig();\n if (!projectsConfig[projectName]) {\n return NextResponse.json(\n { success: false, error: `项目 ${projectName} 不存在` },\n { status: 404 },\n );\n }\n\n // 构建文件路径\n const projectPath = join(WORKSPACE_CONFIG.WORKSPACE_ROOT, projectName);\n const filePath = join(projectPath, '.mock', apiName, method.toLowerCase(), `${siteName}.cjs`);\n\n // 检查文件是否存在\n try {\n await fs.access(filePath);\n } catch {\n return NextResponse.json(\n { success: false, error: 'Mock文件不存在' },\n { status: 404 },\n );\n }\n\n // 写入文件内容\n await fs.writeFile(filePath, content, 'utf-8');\n\n return NextResponse.json({\n success: true,\n message: 'Mock文件内容更新成功',\n data: {\n projectName,\n apiName,\n method: method.toLowerCase(),\n siteName,\n filePath: join('.mock', apiName, method.toLowerCase(), `${siteName}.cjs`),\n updatedAt: new Date().toISOString(),\n },\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : '更新Mock文件内容失败';\n console.error('更新Mock文件内容失败:', error);\n return NextResponse.json(\n { success: false, error: errorMessage },\n { status: 500 },\n );\n }\n} ","import {\n AppRouteRouteModule,\n type AppRouteRouteModuleOptions,\n} from '../../server/route-modules/app-route/module.compiled'\nimport { RouteKind } from '../../server/route-kind'\nimport { patchFetch as _patchFetch } from '../../server/lib/patch-fetch'\n\nimport * as userland from 'VAR_USERLAND'\n\n// These are injected by the loader afterwards. This is injected as a variable\n// instead of a replacement because this could also be `undefined` instead of\n// an empty string.\ndeclare const nextConfigOutput: AppRouteRouteModuleOptions['nextConfigOutput']\n\n// We inject the nextConfigOutput here so that we can use them in the route\n// module.\n// INJECT:nextConfigOutput\n\nconst routeModule = new AppRouteRouteModule({\n definition: {\n kind: RouteKind.APP_ROUTE,\n page: 'VAR_DEFINITION_PAGE',\n pathname: 'VAR_DEFINITION_PATHNAME',\n filename: 'VAR_DEFINITION_FILENAME',\n bundlePath: 'VAR_DEFINITION_BUNDLE_PATH',\n },\n resolvedPagePath: 'VAR_RESOLVED_PAGE_PATH',\n nextConfigOutput,\n userland,\n})\n\n// Pull out the exports that we need to expose from the module. This should\n// be eliminated when we've moved the other routes to the new format. These\n// are used to hook into the route.\nconst { workAsyncStorage, workUnitAsyncStorage, serverHooks } = routeModule\n\nfunction patchFetch() {\n return _patchFetch({\n workAsyncStorage,\n workUnitAsyncStorage,\n })\n}\n\nexport {\n routeModule,\n workAsyncStorage,\n workUnitAsyncStorage,\n serverHooks,\n patchFetch,\n}\n"],"names":["AppRouteRouteModule","RouteKind","patchFetch","_patchFetch","userland","routeModule","definition","kind","APP_ROUTE","page","pathname","filename","bundlePath","resolvedPagePath","nextConfigOutput","workAsyncStorage","workUnitAsyncStorage","serverHooks"],"mappings":"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","ignoreList":[3]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
module.exports={45935:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},30331:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("path",()=>require("path"))},29549:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},83943:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},86103:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},23430:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},52670:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js"))},13442:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("os",()=>require("os"))},9892:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("fs/promises",()=>require("fs/promises"))},
|
|
1
|
+
module.exports={87485:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("child_process",()=>require("child_process"))},45935:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},30331:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("path",()=>require("path"))},29549:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},83943:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},86103:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},23430:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},52670:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-route-turbo.runtime.prod.js"))},13442:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("os",()=>require("os"))},9892:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("fs/promises",()=>require("fs/promises"))},4713:function(e){var{g:t,__dirname:o,m:r,e:s}=e;r.exports=e.x("util",()=>require("util"))},70967:e=>{"use strict";var{g:t,__dirname:o}=e;{e.s({appendLog:()=>h,cleanupOldLogs:()=>g,deleteProcessLogs:()=>m,getLogsDirSize:()=>f,getProcessLogPath:()=>i,readLastNLines:()=>d,rotateLogFile:()=>u,startLogCleanupTask:()=>y,stopLogCleanupTask:()=>E,truncateLogLine:()=>c,writeLogsSync:()=>p});var r=e.i(9892),s=e.i(30331),n=e.i(13442);let t={MAX_FILE_SIZE:5242880,MAX_LOG_FILES:3,MAX_LOG_AGE_DAYS:7,MAX_LINE_LENGTH:1e3,CLEANUP_INTERVAL:18e5};function a(){return s.default.join(n.default.homedir(),".prime-process-logs")}function i(e){return s.default.join(a(),`${e}.log`)}function c(e){return e.length<=t.MAX_LINE_LENGTH?e:e.substring(0,t.MAX_LINE_LENGTH)+"... [truncated]"}async function l(e){try{return(await r.default.stat(e)).size}catch{return 0}}async function u(e){let o=i(e),s=await l(o);if(!(s<t.MAX_FILE_SIZE)){console.log(`[日志管理] 轮转日志文件: ${e}, 大小: ${(s/1024/1024).toFixed(2)}MB`);try{let s=`${o}.${t.MAX_LOG_FILES}`;try{await r.default.unlink(s)}catch{}for(let e=t.MAX_LOG_FILES-1;e>=1;e--){let t=1===e?o:`${o}.${e}`,s=`${o}.${e+1}`;try{await r.default.rename(t,s)}catch{}}await r.default.rename(o,`${o}.1`),await r.default.writeFile(o,"","utf-8"),console.log(`[日志管理] 日志轮转完成: ${e}`)}catch(t){console.error(`[日志管理] 轮转日志文件失败: ${e}`,t)}}}async function h(e,t){await u(e);let o=i(e),s=c(t);try{await r.default.mkdir(a(),{recursive:!0}),await r.default.appendFile(o,s+"\n","utf-8")}catch(t){console.error(`[日志管理] 追加日志失败: ${e}`,t)}}async function p(e,t){await u(e);let o=i(e),s=t.map(e=>c(e));try{await r.default.mkdir(a(),{recursive:!0}),await r.default.writeFile(o,s.join("\n")+"\n","utf-8")}catch(t){console.error(`[日志管理] 写入日志失败: ${e}`,t)}}async function d(e,t=100){let o=i(e);try{return(await r.default.readFile(o,"utf-8")).split("\n").filter(e=>e.trim()).slice(-t)}catch{return[]}}async function g(){console.log("[日志管理] 开始清理旧日志...");try{let e=a();try{await r.default.access(e)}catch{console.log("[日志管理] 日志目录不存在,无需清理");return}let o=await r.default.readdir(e),n=Date.now(),i=24*t.MAX_LOG_AGE_DAYS*36e5,c=0,l=0;for(let t of o){let o=s.default.join(e,t);try{let e=await r.default.stat(o);if(n-e.mtime.getTime()>i){l+=e.size;try{await r.default.unlink(o),c++,console.log(`[日志管理] 删除过期日志: ${t}`)}catch(e){e?.code!=="ENOENT"&&console.error(`[日志管理] 删除文件失败: ${t}`,e)}}}catch(e){e?.code!=="ENOENT"&&console.error(`[日志管理] 处理文件失败: ${t}`,e)}}console.log(`[日志管理] 清理完成: 删除 ${c} 个文件, 释放 ${(l/1024/1024).toFixed(2)}MB`)}catch(e){console.error("[日志管理] 清理日志失败:",e)}}async function m(e){let o=i(e);try{await r.default.unlink(o)}catch(t){t?.code!=="ENOENT"&&console.error(`[日志管理] 删除主日志文件失败: ${e}`,t)}for(let s=1;s<=t.MAX_LOG_FILES;s++)try{await r.default.unlink(`${o}.${s}`)}catch(t){t?.code!=="ENOENT"&&console.error(`[日志管理] 删除轮转日志文件失败: ${e}.${s}`,t)}console.log(`[日志管理] 删除进程日志: ${e}`)}async function f(){try{let e=a(),t=await r.default.readdir(e),o=0,n=0;for(let a of t)try{let t=await r.default.stat(s.default.join(e,a));o+=t.size,n++}catch{}return{totalSize:o,fileCount:n}}catch{return{totalSize:0,fileCount:0}}}let o=null;function y(){o||(console.log("[日志管理] 启动定期清理任务"),g(),o=setInterval(()=>{g()},t.CLEANUP_INTERVAL))}function E(){o&&(clearInterval(o),o=null,console.log("[日志管理] 停止定期清理任务"))}process.on("SIGINT",()=>{E()}),process.on("SIGTERM",()=>{E()})}},94722:e=>{"use strict";var{g:t,__dirname:o}=e;{e.s({sseConnectionManager:()=>o});class t{connections=new Map;encoder=new TextEncoder;heartbeatInterval=null;HEARTBEAT_INTERVAL=3e4;CONNECTION_TIMEOUT=12e4;MAX_CONNECTIONS_PER_ENV=10;constructor(){this.startHeartbeat()}clearAllConnections(){console.log("[SSE] 开始清理所有连接...");let e=Array.from(this.connections.values()).reduce((e,t)=>e+t.size,0);this.connections.forEach(e=>{e.forEach(e=>{try{e.controller.close()}catch{}})}),this.connections.clear(),console.log(`[SSE] 已清理 ${e} 个连接`)}addConnection(e,t,o){console.log(`[SSE] 添加连接: 环境=${e}, 客户端=${o}`),this.connections.has(e)||this.connections.set(e,new Set);let r=this.connections.get(e);if(r.size>=this.MAX_CONNECTIONS_PER_ENV){console.warn(`[SSE] 环境 ${e} 连接数已达上限,清理最旧的连接`);let t=Array.from(r).sort((e,t)=>e.timestamp-t.timestamp)[0];if(t){try{t.controller.close()}catch{}r.delete(t)}}let s={controller:t,timestamp:Date.now(),clientId:o,envName:e};r.add(s),this.sendToConnection(s,{type:"heartbeat",timestamp:Date.now()}),console.log(`[SSE] 当前连接统计: ${this.getConnectionStats()}`)}removeConnection(e,t){console.log(`[SSE] 移除连接: 环境=${e}, 客户端=${t}`);let o=this.connections.get(e);if(o){let r=Array.from(o).find(e=>e.clientId===t);r&&(o.delete(r),0===o.size&&this.connections.delete(e))}console.log(`[SSE] 当前连接统计: ${this.getConnectionStats()}`)}broadcastToEnv(e,t){console.log(`[SSE] 向环境 ${e} 广播配置变化消息`);let o=this.connections.get(e);if(!o||0===o.size)return void console.log(`[SSE] 环境 ${e} 没有活跃连接,跳过广播`);let r=[];o.forEach(e=>{try{this.sendToConnection(e,t)}catch(t){console.error(`[SSE] 发送消息到客户端 ${e.clientId} 失败:`,t),r.push(e)}}),r.forEach(e=>{o.delete(e),console.log(`[SSE] 清理无效连接: 客户端=${e.clientId}`)}),console.log(`[SSE] 成功发送给 ${o.size} 个连接`)}sendToConnection(e,t){let o=`data: ${JSON.stringify(t)}
|
|
2
2
|
|
|
3
3
|
`,r=this.encoder.encode(o);try{e.controller.enqueue(r),e.timestamp=Date.now()}catch(e){throw console.error(`[SSE] 发送消息失败:`,e),e}}startHeartbeat(){this.heartbeatInterval=setInterval(()=>{this.sendHeartbeat(),this.cleanupStaleConnections()},this.HEARTBEAT_INTERVAL),console.log(`[SSE] 心跳机制已启动,间隔: ${this.HEARTBEAT_INTERVAL}ms`)}sendHeartbeat(){let e={type:"heartbeat",timestamp:Date.now()},t=0;this.connections.forEach(o=>{t+=o.size;let r=[];o.forEach(t=>{try{this.sendToConnection(t,e)}catch{r.push(t)}}),r.forEach(e=>o.delete(e))}),t>0&&console.log(`[SSE] 心跳发送完成,活跃连接数: ${t}`)}cleanupStaleConnections(){let e=Date.now(),t=0;this.connections.forEach((o,r)=>{let s=[];o.forEach(t=>{e-t.timestamp>this.CONNECTION_TIMEOUT&&s.push(t)}),s.forEach(e=>{o.delete(e),t++,console.log(`[SSE] 清理过期连接: 环境=${r}, 客户端=${e.clientId}`)}),0===o.size&&this.connections.delete(r)}),t>0&&console.log(`[SSE] 连接清理完成,清理数量: ${t}`)}getConnectionStats(){let e=[],t=0;return this.connections.forEach((o,r)=>{let s=o.size;t+=s,e.push(`${r}: ${s}`)}),`总计 ${t} 个连接 (${e.join(", ")})`}stop(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null,console.log(`[SSE] 心跳机制已停止`)),this.connections.forEach(e=>{e.forEach(e=>{try{e.controller.close()}catch(e){console.error(`[SSE] 关闭连接失败:`,e)}})}),this.connections.clear(),console.log(`[SSE] 所有连接已关闭`)}}let o=new t;process.on("SIGINT",()=>{console.log("[SSE] 收到退出信号,正在清理连接..."),o.stop(),process.exit(0)}),process.on("SIGTERM",()=>{console.log("[SSE] 收到终止信号,正在清理连接..."),o.stop(),process.exit(0)})}},71034:function(e){var{g:t,__dirname:o,m:r,e:s}=e},20248:e=>{"use strict";var{g:t,__dirname:o}=e;{e.s({memoryMonitor:()=>n});var r=e.i(87485);let o=(0,e.i(4713).promisify)(r.exec),s={warningMB:512,criticalMB:1024,heapUsagePercent:90},n=new class{monitorTimer=null;thresholds;cleanupCallbacks=[];lastWarningTime=0;warningCooldown=3e5;constructor(e={}){this.thresholds={...s,...e}}registerCleanupCallback(e){this.cleanupCallbacks.push(e)}async getSystemMemory(){try{{let{stdout:e}=await o(`ps -o rss= -g ${process.pid}`),t=e.trim().split("\n").reduce((e,t)=>{let o=parseInt(t.trim());return e+(isNaN(o)?0:o)},0);return 1024*t}}catch{}return 0}getMemoryUsage(){let e=process.memoryUsage();return{rss:e.rss,heapTotal:e.heapTotal,heapUsed:e.heapUsed,external:e.external,arrayBuffers:e.arrayBuffers}}async getFullMemoryUsage(){let e=this.getMemoryUsage(),t=await this.getSystemMemory();return{...e,systemTotal:t>0?t:void 0}}formatBytes(e){return`${(e/1024/1024).toFixed(2)} MB`}async checkMemory(){let e=await this.getFullMemoryUsage(),t=e.rss/1024/1024,o=e.heapUsed/e.heapTotal*100,r=e.systemTotal?e.systemTotal/1024/1024:null,s={rss:this.formatBytes(e.rss),heapUsed:this.formatBytes(e.heapUsed),heapTotal:this.formatBytes(e.heapTotal),heapUsagePercent:`${o.toFixed(2)}%`};e.systemTotal&&(s.systemTotal=this.formatBytes(e.systemTotal)),console.log("[内存监控] 当前使用:",s);let n=r||t;if(n>=this.thresholds.criticalMB){console.error(`[内存监控] ⚠️ 内存使用达到临界值: ${n.toFixed(2)}MB`),await this.triggerCleanup("critical");return}if(n>=this.thresholds.warningMB||o>=this.thresholds.heapUsagePercent){let e=Date.now();e-this.lastWarningTime>this.warningCooldown&&(console.warn(`[内存监控] ⚠️ 内存使用较高: ${n.toFixed(2)}MB (堆使用率: ${o.toFixed(2)}%)`),this.lastWarningTime=e,await this.triggerCleanup("warning"))}}async triggerCleanup(e){console.log(`[内存监控] 开始 ${"critical"===e?"紧急":"常规"} 清理...`);let o=this.getMemoryUsage();for(let e of this.cleanupCallbacks)try{await e()}catch(e){console.error("[内存监控] 清理回调执行失败:",e)}t.gc?(t.gc(),console.log("[内存监控] 已触发垃圾回收")):"critical"===e&&console.warn("[内存监控] 垃圾回收不可用。启动 Node.js 时使用 --expose-gc 标志以启用手动垃圾回收");let r=this.getMemoryUsage(),s=(o.rss-r.rss)/1024/1024;console.log(`[内存监控] 清理完成,释放内存: ${s.toFixed(2)}MB`)}start(){if(this.monitorTimer)return void console.warn("[内存监控] 监控器已经在运行");console.log("[内存监控] 启动内存监控",{interval:`60秒`,thresholds:{warning:`${this.thresholds.warningMB}MB`,critical:`${this.thresholds.criticalMB}MB`,heapUsage:`${this.thresholds.heapUsagePercent}%`}}),this.checkMemory(),this.monitorTimer=setInterval(()=>{this.checkMemory()},6e4)}stop(){this.monitorTimer&&(clearInterval(this.monitorTimer),this.monitorTimer=null,console.log("[内存监控] 监控器已停止"))}async check(){return await this.checkMemory(),await this.getFullMemoryUsage()}};process.on("SIGINT",()=>{n.stop()}),process.on("SIGTERM",()=>{n.stop()})}},44691:e=>{"use strict";var{g:t,__dirname:o}=e;e.s({GET:()=>i,POST:()=>c});var r=e.i(15494),s=e.i(20248),n=e.i(70967),a=e.i(94722);async function i(){try{let e=await s.memoryMonitor.check(),t=await (0,n.getLogsDirSize)(),o={rss:`${(e.rss/1024/1024).toFixed(2)} MB`,heapUsed:`${(e.heapUsed/1024/1024).toFixed(2)} MB`,heapTotal:`${(e.heapTotal/1024/1024).toFixed(2)} MB`,heapUsagePercent:`${(e.heapUsed/e.heapTotal*100).toFixed(2)}%`,external:`${(e.external/1024/1024).toFixed(2)} MB`};return e.systemTotal&&(o.systemTotal=`${(e.systemTotal/1024/1024).toFixed(2)} MB`,o.note="systemTotal 包含所有子进程和相关资源"),r.NextResponse.json({success:!0,data:{memory:o,logs:{totalSize:`${(t.totalSize/1024/1024).toFixed(2)} MB`,fileCount:t.fileCount},connections:a.sseConnectionManager.getConnectionStats(),timestamp:new Date().toISOString()}})}catch(e){return r.NextResponse.json({success:!1,error:e instanceof Error?e.message:"获取内存状态失败"},{status:500})}}async function c(){try{return await s.memoryMonitor.check(),r.NextResponse.json({success:!0,message:"已触发内存检查和清理"})}catch(e){return r.NextResponse.json({success:!1,error:e instanceof Error?e.message:"触发清理失败"},{status:500})}}},74662:e=>{"use strict";var{g:t,__dirname:o}=e;{e.s({patchFetch:()=>i,routeModule:()=>t,serverHooks:()=>l,workAsyncStorage:()=>o,workUnitAsyncStorage:()=>c});var r=e.i(45746),s=e.i(93828),n=e.i(18250),a=e.i(44691);let t=new r.AppRouteRouteModule({definition:{kind:s.RouteKind.APP_ROUTE,page:"/api/memory-status/route",pathname:"/api/memory-status",filename:"route",bundlePath:""},resolvedPagePath:"[project]/packages/server/src/app/api/memory-status/route.ts",nextConfigOutput:"",userland:a}),{workAsyncStorage:o,workUnitAsyncStorage:c,serverHooks:l}=t;function i(){return(0,n.patchFetch)({workAsyncStorage:o,workUnitAsyncStorage:c})}}}};
|
|
4
4
|
|
|
5
|
-
//# sourceMappingURL=%5Broot-of-the-server%
|
|
5
|
+
//# sourceMappingURL=%5Broot-of-the-server%5D__e96f0857._.js.map
|
|
@@ -3,6 +3,6 @@ ${b}`))}function D(){if(!P)throw Object.defineProperty(Error("Invariant: React.u
|
|
|
3
3
|
|
|
4
4
|
If you want to hide the \`${b.titleName}\`, you can wrap it with our VisuallyHidden component.
|
|
5
5
|
|
|
6
|
-
For more information, see https://radix-ui.com/primitives/docs/components/${b.docsSlug}`;return(0,d.useEffect)(()=>{a&&(document.getElementById(a)||console.error(c))},[c,a]),null},Z=({contentRef:a,descriptionId:b})=>{let c=X("DialogDescriptionWarning"),e=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${c.contentName}}.`;return(0,d.useEffect)(()=>{let c=a.current?.getAttribute("aria-describedby");b&&c&&(document.getElementById(b)||console.warn(e))},[e,a,b]),null},$=y,_=A,aa=E,ab=G,ac=K,ad=P,ae=R,af=T},76315:a=>{"use strict";var{g:b,__dirname:c}=a;{a.s({__iconNode:()=>b,default:()=>c});var d=a.i(49756);let b=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],c=(0,d.default)("x",b)}},97231:a=>{"use strict";var{g:b,__dirname:c}=a;a.s({XIcon:()=>d.default});var d=a.i(76315)},22529:a=>{"use strict";var{g:b,__dirname:c}=a;a.s({Dialog:()=>h,DialogClose:()=>k,DialogContent:()=>m,DialogDescription:()=>q,DialogFooter:()=>o,DialogHeader:()=>n,DialogOverlay:()=>l,DialogPortal:()=>j,DialogTitle:()=>p,DialogTrigger:()=>i});var d=a.i(99559),e=a.i(38047),f=a.i(97231),g=a.i(61073);function h({...a}){return(0,d.jsx)(e.Root,{"data-slot":"dialog",...a})}function i({...a}){return(0,d.jsx)(e.Trigger,{"data-slot":"dialog-trigger",...a})}function j({...a}){return(0,d.jsx)(e.Portal,{"data-slot":"dialog-portal",...a})}function k({...a}){return(0,d.jsx)(e.Close,{"data-slot":"dialog-close",...a})}function l({className:a,...b}){return(0,d.jsx)(e.Overlay,{"data-slot":"dialog-overlay",className:(0,g.cn)("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",a),...b})}function m({className:a,children:b,showCloseButton:c=!0,...h}){return(0,d.jsxs)(j,{"data-slot":"dialog-portal",children:[(0,d.jsx)(l,{}),(0,d.jsxs)(e.Content,{"data-slot":"dialog-content",className:(0,g.cn)("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200",a),...h,children:[b,c&&(0,d.jsxs)(e.Close,{"data-slot":"dialog-close",className:"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",children:[(0,d.jsx)(f.XIcon,{}),(0,d.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})}function n({className:a,...b}){return(0,d.jsx)("div",{"data-slot":"dialog-header",className:(0,g.cn)("flex flex-col gap-2 text-center sm:text-left",a),...b})}function o({className:a,...b}){return(0,d.jsx)("div",{"data-slot":"dialog-footer",className:(0,g.cn)("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",a),...b})}function p({className:a,...b}){return(0,d.jsx)(e.Title,{"data-slot":"dialog-title",className:(0,g.cn)("text-lg leading-none font-semibold",a),...b})}function q({className:a,...b}){return(0,d.jsx)(e.Description,{"data-slot":"dialog-description",className:(0,g.cn)("text-muted-foreground text-sm",a),...b})}}};
|
|
6
|
+
For more information, see https://radix-ui.com/primitives/docs/components/${b.docsSlug}`;return(0,d.useEffect)(()=>{a&&(document.getElementById(a)||console.error(c))},[c,a]),null},Z=({contentRef:a,descriptionId:b})=>{let c=X("DialogDescriptionWarning"),e=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${c.contentName}}.`;return(0,d.useEffect)(()=>{let c=a.current?.getAttribute("aria-describedby");b&&c&&(document.getElementById(b)||console.warn(e))},[e,a,b]),null},$=y,_=A,aa=E,ab=G,ac=K,ad=P,ae=R,af=T},76315:a=>{"use strict";var{g:b,__dirname:c}=a;{a.s({__iconNode:()=>b,default:()=>c});var d=a.i(49756);let b=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],c=(0,d.default)("x",b)}},97231:a=>{"use strict";var{g:b,__dirname:c}=a;a.s({XIcon:()=>d.default});var d=a.i(76315)},22529:a=>{"use strict";var{g:b,__dirname:c}=a;a.s({Dialog:()=>h,DialogClose:()=>k,DialogContent:()=>m,DialogDescription:()=>q,DialogFooter:()=>o,DialogHeader:()=>n,DialogOverlay:()=>l,DialogPortal:()=>j,DialogTitle:()=>p,DialogTrigger:()=>i});var d=a.i(99559),e=a.i(38047),f=a.i(97231),g=a.i(61073);function h({...a}){return(0,d.jsx)(e.Root,{"data-slot":"dialog",...a})}function i({...a}){return(0,d.jsx)(e.Trigger,{"data-slot":"dialog-trigger",...a})}function j({...a}){return(0,d.jsx)(e.Portal,{"data-slot":"dialog-portal",...a})}function k({...a}){return(0,d.jsx)(e.Close,{"data-slot":"dialog-close",...a})}function l({className:a,...b}){return(0,d.jsx)(e.Overlay,{"data-slot":"dialog-overlay",className:(0,g.cn)("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",a),...b})}function m({className:a,children:b,showCloseButton:c=!0,...h}){return(0,d.jsxs)(j,{"data-slot":"dialog-portal",children:[(0,d.jsx)(l,{}),(0,d.jsxs)(e.Content,{"data-slot":"dialog-content",className:(0,g.cn)("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200",a),...h,children:[b,c&&(0,d.jsxs)(e.Close,{"data-slot":"dialog-close",className:"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",children:[(0,d.jsx)(f.XIcon,{}),(0,d.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})}function n({className:a,...b}){return(0,d.jsx)("div",{"data-slot":"dialog-header",className:(0,g.cn)("flex flex-col gap-2 text-center sm:text-left",a),...b})}function o({className:a,...b}){return(0,d.jsx)("div",{"data-slot":"dialog-footer",className:(0,g.cn)("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",a),...b})}function p({className:a,...b}){return(0,d.jsx)(e.Title,{"data-slot":"dialog-title",className:(0,g.cn)("text-lg leading-none font-semibold",a),...b})}function q({className:a,...b}){return(0,d.jsx)(e.Description,{"data-slot":"dialog-description",className:(0,g.cn)("text-muted-foreground text-sm",a),...b})}},56414:a=>{"use strict";var{g:b,__dirname:c}=a;{a.s({BRANCH_DISPLAY_LIMIT:()=>b,filterBranchOptions:()=>d});let b=5;function d(a,c,e=b){let f=c.trim().toLowerCase(),g=f?a.filter(a=>a.toLowerCase().includes(f)):a;return{visible:g.slice(0,e),total:g.length}}}}};
|
|
7
7
|
|
|
8
|
-
//# sourceMappingURL=
|
|
8
|
+
//# sourceMappingURL=_283bdc73._.js.map
|