codecrypto-cli 1.0.8 → 1.0.10
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/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +64 -7
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/deploy-sc.d.ts.map +1 -1
- package/dist/commands/deploy-sc.js +162 -0
- package/dist/commands/deploy-sc.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +644 -136
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +518 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/auth.ts +71 -8
- package/src/commands/deploy-sc.ts +182 -0
- package/src/commands/deploy.ts +688 -150
- package/src/commands/doctor.ts +498 -0
- package/src/index.ts +2 -0
- package/token.json +69 -0
- package/docker-build/Dockerfile +0 -14
- package/docker-build/standalone/.next/BUILD_ID +0 -1
- package/docker-build/standalone/.next/app-path-routes-manifest.json +0 -13
- package/docker-build/standalone/.next/build-manifest.json +0 -20
- package/docker-build/standalone/.next/package.json +0 -1
- package/docker-build/standalone/.next/prerender-manifest.json +0 -186
- package/docker-build/standalone/.next/required-server-files.json +0 -164
- package/docker-build/standalone/.next/routes-manifest.json +0 -110
- package/docker-build/standalone/.next/server/app/_global-error/page/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/_global-error/page/build-manifest.json +0 -17
- package/docker-build/standalone/.next/server/app/_global-error/page/next-font-manifest.json +0 -6
- package/docker-build/standalone/.next/server/app/_global-error/page/react-loadable-manifest.json +0 -1
- package/docker-build/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/_global-error/page.js +0 -11
- package/docker-build/standalone/.next/server/app/_global-error/page.js.map +0 -5
- package/docker-build/standalone/.next/server/app/_global-error/page.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/_global-error.html +0 -2
- package/docker-build/standalone/.next/server/app/_global-error.meta +0 -15
- package/docker-build/standalone/.next/server/app/_global-error.rsc +0 -13
- package/docker-build/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +0 -5
- package/docker-build/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +0 -13
- package/docker-build/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +0 -6
- package/docker-build/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +0 -1
- package/docker-build/standalone/.next/server/app/_not-found/page/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/_not-found/page/build-manifest.json +0 -17
- package/docker-build/standalone/.next/server/app/_not-found/page/next-font-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/_not-found/page/react-loadable-manifest.json +0 -1
- package/docker-build/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/_not-found/page.js +0 -14
- package/docker-build/standalone/.next/server/app/_not-found/page.js.map +0 -5
- package/docker-build/standalone/.next/server/app/_not-found/page.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/_not-found.html +0 -1
- package/docker-build/standalone/.next/server/app/_not-found.meta +0 -16
- package/docker-build/standalone/.next/server/app/_not-found.rsc +0 -14
- package/docker-build/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +0 -14
- package/docker-build/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +0 -6
- package/docker-build/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +0 -5
- package/docker-build/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +0 -5
- package/docker-build/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +0 -2
- package/docker-build/standalone/.next/server/app/api/deploy/route/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/api/deploy/route/build-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/api/deploy/route/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/api/deploy/route.js +0 -7
- package/docker-build/standalone/.next/server/app/api/deploy/route.js.map +0 -5
- package/docker-build/standalone/.next/server/app/api/deploy/route.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/api/deploy/route_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/api/deploy-image/route/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/api/deploy-image/route/build-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/api/deploy-image/route/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/api/deploy-image/route.js +0 -6
- package/docker-build/standalone/.next/server/app/api/deploy-image/route.js.map +0 -5
- package/docker-build/standalone/.next/server/app/api/deploy-image/route.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/api/deploy-image/route_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/api/docker-images/route/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/api/docker-images/route/build-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/api/docker-images/route/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/api/docker-images/route.js +0 -6
- package/docker-build/standalone/.next/server/app/api/docker-images/route.js.map +0 -5
- package/docker-build/standalone/.next/server/app/api/docker-images/route.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/api/docker-images/route_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/api/faucet/route/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/api/faucet/route/build-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/api/faucet/route/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/api/faucet/route.js +0 -9
- package/docker-build/standalone/.next/server/app/api/faucet/route.js.map +0 -5
- package/docker-build/standalone/.next/server/app/api/faucet/route.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/api/faucet/route_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/deploy/page/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/deploy/page/build-manifest.json +0 -17
- package/docker-build/standalone/.next/server/app/deploy/page/next-font-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/deploy/page/react-loadable-manifest.json +0 -1
- package/docker-build/standalone/.next/server/app/deploy/page/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/deploy/page.js +0 -16
- package/docker-build/standalone/.next/server/app/deploy/page.js.map +0 -5
- package/docker-build/standalone/.next/server/app/deploy/page.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/deploy/page_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/deploy.html +0 -1
- package/docker-build/standalone/.next/server/app/deploy.meta +0 -15
- package/docker-build/standalone/.next/server/app/deploy.rsc +0 -20
- package/docker-build/standalone/.next/server/app/deploy.segments/_full.segment.rsc +0 -20
- package/docker-build/standalone/.next/server/app/deploy.segments/_head.segment.rsc +0 -6
- package/docker-build/standalone/.next/server/app/deploy.segments/_index.segment.rsc +0 -5
- package/docker-build/standalone/.next/server/app/deploy.segments/_tree.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/deploy.segments/deploy/__PAGE__.segment.rsc +0 -9
- package/docker-build/standalone/.next/server/app/deploy.segments/deploy.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/faucet/page/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/faucet/page/build-manifest.json +0 -17
- package/docker-build/standalone/.next/server/app/faucet/page/next-font-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/faucet/page/react-loadable-manifest.json +0 -1
- package/docker-build/standalone/.next/server/app/faucet/page/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/faucet/page.js +0 -16
- package/docker-build/standalone/.next/server/app/faucet/page.js.map +0 -5
- package/docker-build/standalone/.next/server/app/faucet/page.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/faucet/page_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/faucet.html +0 -1
- package/docker-build/standalone/.next/server/app/faucet.meta +0 -15
- package/docker-build/standalone/.next/server/app/faucet.rsc +0 -20
- package/docker-build/standalone/.next/server/app/faucet.segments/_full.segment.rsc +0 -20
- package/docker-build/standalone/.next/server/app/faucet.segments/_head.segment.rsc +0 -6
- package/docker-build/standalone/.next/server/app/faucet.segments/_index.segment.rsc +0 -5
- package/docker-build/standalone/.next/server/app/faucet.segments/_tree.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/faucet.segments/faucet/__PAGE__.segment.rsc +0 -9
- package/docker-build/standalone/.next/server/app/faucet.segments/faucet.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/favicon.ico/route/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/favicon.ico/route/build-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/favicon.ico/route.js +0 -7
- package/docker-build/standalone/.next/server/app/favicon.ico/route.js.map +0 -5
- package/docker-build/standalone/.next/server/app/favicon.ico/route.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/favicon.ico.body +0 -0
- package/docker-build/standalone/.next/server/app/favicon.ico.meta +0 -1
- package/docker-build/standalone/.next/server/app/images/page/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/images/page/build-manifest.json +0 -17
- package/docker-build/standalone/.next/server/app/images/page/next-font-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/images/page/react-loadable-manifest.json +0 -1
- package/docker-build/standalone/.next/server/app/images/page/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/images/page.js +0 -16
- package/docker-build/standalone/.next/server/app/images/page.js.map +0 -5
- package/docker-build/standalone/.next/server/app/images/page.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/images/page_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app/images.html +0 -1
- package/docker-build/standalone/.next/server/app/images.meta +0 -15
- package/docker-build/standalone/.next/server/app/images.rsc +0 -20
- package/docker-build/standalone/.next/server/app/images.segments/_full.segment.rsc +0 -20
- package/docker-build/standalone/.next/server/app/images.segments/_head.segment.rsc +0 -6
- package/docker-build/standalone/.next/server/app/images.segments/_index.segment.rsc +0 -5
- package/docker-build/standalone/.next/server/app/images.segments/_tree.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/images.segments/images/__PAGE__.segment.rsc +0 -9
- package/docker-build/standalone/.next/server/app/images.segments/images.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/index.html +0 -1
- package/docker-build/standalone/.next/server/app/index.meta +0 -14
- package/docker-build/standalone/.next/server/app/index.rsc +0 -25
- package/docker-build/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +0 -8
- package/docker-build/standalone/.next/server/app/index.segments/_full.segment.rsc +0 -25
- package/docker-build/standalone/.next/server/app/index.segments/_head.segment.rsc +0 -6
- package/docker-build/standalone/.next/server/app/index.segments/_index.segment.rsc +0 -5
- package/docker-build/standalone/.next/server/app/index.segments/_tree.segment.rsc +0 -4
- package/docker-build/standalone/.next/server/app/page/app-paths-manifest.json +0 -3
- package/docker-build/standalone/.next/server/app/page/build-manifest.json +0 -17
- package/docker-build/standalone/.next/server/app/page/next-font-manifest.json +0 -11
- package/docker-build/standalone/.next/server/app/page/react-loadable-manifest.json +0 -1
- package/docker-build/standalone/.next/server/app/page/server-reference-manifest.json +0 -4
- package/docker-build/standalone/.next/server/app/page.js +0 -16
- package/docker-build/standalone/.next/server/app/page.js.map +0 -5
- package/docker-build/standalone/.next/server/app/page.js.nft.json +0 -1
- package/docker-build/standalone/.next/server/app/page_client-reference-manifest.js +0 -2
- package/docker-build/standalone/.next/server/app-paths-manifest.json +0 -13
- package/docker-build/standalone/.next/server/chunks/10072_infra_server-cc__next-internal_server_app_api_deploy_route_actions_6cdc6432.js +0 -3
- package/docker-build/standalone/.next/server/chunks/10072_infra_server-cc__next-internal_server_app_api_faucet_route_actions_f54ec975.js +0 -3
- package/docker-build/standalone/.next/server/chunks/10072_infra_server-cc__next-internal_server_app_favicon_ico_route_actions_d73715d1.js +0 -3
- package/docker-build/standalone/.next/server/chunks/66d90_server-cc__next-internal_server_app_api_deploy-image_route_actions_b340a7f4.js +0 -3
- package/docker-build/standalone/.next/server/chunks/66d90_server-cc__next-internal_server_app_api_docker-images_route_actions_4adcb030.js +0 -3
- package/docker-build/standalone/.next/server/chunks/6f6aa_4d460f49._.js +0 -30
- package/docker-build/standalone/.next/server/chunks/6f6aa_@noble_curves_esm_secp256k1_c7f9b58b.js +0 -3
- package/docker-build/standalone/.next/server/chunks/6f6aa_next_dist_esm_build_templates_app-route_1a9ee783.js +0 -6
- package/docker-build/standalone/.next/server/chunks/6f6aa_next_dist_esm_build_templates_app-route_8d132e6a.js +0 -3
- package/docker-build/standalone/.next/server/chunks/6f6aa_viem__esm_utils_ccip_bb7bf310.js +0 -3
- package/docker-build/standalone/.next/server/chunks/[externals]_next_dist_b01ab6e1._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/[root-of-the-server]__0928cca7._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/[root-of-the-server]__0c6b3bd9._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/[root-of-the-server]__1846bb23._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/[root-of-the-server]__8f8a2ff9._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/[root-of-the-server]__90ea784b._.js +0 -21
- package/docker-build/standalone/.next/server/chunks/[root-of-the-server]__f6379956._.js +0 -39
- package/docker-build/standalone/.next/server/chunks/[turbopack]_runtime.js +0 -795
- package/docker-build/standalone/.next/server/chunks/ssr/10072_infra_server-cc__next-internal_server_app__global-error_page_actions_bdbde336.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/10072_infra_server-cc__next-internal_server_app__not-found_page_actions_41269af3.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/10072_infra_server-cc__next-internal_server_app_deploy_page_actions_3988cfb8.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/10072_infra_server-cc__next-internal_server_app_faucet_page_actions_e5e8dd8a.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/10072_infra_server-cc__next-internal_server_app_images_page_actions_bcdfd86b.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_server-cc_293382c4._.js +0 -4
- package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_server-cc_55723634._.js +0 -4
- package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_server-cc_821445df._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_server-cc_8545ebc7._.js +0 -4
- package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_server-cc_acad38a1._.js +0 -6
- package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_server-cc_app_b373a582._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/2025_cc_CODECRYPTO_infra_server-cc_d03dcb7a._.js +0 -4
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_7c51ed4c._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_next_dist_05cd73d5._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_next_dist_3e60adb5._.js +0 -6
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_next_dist_5002976b._.js +0 -4
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_next_dist_client_components_a432b2d3._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_next_dist_client_components_builtin_forbidden_b4e63d3a.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_next_dist_client_components_builtin_global-error_edcabd66.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_next_dist_client_components_builtin_unauthorized_f08488ad.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/6f6aa_next_dist_esm_build_templates_app-page_c7a8656a.js +0 -4
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e0d983d._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__0f25bf3b._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__10dae68a._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ebd727b._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__30996048._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__587c95dd._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__5ecc39a2._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__6382fff8._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__8ed1042a._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__91644c56._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__a2833bcd._.js +0 -10
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__acf31a1c._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__ae009f46._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__daca67ae._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__f2372d3f._.js +0 -4
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__f2ed834a._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[root-of-the-server]__ff0dddf3._.js +0 -3
- package/docker-build/standalone/.next/server/chunks/ssr/[turbopack]_runtime.js +0 -795
- package/docker-build/standalone/.next/server/chunks/ssr/e6d68_cc_CODECRYPTO_infra_server-cc__next-internal_server_app_page_actions_12ae3ff1.js +0 -3
- package/docker-build/standalone/.next/server/functions-config-manifest.json +0 -4
- package/docker-build/standalone/.next/server/middleware-build-manifest.js +0 -21
- package/docker-build/standalone/.next/server/middleware-manifest.json +0 -6
- package/docker-build/standalone/.next/server/next-font-manifest.js +0 -1
- package/docker-build/standalone/.next/server/next-font-manifest.json +0 -27
- package/docker-build/standalone/.next/server/pages/404.html +0 -1
- package/docker-build/standalone/.next/server/pages/500.html +0 -2
- package/docker-build/standalone/.next/server/pages-manifest.json +0 -4
- package/docker-build/standalone/.next/server/server-reference-manifest.js +0 -1
- package/docker-build/standalone/.next/server/server-reference-manifest.json +0 -5
- package/docker-build/standalone/.next/static/ZrQJjBH5oznRmy8xN4NKX/_buildManifest.js +0 -11
- package/docker-build/standalone/.next/static/ZrQJjBH5oznRmy8xN4NKX/_clientMiddlewareManifest.json +0 -1
- package/docker-build/standalone/.next/static/ZrQJjBH5oznRmy8xN4NKX/_ssgManifest.js +0 -1
- package/docker-build/standalone/.next/static/chunks/0c03a563297c48f4.js +0 -1
- package/docker-build/standalone/.next/static/chunks/3142ddfdb448fd24.js +0 -1
- package/docker-build/standalone/.next/static/chunks/35b2ae0057b43b20.js +0 -1
- package/docker-build/standalone/.next/static/chunks/5a1aef391fd12242.js +0 -1
- package/docker-build/standalone/.next/static/chunks/66401b6fc62891de.js +0 -4
- package/docker-build/standalone/.next/static/chunks/782a67ca986fb1bd.js +0 -1
- package/docker-build/standalone/.next/static/chunks/8b27abf6cb0fca62.js +0 -2
- package/docker-build/standalone/.next/static/chunks/8dba80aa68873762.css +0 -3
- package/docker-build/standalone/.next/static/chunks/902797f337bf356c.js +0 -1
- package/docker-build/standalone/.next/static/chunks/9706b17cfd50df01.js +0 -1
- package/docker-build/standalone/.next/static/chunks/a6dad97d9634a72d.js +0 -1
- package/docker-build/standalone/.next/static/chunks/a6dad97d9634a72d.js.map +0 -1
- package/docker-build/standalone/.next/static/chunks/df3b8eb181fde7c2.js +0 -1
- package/docker-build/standalone/.next/static/chunks/turbopack-237950634fd3a365.js +0 -4
- package/docker-build/standalone/.next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
- package/docker-build/standalone/.next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
- package/docker-build/standalone/.next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
- package/docker-build/standalone/.next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
- package/docker-build/standalone/.next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
- package/docker-build/standalone/.next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
- package/docker-build/standalone/.next/static/media/favicon.0b3bf435.ico +0 -0
- package/docker-build/standalone/package.json +0 -35
- package/docker-build/standalone/public/deploy-test.html +0 -276
- package/docker-build/standalone/public/file.svg +0 -1
- package/docker-build/standalone/public/globe.svg +0 -1
- package/docker-build/standalone/public/next.svg +0 -1
- package/docker-build/standalone/public/vercel.svg +0 -1
- package/docker-build/standalone/public/window.svg +0 -1
- package/docker-build/standalone/server.js +0 -38
package/dist/commands/deploy.js
CHANGED
|
@@ -45,8 +45,8 @@ const fs = __importStar(require("fs"));
|
|
|
45
45
|
const path = __importStar(require("path"));
|
|
46
46
|
const os = __importStar(require("os"));
|
|
47
47
|
exports.deployCommand = new commander_1.Command('deploy')
|
|
48
|
-
.description('Build and deploy Docker image for Next.js
|
|
49
|
-
.argument('<project-path>', 'Path to the
|
|
48
|
+
.description('Build and deploy Docker image for Next.js or Express application')
|
|
49
|
+
.argument('<project-path>', 'Path to the project directory')
|
|
50
50
|
.argument('[dest-folder]', 'Destination folder for Docker build context', './docker-build')
|
|
51
51
|
.option('--skip-build', 'Skip npm run build (assume already built)', false)
|
|
52
52
|
.option('--no-push', 'Build image but do not push to registry')
|
|
@@ -55,6 +55,8 @@ exports.deployCommand = new commander_1.Command('deploy')
|
|
|
55
55
|
.option('--env-file <path>', 'Path to .env file with environment variables')
|
|
56
56
|
.option('--port <port>', 'Application port', '3000')
|
|
57
57
|
.option('--domain-base <domain>', 'Domain base for deployment', 'proyectos.codecrypto.academy')
|
|
58
|
+
.option('--image-version <version>', 'Image version/tag to deploy (overrides package.json version)')
|
|
59
|
+
.option('--skip-git-check', 'Skip Git repository status check', false)
|
|
58
60
|
.action(async (projectPath, destFolder, options) => {
|
|
59
61
|
console.log(chalk_1.default.blue('\n🐳 CodeCrypto Docker Deployment\n'));
|
|
60
62
|
try {
|
|
@@ -70,9 +72,85 @@ exports.deployCommand = new commander_1.Command('deploy')
|
|
|
70
72
|
console.error(chalk_1.default.red(`❌ Error: No se encontró package.json en el proyecto`));
|
|
71
73
|
process.exit(1);
|
|
72
74
|
}
|
|
73
|
-
//
|
|
75
|
+
// Validar que no hay archivos pendientes de commit (a menos que se omita)
|
|
76
|
+
if (!options.skipGitCheck) {
|
|
77
|
+
const gitCheckSpinner = (0, ora_1.default)('Checking Git status...').start();
|
|
78
|
+
try {
|
|
79
|
+
// Verificar si es un repositorio git usando git rev-parse
|
|
80
|
+
// Esto es más robusto que solo verificar .git ya que funciona con submodules y worktrees
|
|
81
|
+
let isGitRepo = false;
|
|
82
|
+
try {
|
|
83
|
+
(0, child_process_1.execSync)('git rev-parse --git-dir', {
|
|
84
|
+
cwd: resolvedProjectPath,
|
|
85
|
+
encoding: 'utf-8',
|
|
86
|
+
stdio: 'pipe',
|
|
87
|
+
});
|
|
88
|
+
isGitRepo = true;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// No es un repositorio git o git no está disponible
|
|
92
|
+
isGitRepo = false;
|
|
93
|
+
}
|
|
94
|
+
if (isGitRepo) {
|
|
95
|
+
// Verificar si hay cambios sin commitear
|
|
96
|
+
try {
|
|
97
|
+
const gitStatus = (0, child_process_1.execSync)('git status --porcelain', {
|
|
98
|
+
cwd: resolvedProjectPath,
|
|
99
|
+
encoding: 'utf-8',
|
|
100
|
+
stdio: 'pipe',
|
|
101
|
+
}).trim();
|
|
102
|
+
if (gitStatus) {
|
|
103
|
+
gitCheckSpinner.fail('Uncommitted changes detected');
|
|
104
|
+
console.error(chalk_1.default.red('\n❌ Error: Hay archivos pendientes de commit en el repositorio'));
|
|
105
|
+
console.error(chalk_1.default.yellow('\n📋 Archivos modificados/sin commitear:'));
|
|
106
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
107
|
+
// Mostrar los archivos pendientes
|
|
108
|
+
const files = gitStatus.split('\n').filter(line => line.trim());
|
|
109
|
+
files.forEach(file => {
|
|
110
|
+
const status = file.substring(0, 2);
|
|
111
|
+
const fileName = file.substring(3);
|
|
112
|
+
let statusColor = chalk_1.default.yellow;
|
|
113
|
+
if (status.includes('A'))
|
|
114
|
+
statusColor = chalk_1.default.green;
|
|
115
|
+
else if (status.includes('D'))
|
|
116
|
+
statusColor = chalk_1.default.red;
|
|
117
|
+
else if (status.includes('M'))
|
|
118
|
+
statusColor = chalk_1.default.yellow;
|
|
119
|
+
console.log(chalk_1.default.gray(` ${statusColor(status)} ${chalk_1.default.white(fileName)}`));
|
|
120
|
+
});
|
|
121
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
122
|
+
console.error(chalk_1.default.yellow('\n💡 Por favor, haz commit de tus cambios antes de desplegar:'));
|
|
123
|
+
console.error(chalk_1.default.cyan(' git add .'));
|
|
124
|
+
console.error(chalk_1.default.cyan(' git commit -m "your message"'));
|
|
125
|
+
console.error(chalk_1.default.yellow('\n O usa --skip-git-check para omitir esta validación (no recomendado)'));
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
gitCheckSpinner.succeed('Git repository is clean');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
// Si git status falla, puede ser que haya algún problema
|
|
134
|
+
gitCheckSpinner.warn('Could not check Git status, continuing...');
|
|
135
|
+
if (error.message) {
|
|
136
|
+
console.log(chalk_1.default.yellow(` Warning: ${error.message}`));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
gitCheckSpinner.succeed('Not a Git repository (skipping check)');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
gitCheckSpinner.warn('Git check failed, continuing...');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.log(chalk_1.default.yellow('⚠️ Git status check skipped (--skip-git-check)'));
|
|
150
|
+
}
|
|
151
|
+
// Leer versión del package.json o usar la versión especificada
|
|
74
152
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
75
|
-
const version = packageJson.version || 'latest';
|
|
153
|
+
const version = options.imageVersion || packageJson.version || 'latest';
|
|
76
154
|
const projectName = path.basename(resolvedProjectPath);
|
|
77
155
|
const imageBase = `jviejo/${projectName}`;
|
|
78
156
|
const imageName = `${imageBase}:${version}`;
|
|
@@ -82,114 +160,145 @@ exports.deployCommand = new commander_1.Command('deploy')
|
|
|
82
160
|
// - Por defecto (sin flags): options.push = true (hace push)
|
|
83
161
|
// - Con --no-push: options.push = false (no hace push)
|
|
84
162
|
const shouldPush = options.push !== false;
|
|
163
|
+
// Detectar automáticamente el tipo de proyecto analizando package.json
|
|
164
|
+
const allDependencies = {
|
|
165
|
+
...(packageJson.dependencies || {}),
|
|
166
|
+
...(packageJson.devDependencies || {}),
|
|
167
|
+
};
|
|
168
|
+
let projectType = null;
|
|
169
|
+
if (allDependencies.next || allDependencies['nextjs']) {
|
|
170
|
+
projectType = 'nextjs';
|
|
171
|
+
}
|
|
172
|
+
else if (allDependencies.express) {
|
|
173
|
+
projectType = 'express';
|
|
174
|
+
}
|
|
175
|
+
if (!projectType) {
|
|
176
|
+
console.error(chalk_1.default.red(`❌ Error: No se pudo detectar el tipo de proyecto`));
|
|
177
|
+
console.error(chalk_1.default.yellow(' El proyecto debe tener "next" o "express" en las dependencias del package.json'));
|
|
178
|
+
console.error(chalk_1.default.yellow(' Dependencias encontradas:'));
|
|
179
|
+
const depKeys = Object.keys(allDependencies).slice(0, 10);
|
|
180
|
+
depKeys.forEach(dep => {
|
|
181
|
+
console.error(chalk_1.default.gray(` - ${dep}`));
|
|
182
|
+
});
|
|
183
|
+
if (Object.keys(allDependencies).length > 10) {
|
|
184
|
+
console.error(chalk_1.default.gray(` ... y ${Object.keys(allDependencies).length - 10} más`));
|
|
185
|
+
}
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
85
188
|
console.log(chalk_1.default.gray('Deployment Configuration:'));
|
|
86
189
|
console.log(chalk_1.default.white(` Project: ${chalk_1.default.green(projectName)}`));
|
|
190
|
+
console.log(chalk_1.default.white(` Type: ${chalk_1.default.green(projectType)}`));
|
|
87
191
|
console.log(chalk_1.default.white(` Version: ${chalk_1.default.green(version)}`));
|
|
88
192
|
console.log(chalk_1.default.white(` Image: ${chalk_1.default.green(imageName)}`));
|
|
89
193
|
console.log(chalk_1.default.white(` Latest: ${chalk_1.default.green(imageLatest)}`));
|
|
90
194
|
console.log(chalk_1.default.white(` Push to Registry: ${shouldPush ? chalk_1.default.green('Yes') : chalk_1.default.yellow('No')}\n`));
|
|
91
|
-
//
|
|
92
|
-
if (!options.skipBuild) {
|
|
93
|
-
const buildSpinner = (0, ora_1.default)('Building Next.js application...').start();
|
|
94
|
-
try {
|
|
95
|
-
(0, child_process_1.execSync)('npm run build', {
|
|
96
|
-
cwd: resolvedProjectPath,
|
|
97
|
-
stdio: 'pipe'
|
|
98
|
-
});
|
|
99
|
-
buildSpinner.succeed('Build completed successfully');
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
buildSpinner.fail('Build failed');
|
|
103
|
-
console.error(chalk_1.default.red('Error during build. Make sure you have "output: standalone" in next.config.ts'));
|
|
104
|
-
process.exit(1);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
// Verificar que existe .next/standalone
|
|
108
|
-
const standalonePath = path.join(resolvedProjectPath, '.next', 'standalone');
|
|
109
|
-
if (!fs.existsSync(standalonePath)) {
|
|
110
|
-
console.error(chalk_1.default.red(`❌ Error: No se encontró .next/standalone`));
|
|
111
|
-
console.error(chalk_1.default.yellow('Asegúrate de tener "output: standalone" en next.config.ts y ejecutar "npm run build"'));
|
|
112
|
-
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
// Paso 2: Preparar directorio destino
|
|
195
|
+
// Preparar directorio destino
|
|
115
196
|
const resolvedDestFolder = path.resolve(destFolder);
|
|
116
|
-
const standaloneDest = path.join(resolvedDestFolder, 'standalone');
|
|
117
|
-
const copySpinner = (0, ora_1.default)('Copying standalone files...').start();
|
|
118
197
|
if (fs.existsSync(resolvedDestFolder)) {
|
|
119
198
|
fs.rmSync(resolvedDestFolder, { recursive: true, force: true });
|
|
120
199
|
}
|
|
121
|
-
fs.mkdirSync(
|
|
122
|
-
// Copiar contenido de standalone
|
|
123
|
-
const nextDir = findDirectory(standalonePath, '.next');
|
|
124
|
-
if (nextDir) {
|
|
125
|
-
const parentDir = path.dirname(nextDir);
|
|
126
|
-
copyDirectory(parentDir, standaloneDest);
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
copyDirectory(standalonePath, standaloneDest);
|
|
130
|
-
}
|
|
131
|
-
// Copiar .next/static
|
|
132
|
-
const staticPath = path.join(resolvedProjectPath, '.next', 'static');
|
|
133
|
-
if (fs.existsSync(staticPath)) {
|
|
134
|
-
const staticDest = path.join(standaloneDest, '.next', 'static');
|
|
135
|
-
fs.mkdirSync(staticDest, { recursive: true });
|
|
136
|
-
copyDirectory(staticPath, staticDest);
|
|
137
|
-
}
|
|
138
|
-
// Copiar public
|
|
139
|
-
const publicPath = path.join(resolvedProjectPath, 'public');
|
|
140
|
-
if (fs.existsSync(publicPath)) {
|
|
141
|
-
const publicDest = path.join(standaloneDest, 'public');
|
|
142
|
-
fs.mkdirSync(publicDest, { recursive: true });
|
|
143
|
-
copyDirectory(publicPath, publicDest);
|
|
144
|
-
}
|
|
145
|
-
// Verificar server.js
|
|
146
|
-
const serverJsPath = path.join(standaloneDest, 'server.js');
|
|
147
|
-
if (!fs.existsSync(serverJsPath)) {
|
|
148
|
-
copySpinner.fail('server.js not found in standalone');
|
|
149
|
-
process.exit(1);
|
|
150
|
-
}
|
|
151
|
-
copySpinner.succeed('Files copied successfully');
|
|
152
|
-
// Leer y procesar archivo .env si existe
|
|
153
|
-
let nextPublicEnvVars = [];
|
|
200
|
+
fs.mkdirSync(resolvedDestFolder, { recursive: true });
|
|
154
201
|
let runtimeEnvVars = [];
|
|
202
|
+
let nextPublicEnvVars = [];
|
|
203
|
+
let dockerfileContent;
|
|
204
|
+
// Determinar ruta del archivo .env (común para ambos tipos de proyecto)
|
|
155
205
|
const envFilePath = options.envFile
|
|
156
206
|
? path.resolve(options.envFile)
|
|
157
207
|
: path.join(resolvedProjectPath, '.env');
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const key = trimmed.substring(0, equalIndex).trim();
|
|
170
|
-
const value = trimmed.substring(equalIndex + 1).trim();
|
|
171
|
-
if (key.startsWith('NEXT_PUBLIC_')) {
|
|
172
|
-
nextPublicEnvVars.push(`${key}=${value}`);
|
|
208
|
+
if (projectType === 'nextjs') {
|
|
209
|
+
// ========== LÓGICA PARA NEXT.JS ==========
|
|
210
|
+
// Paso 1: Build del proyecto si es necesario
|
|
211
|
+
if (!options.skipBuild) {
|
|
212
|
+
const buildSpinner = (0, ora_1.default)('Building Next.js application...').start();
|
|
213
|
+
try {
|
|
214
|
+
(0, child_process_1.execSync)('npm run build', {
|
|
215
|
+
cwd: resolvedProjectPath,
|
|
216
|
+
stdio: 'pipe'
|
|
217
|
+
});
|
|
218
|
+
buildSpinner.succeed('Build completed successfully');
|
|
173
219
|
}
|
|
174
|
-
|
|
175
|
-
|
|
220
|
+
catch (error) {
|
|
221
|
+
buildSpinner.fail('Build failed');
|
|
222
|
+
console.error(chalk_1.default.red('Error during build. Make sure you have "output: standalone" in next.config.ts'));
|
|
223
|
+
process.exit(1);
|
|
176
224
|
}
|
|
177
225
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
226
|
+
// Verificar que existe .next/standalone
|
|
227
|
+
const standalonePath = path.join(resolvedProjectPath, '.next', 'standalone');
|
|
228
|
+
if (!fs.existsSync(standalonePath)) {
|
|
229
|
+
console.error(chalk_1.default.red(`❌ Error: No se encontró .next/standalone`));
|
|
230
|
+
console.error(chalk_1.default.yellow('Asegúrate de tener "output: standalone" en next.config.ts y ejecutar "npm run build"'));
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
// Paso 2: Preparar directorio destino
|
|
234
|
+
const standaloneDest = path.join(resolvedDestFolder, 'standalone');
|
|
235
|
+
const copySpinner = (0, ora_1.default)('Copying standalone files...').start();
|
|
236
|
+
fs.mkdirSync(standaloneDest, { recursive: true });
|
|
237
|
+
// Copiar contenido de standalone
|
|
238
|
+
const nextDir = findDirectory(standalonePath, '.next');
|
|
239
|
+
if (nextDir) {
|
|
240
|
+
const parentDir = path.dirname(nextDir);
|
|
241
|
+
copyDirectory(parentDir, standaloneDest);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
copyDirectory(standalonePath, standaloneDest);
|
|
245
|
+
}
|
|
246
|
+
// Copiar .next/static
|
|
247
|
+
const staticPath = path.join(resolvedProjectPath, '.next', 'static');
|
|
248
|
+
if (fs.existsSync(staticPath)) {
|
|
249
|
+
const staticDest = path.join(standaloneDest, '.next', 'static');
|
|
250
|
+
fs.mkdirSync(staticDest, { recursive: true });
|
|
251
|
+
copyDirectory(staticPath, staticDest);
|
|
252
|
+
}
|
|
253
|
+
// Copiar public
|
|
254
|
+
const publicPath = path.join(resolvedProjectPath, 'public');
|
|
255
|
+
if (fs.existsSync(publicPath)) {
|
|
256
|
+
const publicDest = path.join(standaloneDest, 'public');
|
|
257
|
+
fs.mkdirSync(publicDest, { recursive: true });
|
|
258
|
+
copyDirectory(publicPath, publicDest);
|
|
259
|
+
}
|
|
260
|
+
// Verificar server.js
|
|
261
|
+
const serverJsPath = path.join(standaloneDest, 'server.js');
|
|
262
|
+
if (!fs.existsSync(serverJsPath)) {
|
|
263
|
+
copySpinner.fail('server.js not found in standalone');
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
copySpinner.succeed('Files copied successfully');
|
|
267
|
+
// Leer y procesar archivo .env si existe
|
|
268
|
+
// (envFilePath ya está definido arriba)
|
|
269
|
+
if (fs.existsSync(envFilePath)) {
|
|
270
|
+
const envContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
271
|
+
const envLines = envContent.split('\n');
|
|
272
|
+
for (const line of envLines) {
|
|
273
|
+
const trimmed = line.trim();
|
|
274
|
+
// Ignorar comentarios y líneas vacías
|
|
275
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
276
|
+
continue;
|
|
277
|
+
const equalIndex = trimmed.indexOf('=');
|
|
278
|
+
if (equalIndex === -1)
|
|
279
|
+
continue;
|
|
280
|
+
const key = trimmed.substring(0, equalIndex).trim();
|
|
281
|
+
const value = trimmed.substring(equalIndex + 1).trim();
|
|
282
|
+
if (key.startsWith('NEXT_PUBLIC_')) {
|
|
283
|
+
nextPublicEnvVars.push(`${key}=${value}`);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
runtimeEnvVars.push(`${key}=${value}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// Construir ARG y ENV para NEXT_PUBLIC_*
|
|
291
|
+
const buildArgs = nextPublicEnvVars.map(env => {
|
|
292
|
+
const [key, ...valueParts] = env.split('=');
|
|
293
|
+
const value = valueParts.join('=');
|
|
294
|
+
return `ARG ${key}=${value}`;
|
|
295
|
+
}).join('\n');
|
|
296
|
+
const buildEnvs = nextPublicEnvVars.map(env => {
|
|
297
|
+
const [key, ...valueParts] = env.split('=');
|
|
298
|
+
const value = valueParts.join('=');
|
|
299
|
+
return `ENV ${key}=${value}`;
|
|
300
|
+
}).join('\n');
|
|
301
|
+
dockerfileContent = `FROM node:20-alpine
|
|
193
302
|
WORKDIR /app
|
|
194
303
|
|
|
195
304
|
ENV NODE_ENV=production
|
|
@@ -208,23 +317,243 @@ EXPOSE 3000
|
|
|
208
317
|
# Arrancamos directamente con Node
|
|
209
318
|
CMD ["node", "server.js"]
|
|
210
319
|
`;
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
// ========== LÓGICA PARA EXPRESS ==========
|
|
323
|
+
// Paso 1: Instalar dependencias de producción si es necesario
|
|
324
|
+
if (!options.skipBuild) {
|
|
325
|
+
const installSpinner = (0, ora_1.default)('Installing production dependencies...').start();
|
|
326
|
+
try {
|
|
327
|
+
// Verificar si node_modules existe
|
|
328
|
+
const nodeModulesPath = path.join(resolvedProjectPath, 'node_modules');
|
|
329
|
+
if (!fs.existsSync(nodeModulesPath)) {
|
|
330
|
+
(0, child_process_1.execSync)('npm install --production', {
|
|
331
|
+
cwd: resolvedProjectPath,
|
|
332
|
+
stdio: 'pipe'
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
installSpinner.succeed('Dependencies ready');
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
installSpinner.fail('Failed to install dependencies');
|
|
339
|
+
console.error(chalk_1.default.red('Error installing dependencies'));
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// Paso 2: Copiar archivos del proyecto (sin node_modules, Docker lo instalará)
|
|
344
|
+
const copySpinner = (0, ora_1.default)('Copying project files...').start();
|
|
345
|
+
// Copiar todos los archivos excepto los que están en .dockerignore
|
|
346
|
+
const ignorePatterns = [
|
|
347
|
+
'node_modules',
|
|
348
|
+
'.git',
|
|
349
|
+
'.next',
|
|
350
|
+
'dist',
|
|
351
|
+
'build',
|
|
352
|
+
'.env',
|
|
353
|
+
'.env.local',
|
|
354
|
+
'.env.*.local',
|
|
355
|
+
'npm-debug.log*',
|
|
356
|
+
'yarn-debug.log*',
|
|
357
|
+
'yarn-error.log*',
|
|
358
|
+
'.DS_Store',
|
|
359
|
+
'coverage',
|
|
360
|
+
'.nyc_output',
|
|
361
|
+
];
|
|
362
|
+
function shouldIgnore(filePath, basePath) {
|
|
363
|
+
const relativePath = path.relative(basePath, filePath);
|
|
364
|
+
return ignorePatterns.some(pattern => {
|
|
365
|
+
if (relativePath.includes(pattern))
|
|
366
|
+
return true;
|
|
367
|
+
// Verificar si es un archivo que empieza con el patrón
|
|
368
|
+
const parts = relativePath.split(path.sep);
|
|
369
|
+
return parts.some(part => part === pattern || part.startsWith(pattern));
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
function copyProjectFiles(src, dest) {
|
|
373
|
+
if (!fs.existsSync(dest)) {
|
|
374
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
375
|
+
}
|
|
376
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
377
|
+
for (const entry of entries) {
|
|
378
|
+
const srcPath = path.join(src, entry.name);
|
|
379
|
+
const destPath = path.join(dest, entry.name);
|
|
380
|
+
// Ignorar archivos y directorios según los patrones
|
|
381
|
+
if (shouldIgnore(srcPath, resolvedProjectPath)) {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
try {
|
|
385
|
+
const stats = fs.lstatSync(srcPath);
|
|
386
|
+
if (stats.isDirectory()) {
|
|
387
|
+
copyProjectFiles(srcPath, destPath);
|
|
388
|
+
}
|
|
389
|
+
else if (stats.isFile()) {
|
|
390
|
+
fs.copyFileSync(srcPath, destPath);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
catch (error) {
|
|
394
|
+
// Ignorar errores al copiar archivos especiales
|
|
395
|
+
if (error.code === 'ENOTSUP' || error.code === 'EINVAL' || error.code === 'EOPNOTSUPP') {
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
throw error;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
// Copiar archivos del proyecto
|
|
403
|
+
copyProjectFiles(resolvedProjectPath, resolvedDestFolder);
|
|
404
|
+
// Verificar que existe package.json en el destino
|
|
405
|
+
const destPackageJson = path.join(resolvedDestFolder, 'package.json');
|
|
406
|
+
if (!fs.existsSync(destPackageJson)) {
|
|
407
|
+
copySpinner.fail('package.json not found');
|
|
408
|
+
console.error(chalk_1.default.red('❌ Error: package.json is required for Express application'));
|
|
409
|
+
process.exit(1);
|
|
410
|
+
}
|
|
411
|
+
// Verificar que existe un archivo principal
|
|
412
|
+
const packageJson = JSON.parse(fs.readFileSync(destPackageJson, 'utf-8'));
|
|
413
|
+
const mainFile = packageJson.main || 'index.js';
|
|
414
|
+
const mainFilePath = path.join(resolvedDestFolder, mainFile);
|
|
415
|
+
if (!fs.existsSync(mainFilePath)) {
|
|
416
|
+
// Buscar otros archivos comunes
|
|
417
|
+
const commonFiles = ['index.js', 'server.js', 'app.js', 'main.js'];
|
|
418
|
+
let found = false;
|
|
419
|
+
for (const file of commonFiles) {
|
|
420
|
+
if (fs.existsSync(path.join(resolvedDestFolder, file))) {
|
|
421
|
+
found = true;
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (!found) {
|
|
426
|
+
copySpinner.fail(`Main entry file not found: ${mainFile}`);
|
|
427
|
+
console.error(chalk_1.default.red(`❌ Error: Could not find main entry file (${mainFile}) for Express application`));
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
copySpinner.succeed('Files copied successfully');
|
|
432
|
+
// Leer y procesar archivo .env si existe
|
|
433
|
+
// (envFilePath ya está definido arriba)
|
|
434
|
+
if (fs.existsSync(envFilePath)) {
|
|
435
|
+
const envContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
436
|
+
const envLines = envContent.split('\n');
|
|
437
|
+
for (const line of envLines) {
|
|
438
|
+
const trimmed = line.trim();
|
|
439
|
+
// Ignorar comentarios y líneas vacías
|
|
440
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
441
|
+
continue;
|
|
442
|
+
const equalIndex = trimmed.indexOf('=');
|
|
443
|
+
if (equalIndex === -1)
|
|
444
|
+
continue;
|
|
445
|
+
const key = trimmed.substring(0, equalIndex).trim();
|
|
446
|
+
const value = trimmed.substring(equalIndex + 1).trim();
|
|
447
|
+
runtimeEnvVars.push(`${key}=${value}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
// Crear Dockerfile optimizado para Express
|
|
451
|
+
// (destPackageJson, packageJson y mainFile ya están declaradas arriba)
|
|
452
|
+
const startScript = packageJson.scripts?.start;
|
|
453
|
+
// Determinar el comando de inicio
|
|
454
|
+
let startCmd;
|
|
455
|
+
if (startScript) {
|
|
456
|
+
// Si hay un script start, usarlo
|
|
457
|
+
startCmd = startScript.split(' ');
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
// Si no, usar node con el archivo principal
|
|
461
|
+
startCmd = ['node', mainFile];
|
|
462
|
+
}
|
|
463
|
+
dockerfileContent = `FROM node:20-alpine
|
|
464
|
+
|
|
465
|
+
WORKDIR /app
|
|
466
|
+
|
|
467
|
+
ENV NODE_ENV=production
|
|
468
|
+
ENV PORT=3000
|
|
469
|
+
|
|
470
|
+
# Copiar package files primero para aprovechar cache de Docker
|
|
471
|
+
COPY package*.json ./
|
|
472
|
+
|
|
473
|
+
# Instalar solo dependencias de producción
|
|
474
|
+
RUN npm ci --only=production && npm cache clean --force
|
|
475
|
+
|
|
476
|
+
# Copiar código fuente
|
|
477
|
+
COPY . .
|
|
478
|
+
|
|
479
|
+
# Exponemos el puerto
|
|
480
|
+
EXPOSE 3000
|
|
481
|
+
|
|
482
|
+
# Comando de inicio
|
|
483
|
+
CMD ${JSON.stringify(startCmd)}
|
|
484
|
+
`;
|
|
485
|
+
}
|
|
486
|
+
// Paso 3: Crear Dockerfile
|
|
487
|
+
const dockerfileSpinner = (0, ora_1.default)('Creating Dockerfile...').start();
|
|
488
|
+
const dockerfilePath = path.join(resolvedDestFolder, 'Dockerfile');
|
|
211
489
|
fs.writeFileSync(dockerfilePath, dockerfileContent);
|
|
490
|
+
dockerfileSpinner.succeed('Dockerfile created');
|
|
491
|
+
// Mostrar contenido del Dockerfile
|
|
492
|
+
if (projectType === 'nextjs' && nextPublicEnvVars.length > 0) {
|
|
493
|
+
console.log(chalk_1.default.gray('\n📄 Dockerfile content:'));
|
|
494
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
495
|
+
console.log(chalk_1.default.white(dockerfileContent));
|
|
496
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
497
|
+
console.log(chalk_1.default.gray(`\n NEXT_PUBLIC_* variables: ${chalk_1.default.cyan(nextPublicEnvVars.length)}`));
|
|
498
|
+
nextPublicEnvVars.forEach(env => {
|
|
499
|
+
const [key] = env.split('=');
|
|
500
|
+
console.log(chalk_1.default.gray(` - ${chalk_1.default.cyan(key)}`));
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
console.log(chalk_1.default.gray(`\n📄 Dockerfile created for ${projectType} application`));
|
|
505
|
+
}
|
|
212
506
|
// Paso 4: Verificar/crear builder multi-plataforma
|
|
213
507
|
const builderSpinner = (0, ora_1.default)('Setting up multi-platform builder...').start();
|
|
214
508
|
try {
|
|
215
|
-
|
|
509
|
+
// Listar builders disponibles, ignorando errores de builders con problemas
|
|
510
|
+
let buildersOutput = '';
|
|
511
|
+
try {
|
|
512
|
+
// Redirigir stderr a /dev/null para ignorar errores de builders problemáticos
|
|
513
|
+
buildersOutput = (0, child_process_1.execSync)('docker buildx ls 2>/dev/null', {
|
|
514
|
+
encoding: 'utf-8',
|
|
515
|
+
stdio: 'pipe',
|
|
516
|
+
shell: '/bin/sh',
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
catch (error) {
|
|
520
|
+
// Si hay errores al listar builders (por ejemplo, builder "cc" con problemas SSH),
|
|
521
|
+
// intentar continuar de todas formas
|
|
522
|
+
console.log(chalk_1.default.yellow('⚠️ Warning: Some builders have connection issues, continuing...'));
|
|
523
|
+
}
|
|
216
524
|
const builderName = 'multiarch-builder';
|
|
217
|
-
if (!
|
|
218
|
-
|
|
525
|
+
if (!buildersOutput.includes(builderName)) {
|
|
526
|
+
builderSpinner.text = 'Creating multi-platform builder...';
|
|
527
|
+
(0, child_process_1.execSync)(`docker buildx create --name ${builderName} --use --bootstrap`, {
|
|
528
|
+
stdio: 'pipe',
|
|
529
|
+
// No heredar stderr para evitar errores de otros builders
|
|
530
|
+
});
|
|
219
531
|
}
|
|
220
532
|
else {
|
|
221
|
-
|
|
533
|
+
builderSpinner.text = 'Using existing multi-platform builder...';
|
|
534
|
+
try {
|
|
535
|
+
(0, child_process_1.execSync)(`docker buildx use ${builderName}`, { stdio: 'pipe' });
|
|
536
|
+
}
|
|
537
|
+
catch (error) {
|
|
538
|
+
// Si falla, intentar crearlo de nuevo
|
|
539
|
+
builderSpinner.text = 'Recreating multi-platform builder...';
|
|
540
|
+
try {
|
|
541
|
+
(0, child_process_1.execSync)(`docker buildx rm ${builderName}`, { stdio: 'pipe' });
|
|
542
|
+
}
|
|
543
|
+
catch {
|
|
544
|
+
// Ignorar si no existe
|
|
545
|
+
}
|
|
546
|
+
(0, child_process_1.execSync)(`docker buildx create --name ${builderName} --use --bootstrap`, { stdio: 'pipe' });
|
|
547
|
+
}
|
|
222
548
|
}
|
|
223
549
|
builderSpinner.succeed('Builder ready');
|
|
224
550
|
}
|
|
225
551
|
catch (error) {
|
|
226
552
|
builderSpinner.fail('Failed to setup builder');
|
|
227
553
|
console.error(chalk_1.default.red('Error setting up Docker buildx builder'));
|
|
554
|
+
console.error(chalk_1.default.yellow('💡 Tip: If you have problematic builders configured, you can remove them with:'));
|
|
555
|
+
console.error(chalk_1.default.cyan(' docker buildx rm <builder-name>'));
|
|
556
|
+
console.error(chalk_1.default.yellow(' Or inspect them with: docker buildx inspect <builder-name>'));
|
|
228
557
|
process.exit(1);
|
|
229
558
|
}
|
|
230
559
|
// Verificar autenticación de Docker si se va a hacer push
|
|
@@ -261,13 +590,21 @@ CMD ["node", "server.js"]
|
|
|
261
590
|
${tags.join(' \\\n ')} \
|
|
262
591
|
--progress=plain \
|
|
263
592
|
.`;
|
|
593
|
+
console.log(chalk_1.default.gray('\n🔨 Build command:'));
|
|
594
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
595
|
+
console.log(chalk_1.default.cyan(buildCommand));
|
|
596
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
597
|
+
console.log(chalk_1.default.gray(`\n Working directory: ${chalk_1.default.cyan(resolvedDestFolder)}`));
|
|
598
|
+
console.log(chalk_1.default.gray(` Platforms: ${chalk_1.default.cyan('linux/amd64, linux/arm64')}`));
|
|
599
|
+
console.log(chalk_1.default.gray(` Push to registry: ${shouldPush ? chalk_1.default.green('Yes') : chalk_1.default.yellow('No')}\n`));
|
|
264
600
|
(0, child_process_1.execSync)(buildCommand, {
|
|
265
601
|
cwd: resolvedDestFolder,
|
|
266
602
|
stdio: 'inherit'
|
|
267
603
|
});
|
|
268
604
|
buildDockerSpinner.succeed('Docker image built successfully');
|
|
269
|
-
console.log(chalk_1.default.green('\n✅
|
|
270
|
-
console.log(chalk_1.default.gray('Image details:'));
|
|
605
|
+
console.log(chalk_1.default.green('\n✅ Image build and push completed successfully!'));
|
|
606
|
+
console.log(chalk_1.default.gray('📦 Image details:'));
|
|
607
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
271
608
|
console.log(chalk_1.default.white(` Platforms: ${chalk_1.default.cyan('linux/amd64, linux/arm64')}`));
|
|
272
609
|
console.log(chalk_1.default.white(` Version: ${chalk_1.default.cyan(version)}`));
|
|
273
610
|
console.log(chalk_1.default.white(` Tags:`));
|
|
@@ -276,6 +613,12 @@ CMD ["node", "server.js"]
|
|
|
276
613
|
if (shouldPush) {
|
|
277
614
|
console.log(chalk_1.default.white(` Registry: ${chalk_1.default.cyan('Docker Hub')}`));
|
|
278
615
|
console.log(chalk_1.default.white(` URL: ${chalk_1.default.cyan(`https://hub.docker.com/r/${imageBase}`)}`));
|
|
616
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
617
|
+
console.log(chalk_1.default.green(`\n✅ Image pushed to Docker Hub successfully!`));
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
621
|
+
console.log(chalk_1.default.yellow(`\n⚠️ Image built locally (not pushed to registry)`));
|
|
279
622
|
}
|
|
280
623
|
}
|
|
281
624
|
catch (error) {
|
|
@@ -288,8 +631,12 @@ CMD ["node", "server.js"]
|
|
|
288
631
|
}
|
|
289
632
|
// Paso 6: Desplegar en servidor remoto si se solicita
|
|
290
633
|
if (options.deploy) {
|
|
634
|
+
// Para despliegue, usar la versión especificada o la del package.json
|
|
635
|
+
const deployImageName = options.imageVersion
|
|
636
|
+
? `${imageBase}:${options.imageVersion}`
|
|
637
|
+
: (shouldPush ? imageName : imageLatest);
|
|
291
638
|
await deployToRemoteServer({
|
|
292
|
-
imageName:
|
|
639
|
+
imageName: deployImageName,
|
|
293
640
|
serviceName: options.serviceName || projectName,
|
|
294
641
|
domainBase: options.domainBase,
|
|
295
642
|
port: options.port,
|
|
@@ -303,16 +650,117 @@ CMD ["node", "server.js"]
|
|
|
303
650
|
process.exit(1);
|
|
304
651
|
}
|
|
305
652
|
});
|
|
653
|
+
// Función para leer certificados Docker desde token.json
|
|
654
|
+
function loadDockerCertificatesFromToken() {
|
|
655
|
+
const tokenFilePath = path.join(os.homedir(), '.codecrypto', 'token.json');
|
|
656
|
+
if (!fs.existsSync(tokenFilePath)) {
|
|
657
|
+
throw new Error(`Token file not found at ${tokenFilePath}. Please run 'codecrypto auth' first.`);
|
|
658
|
+
}
|
|
659
|
+
let tokenData;
|
|
660
|
+
try {
|
|
661
|
+
tokenData = JSON.parse(fs.readFileSync(tokenFilePath, 'utf-8'));
|
|
662
|
+
}
|
|
663
|
+
catch (error) {
|
|
664
|
+
throw new Error(`Failed to read token file: ${error.message}`);
|
|
665
|
+
}
|
|
666
|
+
if (!tokenData.adminGlobals || !Array.isArray(tokenData.adminGlobals)) {
|
|
667
|
+
throw new Error('adminGlobals not found in token.json. Please run "codecrypto auth --force" to refresh your token.');
|
|
668
|
+
}
|
|
669
|
+
// Buscar los certificados Docker en el array adminGlobals
|
|
670
|
+
// Las keys que buscamos son:
|
|
671
|
+
// - docker-client/ca-pem
|
|
672
|
+
// - docker-client/cert.pem
|
|
673
|
+
// - docker-client/key.pem
|
|
674
|
+
const certKeys = {
|
|
675
|
+
ca: 'docker-client/ca-pem',
|
|
676
|
+
cert: 'docker-client/cert.pem',
|
|
677
|
+
key: 'docker-client/key.pem'
|
|
678
|
+
};
|
|
679
|
+
const certificates = {};
|
|
680
|
+
// Lista de keys encontradas para debugging
|
|
681
|
+
const foundKeys = [];
|
|
682
|
+
// Iterar sobre adminGlobals para encontrar los certificados
|
|
683
|
+
for (const global of tokenData.adminGlobals) {
|
|
684
|
+
if (global && global.key) {
|
|
685
|
+
foundKeys.push(global.key);
|
|
686
|
+
// Buscar cada certificado por su key exacta
|
|
687
|
+
if (global.key === certKeys.ca) {
|
|
688
|
+
certificates.ca = global.value;
|
|
689
|
+
}
|
|
690
|
+
else if (global.key === certKeys.cert) {
|
|
691
|
+
certificates.cert = global.value;
|
|
692
|
+
}
|
|
693
|
+
else if (global.key === certKeys.key) {
|
|
694
|
+
certificates.key = global.value;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
// Verificar que todos los certificados estén presentes
|
|
699
|
+
if (!certificates.ca) {
|
|
700
|
+
const availableKeys = foundKeys.filter(k => k.includes('docker-client')).join(', ') || 'none';
|
|
701
|
+
throw new Error(`Certificate not found: ${certKeys.ca} in adminGlobals.\n` +
|
|
702
|
+
` Available docker-client keys: ${availableKeys || 'none'}\n` +
|
|
703
|
+
` Total adminGlobals entries: ${tokenData.adminGlobals.length}\n` +
|
|
704
|
+
` Please run "codecrypto auth --force" to refresh your token.`);
|
|
705
|
+
}
|
|
706
|
+
if (!certificates.cert) {
|
|
707
|
+
const availableKeys = foundKeys.filter(k => k.includes('docker-client')).join(', ') || 'none';
|
|
708
|
+
throw new Error(`Certificate not found: ${certKeys.cert} in adminGlobals.\n` +
|
|
709
|
+
` Available docker-client keys: ${availableKeys || 'none'}\n` +
|
|
710
|
+
` Total adminGlobals entries: ${tokenData.adminGlobals.length}\n` +
|
|
711
|
+
` Please run "codecrypto auth --force" to refresh your token.`);
|
|
712
|
+
}
|
|
713
|
+
if (!certificates.key) {
|
|
714
|
+
const availableKeys = foundKeys.filter(k => k.includes('docker-client')).join(', ') || 'none';
|
|
715
|
+
throw new Error(`Certificate not found: ${certKeys.key} in adminGlobals.\n` +
|
|
716
|
+
` Available docker-client keys: ${availableKeys || 'none'}\n` +
|
|
717
|
+
` Total adminGlobals entries: ${tokenData.adminGlobals.length}\n` +
|
|
718
|
+
` Please run "codecrypto auth --force" to refresh your token.`);
|
|
719
|
+
}
|
|
720
|
+
// Crear directorio para certificados si no existe
|
|
721
|
+
const dockerCertPath = path.join(os.homedir(), '.codecrypto', 'docker-client');
|
|
722
|
+
if (!fs.existsSync(dockerCertPath)) {
|
|
723
|
+
fs.mkdirSync(dockerCertPath, { recursive: true });
|
|
724
|
+
}
|
|
725
|
+
// Escribir certificados a archivos
|
|
726
|
+
const caPemPath = path.join(dockerCertPath, 'ca.pem');
|
|
727
|
+
const certPemPath = path.join(dockerCertPath, 'cert.pem');
|
|
728
|
+
const keyPemPath = path.join(dockerCertPath, 'key.pem');
|
|
729
|
+
fs.writeFileSync(caPemPath, certificates.ca, 'utf-8');
|
|
730
|
+
fs.writeFileSync(certPemPath, certificates.cert, 'utf-8');
|
|
731
|
+
fs.writeFileSync(keyPemPath, certificates.key, 'utf-8');
|
|
732
|
+
// Establecer permisos correctos para la clave privada (solo lectura para el propietario)
|
|
733
|
+
try {
|
|
734
|
+
fs.chmodSync(keyPemPath, 0o600);
|
|
735
|
+
}
|
|
736
|
+
catch (error) {
|
|
737
|
+
// Ignorar errores de chmod en Windows
|
|
738
|
+
}
|
|
739
|
+
return {
|
|
740
|
+
caPem: certificates.ca,
|
|
741
|
+
certPem: certificates.cert,
|
|
742
|
+
keyPem: certificates.key,
|
|
743
|
+
certPath: dockerCertPath
|
|
744
|
+
};
|
|
745
|
+
}
|
|
306
746
|
// Función para desplegar en servidor remoto
|
|
307
747
|
async function deployToRemoteServer(config) {
|
|
308
748
|
const deploySpinner = (0, ora_1.default)('Configuring remote Docker connection...').start();
|
|
309
749
|
try {
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
750
|
+
// Cargar certificados desde token.json
|
|
751
|
+
let dockerCertPath;
|
|
752
|
+
try {
|
|
753
|
+
const certs = loadDockerCertificatesFromToken();
|
|
754
|
+
dockerCertPath = certs.certPath;
|
|
755
|
+
deploySpinner.succeed('Docker certificates loaded from token.json');
|
|
756
|
+
}
|
|
757
|
+
catch (error) {
|
|
758
|
+
deploySpinner.fail('Failed to load Docker certificates');
|
|
759
|
+
console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
|
|
760
|
+
console.error(chalk_1.default.yellow('\n💡 To fix this issue:'));
|
|
761
|
+
console.error(chalk_1.default.yellow(' 1. Run: codecrypto auth --force'));
|
|
762
|
+
console.error(chalk_1.default.yellow(' 2. This will refresh your token with the latest adminGlobals'));
|
|
763
|
+
console.error(chalk_1.default.yellow(' 3. Then try the deploy command again\n'));
|
|
316
764
|
process.exit(1);
|
|
317
765
|
}
|
|
318
766
|
// Verificar que existen los certificados necesarios
|
|
@@ -325,43 +773,80 @@ async function deployToRemoteServer(config) {
|
|
|
325
773
|
process.exit(1);
|
|
326
774
|
}
|
|
327
775
|
}
|
|
328
|
-
//
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
776
|
+
// Construir prefijo de comando Docker con parámetros TLS
|
|
777
|
+
const dockerHost = 'tcp://server.codecrypto.academy:2376';
|
|
778
|
+
const dockerTlsPrefix = `docker -H ${dockerHost} \\
|
|
779
|
+
--tlsverify \\
|
|
780
|
+
--tlscacert="${path.join(dockerCertPath, 'ca.pem')}" \\
|
|
781
|
+
--tlscert="${path.join(dockerCertPath, 'cert.pem')}" \\
|
|
782
|
+
--tlskey="${path.join(dockerCertPath, 'key.pem')}"`;
|
|
783
|
+
console.log(chalk_1.default.gray('\n🔌 Remote Docker configuration:'));
|
|
784
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
785
|
+
console.log(chalk_1.default.white(` Docker Host: ${chalk_1.default.cyan(dockerHost)}`));
|
|
786
|
+
console.log(chalk_1.default.white(` TLS Verify: ${chalk_1.default.cyan('enabled')}`));
|
|
787
|
+
console.log(chalk_1.default.white(` Certificates Source: ${chalk_1.default.cyan('token.json (adminGlobals)')}`));
|
|
788
|
+
console.log(chalk_1.default.white(` Certificates Path: ${chalk_1.default.cyan(dockerCertPath)}`));
|
|
789
|
+
console.log(chalk_1.default.gray(' Certificates loaded:'));
|
|
790
|
+
requiredCerts.forEach(cert => {
|
|
791
|
+
const certPath = path.join(dockerCertPath, cert);
|
|
792
|
+
const exists = fs.existsSync(certPath);
|
|
793
|
+
console.log(chalk_1.default.gray(` ${exists ? '✓' : '✗'} ${chalk_1.default.cyan(cert)}`));
|
|
794
|
+
});
|
|
795
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
796
|
+
console.log(chalk_1.default.yellow('\n💡 All docker commands will use TLS parameters directly\n'));
|
|
336
797
|
// Construir nombre completo del dominio
|
|
337
798
|
const fullDomain = `${config.serviceName}.${config.domainBase}`;
|
|
338
799
|
const serviceName = config.serviceName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
339
800
|
// Detener y eliminar contenedor existente si existe
|
|
340
|
-
const stopSpinner = (0, ora_1.default)('Checking
|
|
801
|
+
const stopSpinner = (0, ora_1.default)('Checking and removing existing container...').start();
|
|
341
802
|
try {
|
|
342
|
-
|
|
343
|
-
|
|
803
|
+
// Verificar si el contenedor existe
|
|
804
|
+
const checkCmd = `${dockerTlsPrefix} ps -a --filter name=^${fullDomain}$ --format "{{.Names}}"`;
|
|
805
|
+
const existingContainer = (0, child_process_1.execSync)(checkCmd, {
|
|
344
806
|
stdio: 'pipe',
|
|
345
807
|
encoding: 'utf-8',
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
808
|
+
shell: '/bin/sh',
|
|
809
|
+
}).trim();
|
|
810
|
+
if (existingContainer === fullDomain) {
|
|
811
|
+
// Contenedor existe, detenerlo primero (si está corriendo)
|
|
812
|
+
try {
|
|
813
|
+
const stopCmd = `${dockerTlsPrefix} stop ${fullDomain}`;
|
|
814
|
+
(0, child_process_1.execSync)(stopCmd, { stdio: 'pipe', shell: '/bin/sh' });
|
|
815
|
+
console.log(chalk_1.default.gray(` ✓ Container ${fullDomain} stopped`));
|
|
816
|
+
}
|
|
817
|
+
catch (error) {
|
|
818
|
+
// Container might not be running, that's okay
|
|
819
|
+
console.log(chalk_1.default.gray(` ℹ Container ${fullDomain} was not running`));
|
|
820
|
+
}
|
|
821
|
+
// Eliminar el contenedor
|
|
822
|
+
try {
|
|
823
|
+
const rmCmd = `${dockerTlsPrefix} rm -f ${fullDomain}`;
|
|
824
|
+
(0, child_process_1.execSync)(rmCmd, { stdio: 'pipe', shell: '/bin/sh' });
|
|
825
|
+
stopSpinner.succeed(`Existing container ${fullDomain} removed`);
|
|
826
|
+
}
|
|
827
|
+
catch (error) {
|
|
828
|
+
stopSpinner.fail(`Failed to remove container ${fullDomain}`);
|
|
829
|
+
console.error(chalk_1.default.red(` Error: ${error.message}`));
|
|
830
|
+
process.exit(1);
|
|
831
|
+
}
|
|
350
832
|
}
|
|
351
|
-
|
|
352
|
-
|
|
833
|
+
else {
|
|
834
|
+
stopSpinner.succeed('No existing container found');
|
|
353
835
|
}
|
|
836
|
+
}
|
|
837
|
+
catch (error) {
|
|
838
|
+
// Si el comando falla, puede ser que el contenedor no exista
|
|
839
|
+
// Intentar eliminarlo de todas formas con -f para forzar
|
|
354
840
|
try {
|
|
355
|
-
|
|
356
|
-
|
|
841
|
+
const forceRmCmd = `${dockerTlsPrefix} rm -f ${fullDomain}`;
|
|
842
|
+
(0, child_process_1.execSync)(forceRmCmd, { stdio: 'pipe', shell: '/bin/sh' });
|
|
843
|
+
stopSpinner.succeed('Existing container removed (forced)');
|
|
357
844
|
}
|
|
358
845
|
catch {
|
|
359
|
-
|
|
846
|
+
// Si falla, asumir que no existe y continuar
|
|
847
|
+
stopSpinner.succeed('No existing container found');
|
|
360
848
|
}
|
|
361
849
|
}
|
|
362
|
-
catch (error) {
|
|
363
|
-
stopSpinner.warn('Could not check for existing container');
|
|
364
|
-
}
|
|
365
850
|
// Preparar opciones de entorno
|
|
366
851
|
// Para despliegue remoto, pasamos las variables directamente con -e
|
|
367
852
|
// ya que --env-file requiere que el archivo esté en el servidor remoto
|
|
@@ -376,33 +861,56 @@ async function deployToRemoteServer(config) {
|
|
|
376
861
|
envOpts.push(`-e "${key}=${escapedValue}"`);
|
|
377
862
|
});
|
|
378
863
|
}
|
|
379
|
-
// Construir comando docker run
|
|
380
|
-
const dockerRunCmd =
|
|
864
|
+
// Construir comando docker run con parámetros TLS
|
|
865
|
+
const dockerRunCmd = `${dockerTlsPrefix} run -d \\
|
|
381
866
|
--name ${fullDomain} \\
|
|
382
867
|
--network academy-network \\
|
|
383
868
|
--restart unless-stopped \\
|
|
384
|
-
${envOpts.join(' \\\n ')
|
|
869
|
+
${envOpts.length > 0 ? envOpts.join(' \\\n ') + ' \\' : ''}
|
|
385
870
|
-l traefik.enable=true \\
|
|
386
871
|
-l "traefik.http.routers.${serviceName}-router.rule=Host(\\\`${fullDomain}\\\`)" \\
|
|
387
872
|
-l traefik.http.routers.${serviceName}-router.entrypoints=websecure \\
|
|
388
873
|
-l traefik.http.routers.${serviceName}-router.tls=true \\
|
|
389
874
|
-l traefik.http.services.${serviceName}-service.loadbalancer.server.port=${config.port} \\
|
|
390
875
|
${config.imageName}`;
|
|
876
|
+
console.log(chalk_1.default.gray('\n🚀 Deployment command (executing on remote Docker):'));
|
|
877
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
878
|
+
console.log(chalk_1.default.cyan(dockerRunCmd));
|
|
879
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
880
|
+
console.log(chalk_1.default.gray(`\n Remote Docker: ${chalk_1.default.cyan(dockerHost)}`));
|
|
881
|
+
console.log(chalk_1.default.gray(` TLS Certificates: ${chalk_1.default.cyan(dockerCertPath)}`));
|
|
882
|
+
console.log(chalk_1.default.gray(` Service name: ${chalk_1.default.cyan(config.serviceName)}`));
|
|
883
|
+
console.log(chalk_1.default.gray(` Full domain: ${chalk_1.default.cyan(fullDomain)}`));
|
|
884
|
+
console.log(chalk_1.default.gray(` Image: ${chalk_1.default.cyan(config.imageName)}`));
|
|
885
|
+
console.log(chalk_1.default.gray(` Port: ${chalk_1.default.cyan(config.port)}`));
|
|
886
|
+
console.log(chalk_1.default.gray(` Environment variables: ${chalk_1.default.cyan(config.envVars.length)}`));
|
|
887
|
+
if (config.envVars.length > 0) {
|
|
888
|
+
config.envVars.forEach(env => {
|
|
889
|
+
const [key] = env.split('=');
|
|
890
|
+
console.log(chalk_1.default.gray(` - ${chalk_1.default.cyan(key)}`));
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
391
894
|
const runSpinner = (0, ora_1.default)('Deploying container to remote server...').start();
|
|
392
895
|
try {
|
|
896
|
+
// Ejecutar comando docker con parámetros TLS directamente
|
|
393
897
|
(0, child_process_1.execSync)(dockerRunCmd, {
|
|
394
|
-
env: dockerEnv,
|
|
395
898
|
stdio: 'inherit',
|
|
396
899
|
shell: '/bin/sh',
|
|
397
900
|
});
|
|
398
901
|
runSpinner.succeed('Container deployed successfully');
|
|
399
902
|
console.log(chalk_1.default.green('\n✅ Remote deployment completed successfully!'));
|
|
400
|
-
console.log(chalk_1.default.gray('Deployment details:'));
|
|
903
|
+
console.log(chalk_1.default.gray('📋 Deployment details:'));
|
|
904
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
401
905
|
console.log(chalk_1.default.white(` Service: ${chalk_1.default.cyan(config.serviceName)}`));
|
|
402
906
|
console.log(chalk_1.default.white(` Domain: ${chalk_1.default.cyan(fullDomain)}`));
|
|
403
907
|
console.log(chalk_1.default.white(` URL: ${chalk_1.default.cyan(`https://${fullDomain}`)}`));
|
|
404
908
|
console.log(chalk_1.default.white(` Image: ${chalk_1.default.cyan(config.imageName)}`));
|
|
405
909
|
console.log(chalk_1.default.white(` Port: ${chalk_1.default.cyan(config.port)}`));
|
|
910
|
+
console.log(chalk_1.default.white(` Network: ${chalk_1.default.cyan('academy-network')}`));
|
|
911
|
+
console.log(chalk_1.default.white(` Restart policy: ${chalk_1.default.cyan('unless-stopped')}`));
|
|
912
|
+
console.log(chalk_1.default.gray('─'.repeat(60)));
|
|
913
|
+
console.log(chalk_1.default.green(`\n🌐 Your application is now available at: ${chalk_1.default.cyan.underline(`https://${fullDomain}`)}`));
|
|
406
914
|
}
|
|
407
915
|
catch (error) {
|
|
408
916
|
runSpinner.fail('Failed to deploy container');
|