@geekmidas/cli 9.0.2 → 10.0.0-alpha.1
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/README.md +66 -122
- package/dist/{CachedStateProvider-BdX7klRc.cjs → CachedStateProvider-BLo7zv7S.cjs} +1 -1
- package/dist/CachedStateProvider-BxoAm-B2.mjs +3 -0
- package/dist/{CachedStateProvider-klLWZXWF.cjs → CachedStateProvider-CqPdW7CB.cjs} +1 -1
- package/dist/{CachedStateProvider-klLWZXWF.cjs.map → CachedStateProvider-CqPdW7CB.cjs.map} +1 -1
- package/dist/{CachedStateProvider-CzyFct42.mjs → CachedStateProvider-DTniehMP.mjs} +1 -1
- package/dist/{CachedStateProvider-CzyFct42.mjs.map → CachedStateProvider-DTniehMP.mjs.map} +1 -1
- package/dist/{HostingerProvider-B2ZYz7Yc.mjs → HostingerProvider-Cft7lEYr.mjs} +4 -3
- package/dist/HostingerProvider-Cft7lEYr.mjs.map +1 -0
- package/dist/{HostingerProvider-CrHfsgz9.cjs → HostingerProvider-h3EbEp-Z.cjs} +4 -3
- package/dist/HostingerProvider-h3EbEp-Z.cjs.map +1 -0
- package/dist/{LocalStateProvider-CP49rjzt.mjs → LocalStateProvider-Bn6tS-oL.mjs} +1 -1
- package/dist/{LocalStateProvider-CP49rjzt.mjs.map → LocalStateProvider-Bn6tS-oL.mjs.map} +1 -1
- package/dist/{LocalStateProvider-CalzNfNA.cjs → LocalStateProvider-Db9SEjyH.cjs} +1 -1
- package/dist/{LocalStateProvider-CalzNfNA.cjs.map → LocalStateProvider-Db9SEjyH.cjs.map} +1 -1
- package/dist/{Route53Provider-tlgBzrRQ.mjs → Route53Provider-RdpUDJQk.mjs} +1 -1
- package/dist/{Route53Provider-tlgBzrRQ.mjs.map → Route53Provider-RdpUDJQk.mjs.map} +1 -1
- package/dist/{Route53Provider-DwgXiLxt.cjs → Route53Provider-di2fMM5N.cjs} +1 -1
- package/dist/{Route53Provider-DwgXiLxt.cjs.map → Route53Provider-di2fMM5N.cjs.map} +1 -1
- package/dist/{SSMStateProvider-BlrTiV5m.mjs → SSMStateProvider-BRt2py-A.mjs} +1 -1
- package/dist/{SSMStateProvider-BlrTiV5m.mjs.map → SSMStateProvider-BRt2py-A.mjs.map} +1 -1
- package/dist/{SSMStateProvider-Bt6r8CTL.cjs → SSMStateProvider-DyX8s9HI.cjs} +1 -1
- package/dist/{SSMStateProvider-Bt6r8CTL.cjs.map → SSMStateProvider-DyX8s9HI.cjs.map} +1 -1
- package/dist/{backup-provisioner-Xunq-p_8.mjs → backup-provisioner-Bgj5Vi_L.mjs} +2 -2
- package/dist/{backup-provisioner-Xunq-p_8.mjs.map → backup-provisioner-Bgj5Vi_L.mjs.map} +1 -1
- package/dist/{backup-provisioner-B3HBN-2k.cjs → backup-provisioner-BrsHwYG0.cjs} +2 -2
- package/dist/{backup-provisioner-B3HBN-2k.cjs.map → backup-provisioner-BrsHwYG0.cjs.map} +1 -1
- package/dist/{bundler-Dufq3uvI.cjs → bundler-BY1OmV1e.cjs} +44 -14
- package/dist/bundler-BY1OmV1e.cjs.map +1 -0
- package/dist/{bundler-DkA4qzUD.mjs → bundler-Be8Zg4Wd.mjs} +45 -15
- package/dist/bundler-Be8Zg4Wd.mjs.map +1 -0
- package/dist/config-D8o6I_7Z.mjs +469 -0
- package/dist/config-D8o6I_7Z.mjs.map +1 -0
- package/dist/config-DbPE1KXF.cjs +535 -0
- package/dist/config-DbPE1KXF.cjs.map +1 -0
- package/dist/config.cjs +3 -2
- package/dist/config.d.cts +2 -2
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +2 -2
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -2
- package/dist/{credentials-s1kLcIzK.mjs → credentials-B5zRHdAl.mjs} +21 -6
- package/dist/credentials-B5zRHdAl.mjs.map +1 -0
- package/dist/{credentials-C8DWtnMY.cjs → credentials-BapzjyV5.cjs} +26 -5
- package/dist/credentials-BapzjyV5.cjs.map +1 -0
- package/dist/credentials-Dh0Q6HzY.mjs +2548 -0
- package/dist/credentials-Dh0Q6HzY.mjs.map +1 -0
- package/dist/credentials-K961ThG3.cjs +2680 -0
- package/dist/credentials-K961ThG3.cjs.map +1 -0
- package/dist/deploy/sniffer-routes-worker.cjs +6 -2
- package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.mjs +6 -2
- package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
- package/dist/discover-CAlFgYec.mjs +229 -0
- package/dist/discover-CAlFgYec.mjs.map +1 -0
- package/dist/discover-DTmFeloL.cjs +271 -0
- package/dist/discover-DTmFeloL.cjs.map +1 -0
- package/dist/dokploy-api-BS2xnJLZ.mjs +3 -0
- package/dist/{dokploy-api-CqOIKHme.cjs → dokploy-api-BsVH0y_s.cjs} +141 -32
- package/dist/dokploy-api-BsVH0y_s.cjs.map +1 -0
- package/dist/dokploy-api-BuxDRo3l.cjs +3 -0
- package/dist/{dokploy-api-sfZFlWuE.mjs → dokploy-api-aTFPz7_4.mjs} +141 -32
- package/dist/dokploy-api-aTFPz7_4.mjs.map +1 -0
- package/dist/emit-CbcRolsa.cjs +236 -0
- package/dist/emit-CbcRolsa.cjs.map +1 -0
- package/dist/emit-CiZS_5Ub.mjs +206 -0
- package/dist/emit-CiZS_5Ub.mjs.map +1 -0
- package/dist/{encryption-MfXAiFTm.cjs → encryption-C6jaU0hE.cjs} +1 -1
- package/dist/{encryption-MfXAiFTm.cjs.map → encryption-C6jaU0hE.cjs.map} +1 -1
- package/dist/{encryption-BVS7Vmzs.cjs → encryption-CHzzeR8a.cjs} +1 -1
- package/dist/encryption-CQUncu7v.mjs +3 -0
- package/dist/{encryption-CO5Q4Bhf.mjs → encryption-D-abyhZx.mjs} +1 -1
- package/dist/{encryption-CO5Q4Bhf.mjs.map → encryption-D-abyhZx.mjs.map} +1 -1
- package/dist/fullstack-secrets-C-GGohke.cjs +111 -0
- package/dist/fullstack-secrets-C-GGohke.cjs.map +1 -0
- package/dist/fullstack-secrets-D1o9-G5l.mjs +87 -0
- package/dist/fullstack-secrets-D1o9-G5l.mjs.map +1 -0
- package/dist/{fullstack-secrets-BYzi6Hwl.cjs → generator-CNzBw7g5.cjs} +1 -114
- package/dist/generator-CNzBw7g5.cjs.map +1 -0
- package/dist/{fullstack-secrets-l8s3II_H.mjs → generator-VE2JrFlY.mjs} +2 -85
- package/dist/generator-VE2JrFlY.mjs.map +1 -0
- package/dist/index-BThUzEIp.d.mts +175 -0
- package/dist/index-BThUzEIp.d.mts.map +1 -0
- package/dist/index-CHB4tSzX.d.cts +175 -0
- package/dist/index-CHB4tSzX.d.cts.map +1 -0
- package/dist/index.cjs +2530 -1810
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2506 -1786
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-Cfwi0fqF.mjs → openapi-CgpMWMmM.mjs} +174 -95
- package/dist/openapi-CgpMWMmM.mjs.map +1 -0
- package/dist/{openapi-BzNOC7_i.cjs → openapi-CljONd_M.cjs} +175 -108
- package/dist/openapi-CljONd_M.cjs.map +1 -0
- package/dist/{openapi-react-query-C4iIvpPf.mjs → openapi-react-query-Byltvm_7.mjs} +2 -2
- package/dist/openapi-react-query-Byltvm_7.mjs.map +1 -0
- package/dist/{openapi-react-query-CYWik72n.cjs → openapi-react-query-CmJ1xDbn.cjs} +2 -2
- package/dist/openapi-react-query-CmJ1xDbn.cjs.map +1 -0
- package/dist/openapi-react-query.cjs +1 -1
- package/dist/openapi-react-query.mjs +1 -1
- package/dist/openapi.cjs +4 -3
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +4 -3
- package/dist/reconcile/public.cjs +9 -0
- package/dist/reconcile/public.d.cts +125 -0
- package/dist/reconcile/public.d.cts.map +1 -0
- package/dist/reconcile/public.d.mts +125 -0
- package/dist/reconcile/public.d.mts.map +1 -0
- package/dist/reconcile/public.mjs +4 -0
- package/dist/{reconcile-B2FoJE0a.mjs → reconcile-CFs8C_1a.mjs} +5 -4
- package/dist/reconcile-CFs8C_1a.mjs.map +1 -0
- package/dist/{reconcile-BzqKJ2Rt.cjs → reconcile-D0pimNiy.cjs} +5 -4
- package/dist/reconcile-D0pimNiy.cjs.map +1 -0
- package/dist/setup-CJiQM2pX.cjs +473 -0
- package/dist/setup-CJiQM2pX.cjs.map +1 -0
- package/dist/setup-DMtU3p41.cjs +11 -0
- package/dist/setup-DOsYueeQ.mjs +443 -0
- package/dist/setup-DOsYueeQ.mjs.map +1 -0
- package/dist/setup-DSutDAlt.mjs +11 -0
- package/dist/{storage-B1wvztiJ.cjs → storage-BJmzYxt8.cjs} +1 -1
- package/dist/{storage-B1wvztiJ.cjs.map → storage-BJmzYxt8.cjs.map} +1 -1
- package/dist/{storage-DOEtT2Hr.cjs → storage-BM9hGpgv.cjs} +1 -1
- package/dist/{storage-dbb9RyBl.mjs → storage-Bi24WfoW.mjs} +1 -1
- package/dist/{storage-dbb9RyBl.mjs.map → storage-Bi24WfoW.mjs.map} +1 -1
- package/dist/{storage-Cs4WBsc4.mjs → storage-CYlGwWTj.mjs} +1 -1
- package/dist/{sync-CSooqRQ8.mjs → sync-CmEuNZsB.mjs} +2 -2
- package/dist/{sync-CSooqRQ8.mjs.map → sync-CmEuNZsB.mjs.map} +1 -1
- package/dist/sync-D306yOWu.cjs +4 -0
- package/dist/{sync-o_CtEbvR.cjs → sync-SizaChmC.cjs} +2 -2
- package/dist/{sync-o_CtEbvR.cjs.map → sync-SizaChmC.cjs.map} +1 -1
- package/dist/{sync-B5UHXwRM.mjs → sync-hOqAWHR6.mjs} +1 -1
- package/dist/{index-Bw548Bta.d.mts → types-C-arnQ1r.d.mts} +590 -143
- package/dist/types-C-arnQ1r.d.mts.map +1 -0
- package/dist/{index-DTpkeFb8.d.cts → types-abJQuk7m.d.cts} +590 -143
- package/dist/types-abJQuk7m.d.cts.map +1 -0
- package/dist/workspace/index.cjs +5 -1
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -2
- package/dist/{workspace-D-37Ylqo.mjs → workspace-7FqprxuJ.mjs} +117 -30
- package/dist/workspace-7FqprxuJ.mjs.map +1 -0
- package/dist/workspace-8acupeaI.cjs +9 -0
- package/dist/{workspace-CQTT7HJQ.cjs → workspace-XvqO9jIv.cjs} +139 -28
- package/dist/workspace-XvqO9jIv.cjs.map +1 -0
- package/dist/workspace-yP5AHnrn.mjs +8 -0
- package/package.json +26 -9
- package/CHANGELOG.md +0 -650
- package/FUNCTION_CRON_SUPPORT.md +0 -266
- package/dist/CachedStateProvider-GcGziXh1.mjs +0 -3
- package/dist/HostingerProvider-B2ZYz7Yc.mjs.map +0 -1
- package/dist/HostingerProvider-CrHfsgz9.cjs.map +0 -1
- package/dist/bundler-DkA4qzUD.mjs.map +0 -1
- package/dist/bundler-Dufq3uvI.cjs.map +0 -1
- package/dist/config-Bbu1JKvf.mjs +0 -211
- package/dist/config-Bbu1JKvf.mjs.map +0 -1
- package/dist/config-DujV8DbR.cjs +0 -253
- package/dist/config-DujV8DbR.cjs.map +0 -1
- package/dist/credentials-C8DWtnMY.cjs.map +0 -1
- package/dist/credentials-s1kLcIzK.mjs.map +0 -1
- package/dist/dokploy-api-BPYkG-ZZ.cjs +0 -3
- package/dist/dokploy-api-BiSzWM4v.mjs +0 -3
- package/dist/dokploy-api-CqOIKHme.cjs.map +0 -1
- package/dist/dokploy-api-sfZFlWuE.mjs.map +0 -1
- package/dist/encryption-Bd_m4q3g.mjs +0 -3
- package/dist/fullstack-secrets-BYzi6Hwl.cjs.map +0 -1
- package/dist/fullstack-secrets-l8s3II_H.mjs.map +0 -1
- package/dist/index-Bw548Bta.d.mts.map +0 -1
- package/dist/index-DTpkeFb8.d.cts.map +0 -1
- package/dist/openapi-BzNOC7_i.cjs.map +0 -1
- package/dist/openapi-Cfwi0fqF.mjs.map +0 -1
- package/dist/openapi-react-query-C4iIvpPf.mjs.map +0 -1
- package/dist/openapi-react-query-CYWik72n.cjs.map +0 -1
- package/dist/reconcile-B2FoJE0a.mjs.map +0 -1
- package/dist/reconcile-BzqKJ2Rt.cjs.map +0 -1
- package/dist/setup-DDXUXzzl.mjs +0 -765
- package/dist/setup-DDXUXzzl.mjs.map +0 -1
- package/dist/setup-DLwhfyt-.cjs +0 -8
- package/dist/setup-Dh-B7YTX.mjs +0 -8
- package/dist/setup-WZ-xqAQO.cjs +0 -849
- package/dist/setup-WZ-xqAQO.cjs.map +0 -1
- package/dist/sync-BLA94rgC.cjs +0 -4
- package/dist/types-B3GQUg3k.d.mts +0 -280
- package/dist/types-B3GQUg3k.d.mts.map +0 -1
- package/dist/types-BWQDiooe.d.cts +0 -280
- package/dist/types-BWQDiooe.d.cts.map +0 -1
- package/dist/workspace-CQTT7HJQ.cjs.map +0 -1
- package/dist/workspace-D-37Ylqo.mjs.map +0 -1
- package/docs/OPENAPI_TYPESCRIPT_DESIGN.md +0 -408
- package/docs/dev-server-resilience-design.md +0 -189
- package/docs/manifest-refactor-design.md +0 -287
- package/examples/cron-example.ts +0 -45
- package/examples/env.ts +0 -33
- package/examples/function-example.ts +0 -40
- package/examples/gkm.config.json +0 -22
- package/examples/gkm.config.ts +0 -14
- package/examples/gkm.minimal.config.json +0 -7
- package/examples/gkm.production.config.json +0 -27
- package/examples/logger.ts +0 -10
- package/scripts/sync-versions.ts +0 -108
- package/src/__tests__/EndpointGenerator.hooks.spec.ts +0 -204
- package/src/__tests__/config.spec.ts +0 -422
- package/src/__tests__/loadEnvFiles.spec.ts +0 -131
- package/src/__tests__/normalizeHooksConfig.spec.ts +0 -63
- package/src/__tests__/openapi-react-query.spec.ts +0 -506
- package/src/__tests__/openapi.spec.ts +0 -625
- package/src/__tests__/test-helpers.ts +0 -181
- package/src/auth/__tests__/credentials.spec.ts +0 -331
- package/src/auth/__tests__/index.spec.ts +0 -237
- package/src/auth/credentials.ts +0 -286
- package/src/auth/index.ts +0 -233
- package/src/build/__tests__/bundler.spec.ts +0 -446
- package/src/build/__tests__/endpoint-analyzer.spec.ts +0 -623
- package/src/build/__tests__/handler-templates.spec.ts +0 -1287
- package/src/build/__tests__/index-new.spec.ts +0 -550
- package/src/build/__tests__/manifests.spec.ts +0 -583
- package/src/build/__tests__/partitions.spec.ts +0 -110
- package/src/build/__tests__/workspace-build.spec.ts +0 -215
- package/src/build/bundler.ts +0 -256
- package/src/build/endpoint-analyzer.ts +0 -236
- package/src/build/handler-templates.ts +0 -1253
- package/src/build/index.ts +0 -616
- package/src/build/manifests.ts +0 -285
- package/src/build/partitions.ts +0 -58
- package/src/build/providerResolver.ts +0 -184
- package/src/build/types.ts +0 -104
- package/src/config.ts +0 -330
- package/src/credentials/__tests__/fullDockerPorts.spec.ts +0 -144
- package/src/credentials/__tests__/helpers.ts +0 -112
- package/src/credentials/__tests__/prepareEntryCredentials.spec.ts +0 -125
- package/src/credentials/__tests__/readonlyDockerPorts.spec.ts +0 -190
- package/src/credentials/__tests__/workspaceCredentials.spec.ts +0 -209
- package/src/credentials/index.ts +0 -843
- package/src/debug.ts +0 -68
- package/src/deploy/CachedStateProvider.ts +0 -86
- package/src/deploy/LocalStateProvider.ts +0 -57
- package/src/deploy/SSMStateProvider.ts +0 -117
- package/src/deploy/StateProvider.ts +0 -175
- package/src/deploy/__tests__/CachedStateProvider.spec.ts +0 -235
- package/src/deploy/__tests__/HostingerProvider.spec.ts +0 -347
- package/src/deploy/__tests__/LocalStateProvider.spec.ts +0 -130
- package/src/deploy/__tests__/Route53Provider.spec.ts +0 -425
- package/src/deploy/__tests__/SSMStateProvider.spec.ts +0 -201
- package/src/deploy/__tests__/__fixtures__/entry-apps/async-entry.ts +0 -24
- package/src/deploy/__tests__/__fixtures__/entry-apps/nested-config-entry.ts +0 -24
- package/src/deploy/__tests__/__fixtures__/entry-apps/no-env-entry.ts +0 -12
- package/src/deploy/__tests__/__fixtures__/entry-apps/simple-entry.ts +0 -14
- package/src/deploy/__tests__/__fixtures__/entry-apps/throwing-entry.ts +0 -16
- package/src/deploy/__tests__/__fixtures__/env-parsers/non-function-export.ts +0 -10
- package/src/deploy/__tests__/__fixtures__/env-parsers/optional-env-parser.ts +0 -21
- package/src/deploy/__tests__/__fixtures__/env-parsers/parseable-env-parser.ts +0 -18
- package/src/deploy/__tests__/__fixtures__/env-parsers/throwing-env-parser.ts +0 -16
- package/src/deploy/__tests__/__fixtures__/env-parsers/valid-env-parser.ts +0 -16
- package/src/deploy/__tests__/__fixtures__/route-apps/endpoints/auth.ts +0 -16
- package/src/deploy/__tests__/__fixtures__/route-apps/endpoints/health.ts +0 -13
- package/src/deploy/__tests__/__fixtures__/route-apps/endpoints/users.ts +0 -15
- package/src/deploy/__tests__/__fixtures__/route-apps/services.ts +0 -55
- package/src/deploy/__tests__/backup-provisioner.spec.ts +0 -428
- package/src/deploy/__tests__/createDnsProvider.spec.ts +0 -195
- package/src/deploy/__tests__/createStateProvider.spec.ts +0 -126
- package/src/deploy/__tests__/dns-orchestration.spec.ts +0 -192
- package/src/deploy/__tests__/dns-verification.spec.ts +0 -229
- package/src/deploy/__tests__/docker.spec.ts +0 -149
- package/src/deploy/__tests__/dokploy-api.spec.ts +0 -697
- package/src/deploy/__tests__/dokploy.spec.ts +0 -435
- package/src/deploy/__tests__/domain.spec.ts +0 -235
- package/src/deploy/__tests__/env-resolver.spec.ts +0 -903
- package/src/deploy/__tests__/index.spec.ts +0 -1091
- package/src/deploy/__tests__/init.spec.ts +0 -793
- package/src/deploy/__tests__/secrets.spec.ts +0 -303
- package/src/deploy/__tests__/sniffer.spec.ts +0 -838
- package/src/deploy/__tests__/state-e2e.spec.ts +0 -387
- package/src/deploy/__tests__/state.spec.ts +0 -876
- package/src/deploy/__tests__/undeploy.spec.ts +0 -758
- package/src/deploy/backup-provisioner.ts +0 -316
- package/src/deploy/dns/DnsProvider.ts +0 -201
- package/src/deploy/dns/HostingerProvider.ts +0 -174
- package/src/deploy/dns/Route53Provider.ts +0 -340
- package/src/deploy/dns/hostinger-api.ts +0 -261
- package/src/deploy/dns/index.ts +0 -627
- package/src/deploy/docker.ts +0 -260
- package/src/deploy/dokploy-api.ts +0 -1101
- package/src/deploy/dokploy.ts +0 -177
- package/src/deploy/domain.ts +0 -134
- package/src/deploy/env-resolver.ts +0 -305
- package/src/deploy/index.ts +0 -2094
- package/src/deploy/init.ts +0 -427
- package/src/deploy/secrets.ts +0 -187
- package/src/deploy/sniffer-envkit-patch.ts +0 -61
- package/src/deploy/sniffer-hooks.ts +0 -57
- package/src/deploy/sniffer-loader.ts +0 -28
- package/src/deploy/sniffer-routes-worker.ts +0 -104
- package/src/deploy/sniffer-worker.ts +0 -75
- package/src/deploy/sniffer.ts +0 -578
- package/src/deploy/state-commands.ts +0 -274
- package/src/deploy/state.ts +0 -482
- package/src/deploy/types.ts +0 -102
- package/src/deploy/undeploy.ts +0 -407
- package/src/dev/__tests__/entry-integration.spec.ts +0 -347
- package/src/dev/__tests__/entry.spec.ts +0 -144
- package/src/dev/__tests__/index.spec.ts +0 -2084
- package/src/dev/index.ts +0 -1649
- package/src/docker/__tests__/compose.spec.ts +0 -1142
- package/src/docker/__tests__/templates.spec.ts +0 -694
- package/src/docker/compose.ts +0 -808
- package/src/docker/index.ts +0 -523
- package/src/docker/templates.ts +0 -1067
- package/src/exec/index.ts +0 -118
- package/src/generators/CronGenerator.ts +0 -105
- package/src/generators/EndpointGenerator.ts +0 -954
- package/src/generators/FunctionGenerator.ts +0 -117
- package/src/generators/Generator.ts +0 -147
- package/src/generators/OpenApiTsGenerator.ts +0 -821
- package/src/generators/QueueGenerator.ts +0 -245
- package/src/generators/SubscriberGenerator.ts +0 -282
- package/src/generators/TopicGenerator.ts +0 -45
- package/src/generators/__tests__/CronGenerator.spec.ts +0 -445
- package/src/generators/__tests__/EndpointGenerator.spec.ts +0 -544
- package/src/generators/__tests__/FunctionGenerator.spec.ts +0 -256
- package/src/generators/__tests__/Generator.bustCache.spec.ts +0 -72
- package/src/generators/__tests__/OpenApiTsGenerator.registry.spec.ts +0 -98
- package/src/generators/__tests__/OpenApiTsGenerator.responseType.spec.ts +0 -56
- package/src/generators/__tests__/QueueGenerator.spec.ts +0 -141
- package/src/generators/__tests__/SubscriberGenerator.spec.ts +0 -410
- package/src/generators/index.ts +0 -11
- package/src/index.ts +0 -972
- package/src/init/__tests__/generators.spec.ts +0 -1070
- package/src/init/__tests__/init.spec.ts +0 -577
- package/src/init/__tests__/utils.spec.ts +0 -104
- package/src/init/generators/auth.ts +0 -225
- package/src/init/generators/config.ts +0 -316
- package/src/init/generators/docker.ts +0 -388
- package/src/init/generators/env.ts +0 -62
- package/src/init/generators/index.ts +0 -6
- package/src/init/generators/mobile-expo.ts +0 -576
- package/src/init/generators/models.ts +0 -153
- package/src/init/generators/monorepo.ts +0 -475
- package/src/init/generators/package.ts +0 -95
- package/src/init/generators/source.ts +0 -15
- package/src/init/generators/test.ts +0 -178
- package/src/init/generators/ui.ts +0 -1473
- package/src/init/generators/web-tanstack.ts +0 -348
- package/src/init/generators/web.ts +0 -363
- package/src/init/index.ts +0 -542
- package/src/init/templates/api.ts +0 -404
- package/src/init/templates/index.ts +0 -342
- package/src/init/templates/minimal.ts +0 -207
- package/src/init/templates/serverless.ts +0 -148
- package/src/init/templates/worker.ts +0 -216
- package/src/init/utils.ts +0 -197
- package/src/init/versions.ts +0 -52
- package/src/openapi-react-query.ts +0 -288
- package/src/openapi.ts +0 -259
- package/src/secrets/__tests__/encryption.spec.ts +0 -226
- package/src/secrets/__tests__/generator.spec.ts +0 -575
- package/src/secrets/__tests__/index.spec.ts +0 -91
- package/src/secrets/__tests__/reconcile.spec.ts +0 -123
- package/src/secrets/__tests__/storage.spec.ts +0 -645
- package/src/secrets/encryption.ts +0 -91
- package/src/secrets/generator.ts +0 -329
- package/src/secrets/index.ts +0 -417
- package/src/secrets/keystore.ts +0 -144
- package/src/secrets/reconcile.ts +0 -53
- package/src/secrets/storage.ts +0 -337
- package/src/secrets/sync.ts +0 -136
- package/src/secrets/types.ts +0 -70
- package/src/setup/__tests__/auto-setup.spec.ts +0 -147
- package/src/setup/__tests__/reconcile-secrets.spec.ts +0 -439
- package/src/setup/fullstack-secrets.ts +0 -140
- package/src/setup/index.ts +0 -411
- package/src/test/__tests__/__fixtures__/workspace.ts +0 -104
- package/src/test/__tests__/api.spec.ts +0 -199
- package/src/test/__tests__/auth.spec.ts +0 -162
- package/src/test/__tests__/index.spec.ts +0 -502
- package/src/test/__tests__/web.spec.ts +0 -210
- package/src/test/index.ts +0 -198
- package/src/types.ts +0 -363
- package/src/upgrade/__tests__/index.spec.ts +0 -354
- package/src/upgrade/index.ts +0 -253
- package/src/workspace/__tests__/client-generator.spec.ts +0 -326
- package/src/workspace/__tests__/index.spec.ts +0 -766
- package/src/workspace/__tests__/publicEnv.spec.ts +0 -64
- package/src/workspace/__tests__/schema.spec.ts +0 -737
- package/src/workspace/__tests__/type-inference.spec.ts +0 -251
- package/src/workspace/client-generator.ts +0 -109
- package/src/workspace/index.ts +0 -433
- package/src/workspace/publicEnv.ts +0 -57
- package/src/workspace/schema.ts +0 -861
- package/src/workspace/types.ts +0 -943
- package/tsconfig.json +0 -9
- package/tsdown.config.ts +0 -22
package/src/docker/templates.ts
DELETED
|
@@ -1,1067 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { dirname, join, parse } from 'node:path';
|
|
3
|
-
import type { DockerConfig, GkmConfig } from '../types';
|
|
4
|
-
|
|
5
|
-
export type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';
|
|
6
|
-
|
|
7
|
-
export interface DockerTemplateOptions {
|
|
8
|
-
imageName: string;
|
|
9
|
-
baseImage: string;
|
|
10
|
-
port: number;
|
|
11
|
-
healthCheckPath: string;
|
|
12
|
-
/** Whether the build is pre-built (slim Dockerfile) or needs building */
|
|
13
|
-
prebuilt: boolean;
|
|
14
|
-
/** Detected package manager */
|
|
15
|
-
packageManager: PackageManager;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface FrontendDockerfileOptions {
|
|
19
|
-
imageName: string;
|
|
20
|
-
baseImage: string;
|
|
21
|
-
port: number;
|
|
22
|
-
/** App path relative to workspace root */
|
|
23
|
-
appPath: string;
|
|
24
|
-
/** Package name for turbo prune */
|
|
25
|
-
turboPackage: string;
|
|
26
|
-
/** Detected package manager */
|
|
27
|
-
packageManager: PackageManager;
|
|
28
|
-
/**
|
|
29
|
-
* Public URL build args to include in the Dockerfile.
|
|
30
|
-
* These will be declared as ARG and converted to ENV for Next.js build.
|
|
31
|
-
* Example: ['NEXT_PUBLIC_API_URL', 'NEXT_PUBLIC_AUTH_URL']
|
|
32
|
-
*/
|
|
33
|
-
publicUrlArgs?: string[];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface MultiStageDockerfileOptions extends DockerTemplateOptions {
|
|
37
|
-
/** Enable turbo prune for monorepo optimization */
|
|
38
|
-
turbo?: boolean;
|
|
39
|
-
/** Package name for turbo prune (defaults to current directory name) */
|
|
40
|
-
turboPackage?: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const LOCKFILES: [string, PackageManager][] = [
|
|
44
|
-
['pnpm-lock.yaml', 'pnpm'],
|
|
45
|
-
['bun.lockb', 'bun'],
|
|
46
|
-
['yarn.lock', 'yarn'],
|
|
47
|
-
['package-lock.json', 'npm'],
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Detect package manager from lockfiles
|
|
52
|
-
* Walks up the directory tree to find lockfile (for monorepos)
|
|
53
|
-
*/
|
|
54
|
-
export function detectPackageManager(
|
|
55
|
-
cwd: string = process.cwd(),
|
|
56
|
-
): PackageManager {
|
|
57
|
-
let dir = cwd;
|
|
58
|
-
const root = parse(dir).root;
|
|
59
|
-
|
|
60
|
-
// Walk up the directory tree
|
|
61
|
-
while (dir !== root) {
|
|
62
|
-
for (const [lockfile, pm] of LOCKFILES) {
|
|
63
|
-
if (existsSync(join(dir, lockfile))) {
|
|
64
|
-
return pm;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
dir = dirname(dir);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Check root directory
|
|
71
|
-
for (const [lockfile, pm] of LOCKFILES) {
|
|
72
|
-
if (existsSync(join(root, lockfile))) {
|
|
73
|
-
return pm;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return 'pnpm'; // default
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Find the lockfile path by walking up the directory tree
|
|
82
|
-
* Returns the full path to the lockfile, or null if not found
|
|
83
|
-
*/
|
|
84
|
-
export function findLockfilePath(cwd: string = process.cwd()): string | null {
|
|
85
|
-
let dir = cwd;
|
|
86
|
-
const root = parse(dir).root;
|
|
87
|
-
|
|
88
|
-
// Walk up the directory tree
|
|
89
|
-
while (dir !== root) {
|
|
90
|
-
for (const [lockfile] of LOCKFILES) {
|
|
91
|
-
const lockfilePath = join(dir, lockfile);
|
|
92
|
-
if (existsSync(lockfilePath)) {
|
|
93
|
-
return lockfilePath;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
dir = dirname(dir);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Check root directory
|
|
100
|
-
for (const [lockfile] of LOCKFILES) {
|
|
101
|
-
const lockfilePath = join(root, lockfile);
|
|
102
|
-
if (existsSync(lockfilePath)) {
|
|
103
|
-
return lockfilePath;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Get the lockfile name for a package manager
|
|
112
|
-
*/
|
|
113
|
-
export function getLockfileName(pm: PackageManager): string {
|
|
114
|
-
const lockfileMap: Record<PackageManager, string> = {
|
|
115
|
-
pnpm: 'pnpm-lock.yaml',
|
|
116
|
-
npm: 'package-lock.json',
|
|
117
|
-
yarn: 'yarn.lock',
|
|
118
|
-
bun: 'bun.lockb',
|
|
119
|
-
};
|
|
120
|
-
return lockfileMap[pm];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Check if we're in a monorepo (lockfile is in a parent directory)
|
|
125
|
-
*/
|
|
126
|
-
export function isMonorepo(cwd: string = process.cwd()): boolean {
|
|
127
|
-
const lockfilePath = findLockfilePath(cwd);
|
|
128
|
-
if (!lockfilePath) {
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Check if lockfile is in a parent directory (not in cwd)
|
|
133
|
-
const lockfileDir = dirname(lockfilePath);
|
|
134
|
-
return lockfileDir !== cwd;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Check if turbo.json exists (walks up directory tree)
|
|
139
|
-
*/
|
|
140
|
-
export function hasTurboConfig(cwd: string = process.cwd()): boolean {
|
|
141
|
-
let dir = cwd;
|
|
142
|
-
const root = parse(dir).root;
|
|
143
|
-
|
|
144
|
-
while (dir !== root) {
|
|
145
|
-
if (existsSync(join(dir, 'turbo.json'))) {
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
dir = dirname(dir);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return existsSync(join(root, 'turbo.json'));
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get install command for turbo builds (without frozen lockfile)
|
|
156
|
-
* Turbo prune creates a subset that may not perfectly match the lockfile
|
|
157
|
-
*/
|
|
158
|
-
function getTurboInstallCmd(pm: PackageManager): string {
|
|
159
|
-
const commands: Record<PackageManager, string> = {
|
|
160
|
-
pnpm: 'pnpm install',
|
|
161
|
-
npm: 'npm install',
|
|
162
|
-
yarn: 'yarn install',
|
|
163
|
-
bun: 'bun install',
|
|
164
|
-
};
|
|
165
|
-
return commands[pm];
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Get package manager specific commands and paths
|
|
170
|
-
*/
|
|
171
|
-
function getPmConfig(pm: PackageManager) {
|
|
172
|
-
const configs = {
|
|
173
|
-
pnpm: {
|
|
174
|
-
install: 'corepack enable && corepack prepare pnpm@latest --activate',
|
|
175
|
-
lockfile: 'pnpm-lock.yaml',
|
|
176
|
-
fetch: 'pnpm fetch',
|
|
177
|
-
installCmd: 'pnpm install --frozen-lockfile --offline',
|
|
178
|
-
cacheTarget: '/root/.local/share/pnpm/store',
|
|
179
|
-
cacheId: 'pnpm',
|
|
180
|
-
run: 'pnpm',
|
|
181
|
-
exec: 'pnpm exec',
|
|
182
|
-
dlx: 'pnpm dlx',
|
|
183
|
-
addGlobal: 'pnpm add -g',
|
|
184
|
-
},
|
|
185
|
-
npm: {
|
|
186
|
-
install: '', // npm comes with node
|
|
187
|
-
lockfile: 'package-lock.json',
|
|
188
|
-
fetch: '', // npm doesn't have fetch
|
|
189
|
-
installCmd: 'npm ci',
|
|
190
|
-
cacheTarget: '/root/.npm',
|
|
191
|
-
cacheId: 'npm',
|
|
192
|
-
run: 'npm run',
|
|
193
|
-
exec: 'npx',
|
|
194
|
-
dlx: 'npx',
|
|
195
|
-
addGlobal: 'npm install -g',
|
|
196
|
-
},
|
|
197
|
-
yarn: {
|
|
198
|
-
install: 'corepack enable && corepack prepare yarn@stable --activate',
|
|
199
|
-
lockfile: 'yarn.lock',
|
|
200
|
-
fetch: '', // yarn doesn't have fetch
|
|
201
|
-
installCmd: 'yarn install --frozen-lockfile',
|
|
202
|
-
cacheTarget: '/root/.yarn/cache',
|
|
203
|
-
cacheId: 'yarn',
|
|
204
|
-
run: 'yarn',
|
|
205
|
-
exec: 'yarn exec',
|
|
206
|
-
dlx: 'yarn dlx',
|
|
207
|
-
addGlobal: 'yarn global add',
|
|
208
|
-
},
|
|
209
|
-
bun: {
|
|
210
|
-
install: 'npm install -g bun',
|
|
211
|
-
lockfile: 'bun.lockb',
|
|
212
|
-
fetch: '', // bun doesn't have fetch
|
|
213
|
-
installCmd: 'bun install --frozen-lockfile',
|
|
214
|
-
cacheTarget: '/root/.bun/install/cache',
|
|
215
|
-
cacheId: 'bun',
|
|
216
|
-
run: 'bun run',
|
|
217
|
-
exec: 'bunx',
|
|
218
|
-
dlx: 'bunx',
|
|
219
|
-
addGlobal: 'bun add -g',
|
|
220
|
-
},
|
|
221
|
-
};
|
|
222
|
-
return configs[pm];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Generate a multi-stage Dockerfile for building from source
|
|
227
|
-
* Optimized for build speed with:
|
|
228
|
-
* - BuildKit cache mounts for package manager store
|
|
229
|
-
* - pnpm fetch for better layer caching (when using pnpm)
|
|
230
|
-
* - Optional turbo prune for monorepos
|
|
231
|
-
*/
|
|
232
|
-
export function generateMultiStageDockerfile(
|
|
233
|
-
options: MultiStageDockerfileOptions,
|
|
234
|
-
): string {
|
|
235
|
-
const {
|
|
236
|
-
baseImage,
|
|
237
|
-
port,
|
|
238
|
-
healthCheckPath,
|
|
239
|
-
turbo,
|
|
240
|
-
turboPackage,
|
|
241
|
-
packageManager,
|
|
242
|
-
} = options;
|
|
243
|
-
|
|
244
|
-
if (turbo) {
|
|
245
|
-
return generateTurboDockerfile({
|
|
246
|
-
...options,
|
|
247
|
-
turboPackage: turboPackage ?? 'api',
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const pm = getPmConfig(packageManager);
|
|
252
|
-
const installPm = pm.install
|
|
253
|
-
? `\n# Install ${packageManager}\nRUN ${pm.install}\n`
|
|
254
|
-
: '';
|
|
255
|
-
const hasFetch = packageManager === 'pnpm';
|
|
256
|
-
|
|
257
|
-
// pnpm has fetch which allows better caching
|
|
258
|
-
const depsStage = hasFetch
|
|
259
|
-
? `# Copy lockfile first for better caching
|
|
260
|
-
COPY ${pm.lockfile} ./
|
|
261
|
-
|
|
262
|
-
# Fetch dependencies (downloads to virtual store, cached separately)
|
|
263
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
264
|
-
${pm.fetch}
|
|
265
|
-
|
|
266
|
-
# Copy package.json after fetch
|
|
267
|
-
COPY package.json ./
|
|
268
|
-
|
|
269
|
-
# Install from cache (fast - no network needed)
|
|
270
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
271
|
-
${pm.installCmd}`
|
|
272
|
-
: `# Copy package files
|
|
273
|
-
COPY package.json ${pm.lockfile} ./
|
|
274
|
-
|
|
275
|
-
# Install dependencies with cache
|
|
276
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
277
|
-
${pm.installCmd}`;
|
|
278
|
-
|
|
279
|
-
return `# syntax=docker/dockerfile:1
|
|
280
|
-
# Stage 1: Dependencies
|
|
281
|
-
FROM ${baseImage} AS deps
|
|
282
|
-
|
|
283
|
-
WORKDIR /app
|
|
284
|
-
${installPm}
|
|
285
|
-
${depsStage}
|
|
286
|
-
|
|
287
|
-
# Stage 2: Build
|
|
288
|
-
FROM deps AS builder
|
|
289
|
-
|
|
290
|
-
WORKDIR /app
|
|
291
|
-
|
|
292
|
-
# Copy source (deps already installed)
|
|
293
|
-
COPY . .
|
|
294
|
-
|
|
295
|
-
# Build production server using gkm
|
|
296
|
-
RUN ${pm.exec} gkm build --provider server --production
|
|
297
|
-
|
|
298
|
-
# Stage 3: Production
|
|
299
|
-
FROM ${baseImage} AS runner
|
|
300
|
-
|
|
301
|
-
WORKDIR /app
|
|
302
|
-
|
|
303
|
-
# Install tini for proper signal handling as PID 1
|
|
304
|
-
RUN apk add --no-cache tini
|
|
305
|
-
|
|
306
|
-
# Create non-root user
|
|
307
|
-
RUN addgroup --system --gid 1001 nodejs && \\
|
|
308
|
-
adduser --system --uid 1001 hono
|
|
309
|
-
|
|
310
|
-
# Copy bundled server
|
|
311
|
-
COPY --from=builder --chown=hono:nodejs /app/.gkm/server/dist/server.mjs ./
|
|
312
|
-
|
|
313
|
-
# Environment
|
|
314
|
-
ENV NODE_ENV=production
|
|
315
|
-
ENV PORT=${port}
|
|
316
|
-
|
|
317
|
-
# Health check
|
|
318
|
-
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \\
|
|
319
|
-
CMD wget -qO- http://localhost:${port}${healthCheckPath} > /dev/null 2>&1 || exit 1
|
|
320
|
-
|
|
321
|
-
# Switch to non-root user
|
|
322
|
-
USER hono
|
|
323
|
-
|
|
324
|
-
EXPOSE ${port}
|
|
325
|
-
|
|
326
|
-
# Use tini as entrypoint to handle PID 1 responsibilities
|
|
327
|
-
ENTRYPOINT ["/sbin/tini", "--"]
|
|
328
|
-
CMD ["node", "server.mjs"]
|
|
329
|
-
`;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Generate a Dockerfile optimized for Turbo monorepos
|
|
334
|
-
* Uses turbo prune to create minimal Docker context
|
|
335
|
-
*/
|
|
336
|
-
function generateTurboDockerfile(options: MultiStageDockerfileOptions): string {
|
|
337
|
-
const { baseImage, port, healthCheckPath, turboPackage, packageManager } =
|
|
338
|
-
options;
|
|
339
|
-
|
|
340
|
-
const pm = getPmConfig(packageManager);
|
|
341
|
-
const installPm = pm.install ? `RUN ${pm.install}` : '';
|
|
342
|
-
|
|
343
|
-
// For turbo builds, we can't use --frozen-lockfile because turbo prune
|
|
344
|
-
// creates a subset that may not perfectly match. Use relaxed install.
|
|
345
|
-
const turboInstallCmd = getTurboInstallCmd(packageManager);
|
|
346
|
-
|
|
347
|
-
// Use pnpm dlx for pnpm (avoids global bin dir issues in Docker)
|
|
348
|
-
const turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';
|
|
349
|
-
|
|
350
|
-
return `# syntax=docker/dockerfile:1
|
|
351
|
-
# Stage 1: Prune monorepo
|
|
352
|
-
FROM ${baseImage} AS pruner
|
|
353
|
-
|
|
354
|
-
WORKDIR /app
|
|
355
|
-
|
|
356
|
-
${installPm}
|
|
357
|
-
|
|
358
|
-
COPY . .
|
|
359
|
-
|
|
360
|
-
# Prune to only include necessary packages
|
|
361
|
-
RUN ${turboCmd} prune ${turboPackage} --docker
|
|
362
|
-
|
|
363
|
-
# Stage 2: Install dependencies
|
|
364
|
-
FROM ${baseImage} AS deps
|
|
365
|
-
|
|
366
|
-
WORKDIR /app
|
|
367
|
-
|
|
368
|
-
${installPm}
|
|
369
|
-
|
|
370
|
-
# Copy pruned lockfile and package.jsons
|
|
371
|
-
COPY --from=pruner /app/out/${pm.lockfile} ./
|
|
372
|
-
COPY --from=pruner /app/out/json/ ./
|
|
373
|
-
|
|
374
|
-
# Install dependencies (no frozen-lockfile since turbo prune creates a subset)
|
|
375
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
376
|
-
${turboInstallCmd}
|
|
377
|
-
|
|
378
|
-
# Stage 3: Build
|
|
379
|
-
FROM deps AS builder
|
|
380
|
-
|
|
381
|
-
WORKDIR /app
|
|
382
|
-
|
|
383
|
-
# Copy pruned source
|
|
384
|
-
COPY --from=pruner /app/out/full/ ./
|
|
385
|
-
|
|
386
|
-
# Build production server using gkm
|
|
387
|
-
RUN ${pm.exec} gkm build --provider server --production
|
|
388
|
-
|
|
389
|
-
# Stage 4: Production
|
|
390
|
-
FROM ${baseImage} AS runner
|
|
391
|
-
|
|
392
|
-
WORKDIR /app
|
|
393
|
-
|
|
394
|
-
RUN apk add --no-cache tini
|
|
395
|
-
|
|
396
|
-
RUN addgroup --system --gid 1001 nodejs && \\
|
|
397
|
-
adduser --system --uid 1001 hono
|
|
398
|
-
|
|
399
|
-
COPY --from=builder --chown=hono:nodejs /app/.gkm/server/dist/server.mjs ./
|
|
400
|
-
|
|
401
|
-
ENV NODE_ENV=production
|
|
402
|
-
ENV PORT=${port}
|
|
403
|
-
|
|
404
|
-
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \\
|
|
405
|
-
CMD wget -qO- http://localhost:${port}${healthCheckPath} > /dev/null 2>&1 || exit 1
|
|
406
|
-
|
|
407
|
-
USER hono
|
|
408
|
-
|
|
409
|
-
EXPOSE ${port}
|
|
410
|
-
|
|
411
|
-
ENTRYPOINT ["/sbin/tini", "--"]
|
|
412
|
-
CMD ["node", "server.mjs"]
|
|
413
|
-
`;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Generate a slim Dockerfile for pre-built bundles
|
|
418
|
-
*/
|
|
419
|
-
export function generateSlimDockerfile(options: DockerTemplateOptions): string {
|
|
420
|
-
const { baseImage, port, healthCheckPath } = options;
|
|
421
|
-
|
|
422
|
-
return `# Slim Dockerfile for pre-built production bundle
|
|
423
|
-
FROM ${baseImage}
|
|
424
|
-
|
|
425
|
-
WORKDIR /app
|
|
426
|
-
|
|
427
|
-
# Install tini for proper signal handling as PID 1
|
|
428
|
-
# Handles SIGTERM propagation and zombie process reaping
|
|
429
|
-
RUN apk add --no-cache tini
|
|
430
|
-
|
|
431
|
-
# Create non-root user
|
|
432
|
-
RUN addgroup --system --gid 1001 nodejs && \\
|
|
433
|
-
adduser --system --uid 1001 hono
|
|
434
|
-
|
|
435
|
-
# Copy pre-built bundle
|
|
436
|
-
COPY .gkm/server/dist/server.mjs ./
|
|
437
|
-
|
|
438
|
-
# Environment
|
|
439
|
-
ENV NODE_ENV=production
|
|
440
|
-
ENV PORT=${port}
|
|
441
|
-
|
|
442
|
-
# Health check
|
|
443
|
-
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \\
|
|
444
|
-
CMD wget -qO- http://localhost:${port}${healthCheckPath} > /dev/null 2>&1 || exit 1
|
|
445
|
-
|
|
446
|
-
# Switch to non-root user
|
|
447
|
-
USER hono
|
|
448
|
-
|
|
449
|
-
EXPOSE ${port}
|
|
450
|
-
|
|
451
|
-
# Use tini as entrypoint to handle PID 1 responsibilities
|
|
452
|
-
ENTRYPOINT ["/sbin/tini", "--"]
|
|
453
|
-
CMD ["node", "server.mjs"]
|
|
454
|
-
`;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Generate .dockerignore file
|
|
459
|
-
*/
|
|
460
|
-
export function generateDockerignore(): string {
|
|
461
|
-
return `# Dependencies
|
|
462
|
-
node_modules
|
|
463
|
-
.pnpm-store
|
|
464
|
-
|
|
465
|
-
# Build output (except what we need)
|
|
466
|
-
.gkm/aws*
|
|
467
|
-
.gkm/server/*.ts
|
|
468
|
-
!.gkm/server/dist
|
|
469
|
-
|
|
470
|
-
# IDE and editor
|
|
471
|
-
.idea
|
|
472
|
-
.vscode
|
|
473
|
-
*.swp
|
|
474
|
-
*.swo
|
|
475
|
-
|
|
476
|
-
# Git
|
|
477
|
-
.git
|
|
478
|
-
.gitignore
|
|
479
|
-
|
|
480
|
-
# Logs
|
|
481
|
-
*.log
|
|
482
|
-
npm-debug.log*
|
|
483
|
-
pnpm-debug.log*
|
|
484
|
-
|
|
485
|
-
# Test files
|
|
486
|
-
**/*.test.ts
|
|
487
|
-
**/*.spec.ts
|
|
488
|
-
**/__tests__
|
|
489
|
-
coverage
|
|
490
|
-
|
|
491
|
-
# Documentation
|
|
492
|
-
docs
|
|
493
|
-
*.md
|
|
494
|
-
!README.md
|
|
495
|
-
|
|
496
|
-
# Environment files (handle secrets separately)
|
|
497
|
-
.env
|
|
498
|
-
.env.*
|
|
499
|
-
!.env.example
|
|
500
|
-
|
|
501
|
-
# Docker files (don't copy recursively)
|
|
502
|
-
Dockerfile*
|
|
503
|
-
docker-compose*
|
|
504
|
-
.dockerignore
|
|
505
|
-
`;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Generate docker-entrypoint.sh for custom startup logic
|
|
510
|
-
*/
|
|
511
|
-
export function generateDockerEntrypoint(): string {
|
|
512
|
-
return `#!/bin/sh
|
|
513
|
-
set -e
|
|
514
|
-
|
|
515
|
-
# Run any custom startup scripts here
|
|
516
|
-
# Example: wait for database
|
|
517
|
-
# until nc -z $DB_HOST $DB_PORT; do
|
|
518
|
-
# echo "Waiting for database..."
|
|
519
|
-
# sleep 1
|
|
520
|
-
# done
|
|
521
|
-
|
|
522
|
-
# Execute the main command
|
|
523
|
-
exec "$@"
|
|
524
|
-
`;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
/**
|
|
528
|
-
* Resolve Docker configuration from GkmConfig with defaults
|
|
529
|
-
*/
|
|
530
|
-
export function resolveDockerConfig(
|
|
531
|
-
config: GkmConfig,
|
|
532
|
-
): Required<Omit<DockerConfig, 'compose'>> & Pick<DockerConfig, 'compose'> {
|
|
533
|
-
const docker = config.docker ?? {};
|
|
534
|
-
|
|
535
|
-
// Try to get image name from package.json name
|
|
536
|
-
let defaultImageName = 'api';
|
|
537
|
-
try {
|
|
538
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
539
|
-
const pkg = require(`${process.cwd()}/package.json`);
|
|
540
|
-
if (pkg.name) {
|
|
541
|
-
// Remove scope and use just the package name
|
|
542
|
-
defaultImageName = pkg.name.replace(/^@[^/]+\//, '');
|
|
543
|
-
}
|
|
544
|
-
} catch {
|
|
545
|
-
// Ignore if package.json doesn't exist
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
return {
|
|
549
|
-
registry: docker.registry ?? '',
|
|
550
|
-
imageName: docker.imageName ?? defaultImageName,
|
|
551
|
-
baseImage: docker.baseImage ?? 'node:22-alpine',
|
|
552
|
-
port: docker.port ?? 3000,
|
|
553
|
-
compose: docker.compose,
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Generate a Dockerfile for Next.js frontend apps using standalone output.
|
|
559
|
-
* Uses turbo prune for monorepo optimization.
|
|
560
|
-
* @internal Exported for testing
|
|
561
|
-
*/
|
|
562
|
-
export function generateNextjsDockerfile(
|
|
563
|
-
options: FrontendDockerfileOptions,
|
|
564
|
-
): string {
|
|
565
|
-
const {
|
|
566
|
-
baseImage,
|
|
567
|
-
port,
|
|
568
|
-
appPath,
|
|
569
|
-
turboPackage,
|
|
570
|
-
packageManager,
|
|
571
|
-
publicUrlArgs = ['NEXT_PUBLIC_API_URL', 'NEXT_PUBLIC_AUTH_URL'],
|
|
572
|
-
} = options;
|
|
573
|
-
|
|
574
|
-
const pm = getPmConfig(packageManager);
|
|
575
|
-
const installPm = pm.install ? `RUN ${pm.install}` : '';
|
|
576
|
-
|
|
577
|
-
// For turbo builds, we can't use --frozen-lockfile because turbo prune
|
|
578
|
-
// creates a subset that may not perfectly match. Use relaxed install.
|
|
579
|
-
const turboInstallCmd = getTurboInstallCmd(packageManager);
|
|
580
|
-
|
|
581
|
-
// Use pnpm dlx for pnpm (avoids global bin dir issues in Docker)
|
|
582
|
-
const turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';
|
|
583
|
-
|
|
584
|
-
// Generate ARG and ENV declarations for public URLs
|
|
585
|
-
const publicUrlArgDeclarations = publicUrlArgs
|
|
586
|
-
.map((arg) => `ARG ${arg}=""`)
|
|
587
|
-
.join('\n');
|
|
588
|
-
const publicUrlEnvDeclarations = publicUrlArgs
|
|
589
|
-
.map((arg) => `ENV ${arg}=$${arg}`)
|
|
590
|
-
.join('\n');
|
|
591
|
-
|
|
592
|
-
return `# syntax=docker/dockerfile:1
|
|
593
|
-
# Next.js standalone Dockerfile with turbo prune optimization
|
|
594
|
-
|
|
595
|
-
# Stage 1: Prune monorepo
|
|
596
|
-
FROM ${baseImage} AS pruner
|
|
597
|
-
|
|
598
|
-
WORKDIR /app
|
|
599
|
-
|
|
600
|
-
${installPm}
|
|
601
|
-
|
|
602
|
-
COPY . .
|
|
603
|
-
|
|
604
|
-
# Prune to only include necessary packages
|
|
605
|
-
RUN ${turboCmd} prune ${turboPackage} --docker
|
|
606
|
-
|
|
607
|
-
# Stage 2: Install dependencies
|
|
608
|
-
FROM ${baseImage} AS deps
|
|
609
|
-
|
|
610
|
-
WORKDIR /app
|
|
611
|
-
|
|
612
|
-
${installPm}
|
|
613
|
-
|
|
614
|
-
# Copy pruned lockfile and package.jsons
|
|
615
|
-
COPY --from=pruner /app/out/${pm.lockfile} ./
|
|
616
|
-
COPY --from=pruner /app/out/json/ ./
|
|
617
|
-
|
|
618
|
-
# Install dependencies
|
|
619
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
620
|
-
${turboInstallCmd}
|
|
621
|
-
|
|
622
|
-
# Stage 3: Build
|
|
623
|
-
FROM deps AS builder
|
|
624
|
-
|
|
625
|
-
WORKDIR /app
|
|
626
|
-
|
|
627
|
-
# Build-time args for public API URLs (populated by gkm deploy)
|
|
628
|
-
# These get baked into the Next.js build as public environment variables
|
|
629
|
-
${publicUrlArgDeclarations}
|
|
630
|
-
|
|
631
|
-
# Convert ARGs to ENVs for Next.js build
|
|
632
|
-
${publicUrlEnvDeclarations}
|
|
633
|
-
|
|
634
|
-
# Copy pruned source
|
|
635
|
-
COPY --from=pruner /app/out/full/ ./
|
|
636
|
-
|
|
637
|
-
# Copy workspace root configs for turbo builds (turbo prune doesn't include root configs)
|
|
638
|
-
# Using wildcard to make it optional for single-app projects
|
|
639
|
-
COPY --from=pruner /app/tsconfig.* ./
|
|
640
|
-
|
|
641
|
-
# Ensure public directory exists (may be empty for scaffolded projects)
|
|
642
|
-
RUN mkdir -p ${appPath}/public
|
|
643
|
-
|
|
644
|
-
# Set Next.js to produce standalone output
|
|
645
|
-
ENV NEXT_TELEMETRY_DISABLED=1
|
|
646
|
-
|
|
647
|
-
# Build the application
|
|
648
|
-
RUN ${turboCmd} run build --filter=${turboPackage}
|
|
649
|
-
|
|
650
|
-
# Stage 4: Production
|
|
651
|
-
FROM ${baseImage} AS runner
|
|
652
|
-
|
|
653
|
-
WORKDIR /app
|
|
654
|
-
|
|
655
|
-
# Install tini for proper signal handling
|
|
656
|
-
RUN apk add --no-cache tini
|
|
657
|
-
|
|
658
|
-
# Create non-root user
|
|
659
|
-
RUN addgroup --system --gid 1001 nodejs && \\
|
|
660
|
-
adduser --system --uid 1001 nextjs
|
|
661
|
-
|
|
662
|
-
# Set environment
|
|
663
|
-
ENV NODE_ENV=production
|
|
664
|
-
ENV NEXT_TELEMETRY_DISABLED=1
|
|
665
|
-
ENV PORT=${port}
|
|
666
|
-
ENV HOSTNAME="0.0.0.0"
|
|
667
|
-
|
|
668
|
-
# Copy static files and standalone output
|
|
669
|
-
COPY --from=builder --chown=nextjs:nodejs /app/${appPath}/.next/standalone ./
|
|
670
|
-
COPY --from=builder --chown=nextjs:nodejs /app/${appPath}/.next/static ./${appPath}/.next/static
|
|
671
|
-
COPY --from=builder --chown=nextjs:nodejs /app/${appPath}/public ./${appPath}/public
|
|
672
|
-
|
|
673
|
-
USER nextjs
|
|
674
|
-
|
|
675
|
-
EXPOSE ${port}
|
|
676
|
-
|
|
677
|
-
ENTRYPOINT ["/sbin/tini", "--"]
|
|
678
|
-
CMD ["node", "${appPath}/server.js"]
|
|
679
|
-
`;
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
/**
|
|
683
|
-
* Generate a Dockerfile for backend apps in a workspace.
|
|
684
|
-
* Uses turbo prune for monorepo optimization.
|
|
685
|
-
* @internal Exported for testing
|
|
686
|
-
*/
|
|
687
|
-
export function generateBackendDockerfile(
|
|
688
|
-
options: FrontendDockerfileOptions & { healthCheckPath?: string },
|
|
689
|
-
): string {
|
|
690
|
-
const {
|
|
691
|
-
baseImage,
|
|
692
|
-
port,
|
|
693
|
-
appPath,
|
|
694
|
-
turboPackage,
|
|
695
|
-
packageManager,
|
|
696
|
-
healthCheckPath = '/health',
|
|
697
|
-
} = options;
|
|
698
|
-
|
|
699
|
-
const pm = getPmConfig(packageManager);
|
|
700
|
-
const installPm = pm.install ? `RUN ${pm.install}` : '';
|
|
701
|
-
const turboInstallCmd = getTurboInstallCmd(packageManager);
|
|
702
|
-
const turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';
|
|
703
|
-
|
|
704
|
-
return `# syntax=docker/dockerfile:1
|
|
705
|
-
# Backend Dockerfile with turbo prune optimization
|
|
706
|
-
|
|
707
|
-
# Stage 1: Prune monorepo
|
|
708
|
-
FROM ${baseImage} AS pruner
|
|
709
|
-
|
|
710
|
-
WORKDIR /app
|
|
711
|
-
|
|
712
|
-
${installPm}
|
|
713
|
-
|
|
714
|
-
COPY . .
|
|
715
|
-
|
|
716
|
-
# Prune to only include necessary packages
|
|
717
|
-
RUN ${turboCmd} prune ${turboPackage} --docker
|
|
718
|
-
|
|
719
|
-
# Stage 2: Install dependencies
|
|
720
|
-
FROM ${baseImage} AS deps
|
|
721
|
-
|
|
722
|
-
WORKDIR /app
|
|
723
|
-
|
|
724
|
-
${installPm}
|
|
725
|
-
|
|
726
|
-
# Copy pruned lockfile and package.jsons
|
|
727
|
-
COPY --from=pruner /app/out/${pm.lockfile} ./
|
|
728
|
-
COPY --from=pruner /app/out/json/ ./
|
|
729
|
-
|
|
730
|
-
# Install dependencies
|
|
731
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
732
|
-
${turboInstallCmd}
|
|
733
|
-
|
|
734
|
-
# Stage 3: Build
|
|
735
|
-
FROM deps AS builder
|
|
736
|
-
|
|
737
|
-
WORKDIR /app
|
|
738
|
-
|
|
739
|
-
# Build-time args for encrypted secrets
|
|
740
|
-
ARG GKM_ENCRYPTED_CREDENTIALS=""
|
|
741
|
-
ARG GKM_CREDENTIALS_IV=""
|
|
742
|
-
|
|
743
|
-
# Copy pruned source
|
|
744
|
-
COPY --from=pruner /app/out/full/ ./
|
|
745
|
-
|
|
746
|
-
# Copy workspace root configs for turbo builds (turbo prune doesn't include root configs)
|
|
747
|
-
# Using wildcard to make it optional for single-app projects
|
|
748
|
-
COPY --from=pruner /app/gkm.config.* ./
|
|
749
|
-
COPY --from=pruner /app/tsconfig.* ./
|
|
750
|
-
|
|
751
|
-
# Write encrypted credentials for gkm build to embed
|
|
752
|
-
RUN if [ -n "$GKM_ENCRYPTED_CREDENTIALS" ]; then \
|
|
753
|
-
mkdir -p ${appPath}/.gkm && \
|
|
754
|
-
echo "$GKM_ENCRYPTED_CREDENTIALS" > ${appPath}/.gkm/credentials.enc && \
|
|
755
|
-
echo "$GKM_CREDENTIALS_IV" > ${appPath}/.gkm/credentials.iv; \
|
|
756
|
-
fi
|
|
757
|
-
|
|
758
|
-
# Build production server using gkm
|
|
759
|
-
RUN cd ${appPath} && ${pm.exec} gkm build --provider server --production
|
|
760
|
-
|
|
761
|
-
# Stage 4: Production
|
|
762
|
-
FROM ${baseImage} AS runner
|
|
763
|
-
|
|
764
|
-
WORKDIR /app
|
|
765
|
-
|
|
766
|
-
RUN apk add --no-cache tini
|
|
767
|
-
|
|
768
|
-
RUN addgroup --system --gid 1001 nodejs && \\
|
|
769
|
-
adduser --system --uid 1001 hono
|
|
770
|
-
|
|
771
|
-
# Copy bundled server
|
|
772
|
-
COPY --from=builder --chown=hono:nodejs /app/${appPath}/.gkm/server/dist/server.mjs ./
|
|
773
|
-
|
|
774
|
-
ENV NODE_ENV=production
|
|
775
|
-
ENV PORT=${port}
|
|
776
|
-
|
|
777
|
-
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \\
|
|
778
|
-
CMD wget -qO- http://localhost:${port}${healthCheckPath} > /dev/null 2>&1 || exit 1
|
|
779
|
-
|
|
780
|
-
USER hono
|
|
781
|
-
|
|
782
|
-
EXPOSE ${port}
|
|
783
|
-
|
|
784
|
-
ENTRYPOINT ["/sbin/tini", "--"]
|
|
785
|
-
CMD ["node", "server.mjs"]
|
|
786
|
-
`;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
/**
|
|
790
|
-
* Options for entry-based Dockerfile generation.
|
|
791
|
-
*/
|
|
792
|
-
export interface EntryDockerfileOptions {
|
|
793
|
-
imageName: string;
|
|
794
|
-
baseImage: string;
|
|
795
|
-
port: number;
|
|
796
|
-
/** App path relative to workspace root */
|
|
797
|
-
appPath: string;
|
|
798
|
-
/** Entry file path relative to app path (e.g., './src/index.ts') */
|
|
799
|
-
entry: string;
|
|
800
|
-
/** Package name for turbo prune */
|
|
801
|
-
turboPackage: string;
|
|
802
|
-
/** Detected package manager */
|
|
803
|
-
packageManager: PackageManager;
|
|
804
|
-
/** Health check path (default: '/health') */
|
|
805
|
-
healthCheckPath?: string;
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
/**
|
|
809
|
-
* Generate a Dockerfile for apps with a custom entry point.
|
|
810
|
-
* Uses esbuild to bundle the entry point into dist/index.mjs with all dependencies.
|
|
811
|
-
* This is used for apps that don't use gkm routes (e.g., Better Auth servers).
|
|
812
|
-
* @internal Exported for testing
|
|
813
|
-
*/
|
|
814
|
-
export function generateEntryDockerfile(
|
|
815
|
-
options: EntryDockerfileOptions,
|
|
816
|
-
): string {
|
|
817
|
-
const {
|
|
818
|
-
baseImage,
|
|
819
|
-
port,
|
|
820
|
-
appPath,
|
|
821
|
-
entry,
|
|
822
|
-
turboPackage,
|
|
823
|
-
packageManager,
|
|
824
|
-
healthCheckPath = '/health',
|
|
825
|
-
} = options;
|
|
826
|
-
|
|
827
|
-
const pm = getPmConfig(packageManager);
|
|
828
|
-
const installPm = pm.install ? `RUN ${pm.install}` : '';
|
|
829
|
-
const turboInstallCmd = getTurboInstallCmd(packageManager);
|
|
830
|
-
const turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';
|
|
831
|
-
|
|
832
|
-
return `# syntax=docker/dockerfile:1
|
|
833
|
-
# Entry-based Dockerfile with turbo prune + tsdown bundling
|
|
834
|
-
|
|
835
|
-
# Stage 1: Prune monorepo
|
|
836
|
-
FROM ${baseImage} AS pruner
|
|
837
|
-
|
|
838
|
-
WORKDIR /app
|
|
839
|
-
|
|
840
|
-
${installPm}
|
|
841
|
-
|
|
842
|
-
COPY . .
|
|
843
|
-
|
|
844
|
-
# Prune to only include necessary packages
|
|
845
|
-
RUN ${turboCmd} prune ${turboPackage} --docker
|
|
846
|
-
|
|
847
|
-
# Stage 2: Install dependencies
|
|
848
|
-
FROM ${baseImage} AS deps
|
|
849
|
-
|
|
850
|
-
WORKDIR /app
|
|
851
|
-
|
|
852
|
-
${installPm}
|
|
853
|
-
|
|
854
|
-
# Copy pruned lockfile and package.jsons
|
|
855
|
-
COPY --from=pruner /app/out/${pm.lockfile} ./
|
|
856
|
-
COPY --from=pruner /app/out/json/ ./
|
|
857
|
-
|
|
858
|
-
# Install dependencies
|
|
859
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
860
|
-
${turboInstallCmd}
|
|
861
|
-
|
|
862
|
-
# Stage 3: Build with tsdown
|
|
863
|
-
FROM deps AS builder
|
|
864
|
-
|
|
865
|
-
WORKDIR /app
|
|
866
|
-
|
|
867
|
-
# Build-time args for encrypted secrets
|
|
868
|
-
ARG GKM_ENCRYPTED_CREDENTIALS=""
|
|
869
|
-
ARG GKM_CREDENTIALS_IV=""
|
|
870
|
-
|
|
871
|
-
# Copy pruned source
|
|
872
|
-
COPY --from=pruner /app/out/full/ ./
|
|
873
|
-
|
|
874
|
-
# Copy workspace root configs for turbo builds (turbo prune doesn't include root configs)
|
|
875
|
-
# Using wildcard to make it optional for single-app projects
|
|
876
|
-
COPY --from=pruner /app/tsconfig.* ./
|
|
877
|
-
|
|
878
|
-
# Write encrypted credentials for tsdown to embed via define
|
|
879
|
-
RUN if [ -n "$GKM_ENCRYPTED_CREDENTIALS" ]; then \
|
|
880
|
-
mkdir -p ${appPath}/.gkm && \
|
|
881
|
-
echo "$GKM_ENCRYPTED_CREDENTIALS" > ${appPath}/.gkm/credentials.enc && \
|
|
882
|
-
echo "$GKM_CREDENTIALS_IV" > ${appPath}/.gkm/credentials.iv; \
|
|
883
|
-
fi
|
|
884
|
-
|
|
885
|
-
# Bundle entry point with esbuild (outputs to dist/index.mjs)
|
|
886
|
-
# Creates a fully standalone bundle with all dependencies included
|
|
887
|
-
# Use define to embed credentials if present
|
|
888
|
-
RUN cd ${appPath} && \
|
|
889
|
-
if [ -f .gkm/credentials.enc ]; then \
|
|
890
|
-
CREDS=$(cat .gkm/credentials.enc) && \
|
|
891
|
-
IV=$(cat .gkm/credentials.iv) && \
|
|
892
|
-
npx esbuild ${entry} --bundle --platform=node --target=node22 --format=esm \
|
|
893
|
-
--outfile=dist/index.mjs --packages=bundle \
|
|
894
|
-
--banner:js='import { createRequire } from "module"; const require = createRequire(import.meta.url);' \
|
|
895
|
-
--define:__GKM_ENCRYPTED_CREDENTIALS__="'\\"$CREDS\\"'" \
|
|
896
|
-
--define:__GKM_CREDENTIALS_IV__="'\\"$IV\\"'"; \
|
|
897
|
-
else \
|
|
898
|
-
npx esbuild ${entry} --bundle --platform=node --target=node22 --format=esm \
|
|
899
|
-
--outfile=dist/index.mjs --packages=bundle \
|
|
900
|
-
--banner:js='import { createRequire } from "module"; const require = createRequire(import.meta.url);'; \
|
|
901
|
-
fi
|
|
902
|
-
|
|
903
|
-
# Stage 4: Production
|
|
904
|
-
FROM ${baseImage} AS runner
|
|
905
|
-
|
|
906
|
-
WORKDIR /app
|
|
907
|
-
|
|
908
|
-
RUN apk add --no-cache tini
|
|
909
|
-
|
|
910
|
-
RUN addgroup --system --gid 1001 nodejs && \\
|
|
911
|
-
adduser --system --uid 1001 app
|
|
912
|
-
|
|
913
|
-
# Copy bundled output only (no node_modules needed - fully bundled)
|
|
914
|
-
COPY --from=builder --chown=app:nodejs /app/${appPath}/dist/index.mjs ./
|
|
915
|
-
|
|
916
|
-
ENV NODE_ENV=production
|
|
917
|
-
ENV PORT=${port}
|
|
918
|
-
|
|
919
|
-
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \\
|
|
920
|
-
CMD wget -qO- http://localhost:${port}${healthCheckPath} > /dev/null 2>&1 || exit 1
|
|
921
|
-
|
|
922
|
-
USER app
|
|
923
|
-
|
|
924
|
-
EXPOSE ${port}
|
|
925
|
-
|
|
926
|
-
ENTRYPOINT ["/sbin/tini", "--"]
|
|
927
|
-
CMD ["node", "index.mjs"]
|
|
928
|
-
`;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
/**
|
|
932
|
-
* Generate a Dockerfile for Node-based SSR web frameworks (TanStack Start,
|
|
933
|
-
* Remix). Builds with turbo, then runs the framework's production start
|
|
934
|
-
* script via `npm start`.
|
|
935
|
-
*
|
|
936
|
-
* Public URL build args are declared so framework bundlers (Vite, Vinxi)
|
|
937
|
-
* can inline them at build time. Per-framework prefix is the caller's job.
|
|
938
|
-
* @internal Exported for testing
|
|
939
|
-
*/
|
|
940
|
-
export function generateNodeWebDockerfile(
|
|
941
|
-
options: FrontendDockerfileOptions,
|
|
942
|
-
): string {
|
|
943
|
-
const {
|
|
944
|
-
baseImage,
|
|
945
|
-
port,
|
|
946
|
-
appPath,
|
|
947
|
-
turboPackage,
|
|
948
|
-
packageManager,
|
|
949
|
-
publicUrlArgs = [],
|
|
950
|
-
} = options;
|
|
951
|
-
|
|
952
|
-
const pm = getPmConfig(packageManager);
|
|
953
|
-
const installPm = pm.install ? `RUN ${pm.install}` : '';
|
|
954
|
-
const turboInstallCmd = getTurboInstallCmd(packageManager);
|
|
955
|
-
const turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';
|
|
956
|
-
const startCmd =
|
|
957
|
-
packageManager === 'pnpm'
|
|
958
|
-
? 'pnpm start'
|
|
959
|
-
: `${pm.lockfile.startsWith('package-lock') ? 'npm' : packageManager} start`;
|
|
960
|
-
|
|
961
|
-
const argDecls = publicUrlArgs.map((a) => `ARG ${a}=""`).join('\n');
|
|
962
|
-
const envDecls = publicUrlArgs.map((a) => `ENV ${a}=$${a}`).join('\n');
|
|
963
|
-
|
|
964
|
-
return `# syntax=docker/dockerfile:1
|
|
965
|
-
# Node SSR web Dockerfile (TanStack Start / Remix) with turbo prune
|
|
966
|
-
|
|
967
|
-
FROM ${baseImage} AS pruner
|
|
968
|
-
WORKDIR /app
|
|
969
|
-
${installPm}
|
|
970
|
-
COPY . .
|
|
971
|
-
RUN ${turboCmd} prune ${turboPackage} --docker
|
|
972
|
-
|
|
973
|
-
FROM ${baseImage} AS deps
|
|
974
|
-
WORKDIR /app
|
|
975
|
-
${installPm}
|
|
976
|
-
COPY --from=pruner /app/out/${pm.lockfile} ./
|
|
977
|
-
COPY --from=pruner /app/out/json/ ./
|
|
978
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
979
|
-
${turboInstallCmd}
|
|
980
|
-
|
|
981
|
-
FROM deps AS builder
|
|
982
|
-
WORKDIR /app
|
|
983
|
-
${argDecls}
|
|
984
|
-
${envDecls}
|
|
985
|
-
COPY --from=pruner /app/out/full/ ./
|
|
986
|
-
COPY --from=pruner /app/tsconfig.* ./
|
|
987
|
-
RUN ${turboCmd} run build --filter=${turboPackage}
|
|
988
|
-
|
|
989
|
-
FROM ${baseImage} AS runner
|
|
990
|
-
WORKDIR /app
|
|
991
|
-
RUN apk add --no-cache tini
|
|
992
|
-
RUN addgroup --system --gid 1001 nodejs && \\
|
|
993
|
-
adduser --system --uid 1001 app
|
|
994
|
-
|
|
995
|
-
# Copy the whole built workspace — frameworks differ on output paths
|
|
996
|
-
COPY --from=builder --chown=app:nodejs /app/ ./
|
|
997
|
-
|
|
998
|
-
ENV NODE_ENV=production
|
|
999
|
-
ENV PORT=${port}
|
|
1000
|
-
ENV HOSTNAME="0.0.0.0"
|
|
1001
|
-
|
|
1002
|
-
USER app
|
|
1003
|
-
EXPOSE ${port}
|
|
1004
|
-
|
|
1005
|
-
ENTRYPOINT ["/sbin/tini", "--"]
|
|
1006
|
-
CMD ["sh", "-c", "cd ${appPath} && ${startCmd}"]
|
|
1007
|
-
`;
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
/**
|
|
1011
|
-
* Generate a Dockerfile for Vite SPA apps. Builds the static bundle with
|
|
1012
|
-
* turbo, then serves it via nginx.
|
|
1013
|
-
* @internal Exported for testing
|
|
1014
|
-
*/
|
|
1015
|
-
export function generateViteStaticDockerfile(
|
|
1016
|
-
options: FrontendDockerfileOptions,
|
|
1017
|
-
): string {
|
|
1018
|
-
const {
|
|
1019
|
-
baseImage,
|
|
1020
|
-
port,
|
|
1021
|
-
appPath,
|
|
1022
|
-
turboPackage,
|
|
1023
|
-
packageManager,
|
|
1024
|
-
publicUrlArgs = [],
|
|
1025
|
-
} = options;
|
|
1026
|
-
|
|
1027
|
-
const pm = getPmConfig(packageManager);
|
|
1028
|
-
const installPm = pm.install ? `RUN ${pm.install}` : '';
|
|
1029
|
-
const turboInstallCmd = getTurboInstallCmd(packageManager);
|
|
1030
|
-
const turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';
|
|
1031
|
-
|
|
1032
|
-
const argDecls = publicUrlArgs.map((a) => `ARG ${a}=""`).join('\n');
|
|
1033
|
-
const envDecls = publicUrlArgs.map((a) => `ENV ${a}=$${a}`).join('\n');
|
|
1034
|
-
|
|
1035
|
-
return `# syntax=docker/dockerfile:1
|
|
1036
|
-
# Vite SPA Dockerfile — builds static assets, serves via nginx
|
|
1037
|
-
|
|
1038
|
-
FROM ${baseImage} AS pruner
|
|
1039
|
-
WORKDIR /app
|
|
1040
|
-
${installPm}
|
|
1041
|
-
COPY . .
|
|
1042
|
-
RUN ${turboCmd} prune ${turboPackage} --docker
|
|
1043
|
-
|
|
1044
|
-
FROM ${baseImage} AS deps
|
|
1045
|
-
WORKDIR /app
|
|
1046
|
-
${installPm}
|
|
1047
|
-
COPY --from=pruner /app/out/${pm.lockfile} ./
|
|
1048
|
-
COPY --from=pruner /app/out/json/ ./
|
|
1049
|
-
RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
1050
|
-
${turboInstallCmd}
|
|
1051
|
-
|
|
1052
|
-
FROM deps AS builder
|
|
1053
|
-
WORKDIR /app
|
|
1054
|
-
${argDecls}
|
|
1055
|
-
${envDecls}
|
|
1056
|
-
COPY --from=pruner /app/out/full/ ./
|
|
1057
|
-
COPY --from=pruner /app/tsconfig.* ./
|
|
1058
|
-
RUN ${turboCmd} run build --filter=${turboPackage}
|
|
1059
|
-
|
|
1060
|
-
FROM nginx:alpine AS runner
|
|
1061
|
-
COPY --from=builder /app/${appPath}/dist /usr/share/nginx/html
|
|
1062
|
-
RUN printf 'server {\\n listen ${port};\\n root /usr/share/nginx/html;\\n index index.html;\\n location / { try_files $uri $uri/ /index.html; }\\n}\\n' \\
|
|
1063
|
-
> /etc/nginx/conf.d/default.conf
|
|
1064
|
-
EXPOSE ${port}
|
|
1065
|
-
CMD ["nginx", "-g", "daemon off;"]
|
|
1066
|
-
`;
|
|
1067
|
-
}
|