@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/setup/index.ts
DELETED
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import prompts from 'prompts';
|
|
4
|
-
import { loadWorkspaceConfig } from '../config.js';
|
|
5
|
-
import {
|
|
6
|
-
resolveServicePorts,
|
|
7
|
-
startWorkspaceServices,
|
|
8
|
-
} from '../credentials/index.js';
|
|
9
|
-
import {
|
|
10
|
-
createStageSecrets,
|
|
11
|
-
generateConnectionUrls,
|
|
12
|
-
generateLocalStackCredentials,
|
|
13
|
-
generateSecurePassword,
|
|
14
|
-
generateServiceCredentials,
|
|
15
|
-
} from '../secrets/generator.js';
|
|
16
|
-
import {
|
|
17
|
-
readStageSecrets,
|
|
18
|
-
secretsExist,
|
|
19
|
-
writeStageSecrets,
|
|
20
|
-
} from '../secrets/storage.js';
|
|
21
|
-
import { isSSMConfigured, pullSecrets, pushSecrets } from '../secrets/sync.js';
|
|
22
|
-
import type { StageSecrets } from '../secrets/types.js';
|
|
23
|
-
import type { ComposeServiceName } from '../types.js';
|
|
24
|
-
import type { LoadedConfig, NormalizedWorkspace } from '../workspace/types.js';
|
|
25
|
-
import {
|
|
26
|
-
generateFullstackCustomSecrets,
|
|
27
|
-
writeDockerEnvFromSecrets,
|
|
28
|
-
} from './fullstack-secrets.js';
|
|
29
|
-
|
|
30
|
-
const logger = console;
|
|
31
|
-
|
|
32
|
-
export interface SetupOptions {
|
|
33
|
-
stage?: string;
|
|
34
|
-
force?: boolean;
|
|
35
|
-
skipDocker?: boolean;
|
|
36
|
-
yes?: boolean;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Setup development environment.
|
|
41
|
-
*
|
|
42
|
-
* Orchestrates:
|
|
43
|
-
* 1. Load workspace config
|
|
44
|
-
* 2. Resolve secrets (local → SSM → generate fresh)
|
|
45
|
-
* 3. Write docker/.env from secrets
|
|
46
|
-
* 4. Start Docker services
|
|
47
|
-
*/
|
|
48
|
-
export async function setupCommand(options: SetupOptions = {}): Promise<void> {
|
|
49
|
-
const stage = options.stage ?? 'development';
|
|
50
|
-
|
|
51
|
-
logger.log('\n🔧 Setting up development environment...\n');
|
|
52
|
-
|
|
53
|
-
// 1. Load workspace config
|
|
54
|
-
let loadedConfig: LoadedConfig;
|
|
55
|
-
try {
|
|
56
|
-
loadedConfig = await loadWorkspaceConfig();
|
|
57
|
-
} catch {
|
|
58
|
-
logger.error(
|
|
59
|
-
'❌ No gkm.config.ts found. Run this command from a workspace root.',
|
|
60
|
-
);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const { workspace } = loadedConfig;
|
|
65
|
-
const isMultiApp = Object.keys(workspace.apps).length > 1;
|
|
66
|
-
|
|
67
|
-
logger.log(`📦 Workspace: ${workspace.name}`);
|
|
68
|
-
logger.log(`📱 Apps: ${Object.keys(workspace.apps).join(', ')}`);
|
|
69
|
-
logger.log(`🔑 Stage: ${stage}\n`);
|
|
70
|
-
|
|
71
|
-
// 2. Resolve secrets
|
|
72
|
-
const secrets = await resolveSecrets(stage, workspace, options);
|
|
73
|
-
|
|
74
|
-
if (!secrets) {
|
|
75
|
-
logger.error('❌ Failed to resolve secrets. Exiting.');
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// 3. Write docker/.env from secrets (always regenerated as derived file)
|
|
80
|
-
if (isMultiApp && workspace.services.db) {
|
|
81
|
-
await writeDockerEnvFromSecrets(secrets, workspace.root);
|
|
82
|
-
logger.log('📄 Generated docker/.env with database passwords');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 4. Start Docker services with resolved ports
|
|
86
|
-
if (!options.skipDocker) {
|
|
87
|
-
const composeFile = join(workspace.root, 'docker-compose.yml');
|
|
88
|
-
if (existsSync(composeFile)) {
|
|
89
|
-
logger.log('');
|
|
90
|
-
const resolvedPorts = await resolveServicePorts(workspace.root);
|
|
91
|
-
await startWorkspaceServices(workspace, resolvedPorts.dockerEnv);
|
|
92
|
-
} else {
|
|
93
|
-
logger.log('⚠️ No docker-compose.yml found. Skipping Docker services.');
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Print summary
|
|
98
|
-
printSummary(workspace, stage);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Resolve secrets with priority:
|
|
103
|
-
* 1. Local secrets exist → use them (preserves manual additions)
|
|
104
|
-
* 2. SSM configured and has secrets → pull and use
|
|
105
|
-
* 3. Neither → generate fresh secrets
|
|
106
|
-
*
|
|
107
|
-
* --force skips checks 1 and 2 and always regenerates.
|
|
108
|
-
*/
|
|
109
|
-
async function resolveSecrets(
|
|
110
|
-
stage: string,
|
|
111
|
-
workspace: NormalizedWorkspace,
|
|
112
|
-
options: SetupOptions,
|
|
113
|
-
) {
|
|
114
|
-
// Force regeneration
|
|
115
|
-
if (options.force) {
|
|
116
|
-
logger.log('🔐 Generating fresh secrets (--force)...');
|
|
117
|
-
return generateFreshSecrets(stage, workspace, options);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Check local secrets first
|
|
121
|
-
if (secretsExist(stage, workspace.root)) {
|
|
122
|
-
logger.log('🔐 Using existing local secrets');
|
|
123
|
-
const secrets = await readStageSecrets(stage, workspace.root);
|
|
124
|
-
if (secrets) {
|
|
125
|
-
// Reconcile: add any missing workspace-derived keys without overwriting
|
|
126
|
-
const reconciled = reconcileSecrets(secrets, workspace);
|
|
127
|
-
if (reconciled) {
|
|
128
|
-
await writeStageSecrets(reconciled, workspace.root);
|
|
129
|
-
}
|
|
130
|
-
return reconciled ?? secrets;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Try SSM pull if configured
|
|
135
|
-
if (isSSMConfigured(workspace)) {
|
|
136
|
-
logger.log('☁️ Checking for remote secrets in SSM...');
|
|
137
|
-
try {
|
|
138
|
-
const remoteSecrets = await pullSecrets(stage, workspace);
|
|
139
|
-
if (remoteSecrets) {
|
|
140
|
-
logger.log('✅ Pulled secrets from SSM');
|
|
141
|
-
await writeStageSecrets(remoteSecrets, workspace.root);
|
|
142
|
-
return remoteSecrets;
|
|
143
|
-
}
|
|
144
|
-
logger.log(' No remote secrets found');
|
|
145
|
-
} catch (error) {
|
|
146
|
-
logger.warn(`⚠️ Failed to pull from SSM: ${(error as Error).message}`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Generate fresh secrets
|
|
151
|
-
logger.log('🔐 Generating fresh development secrets...');
|
|
152
|
-
return generateFreshSecrets(stage, workspace, options);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Reconcile existing secrets with expected workspace-derived keys.
|
|
157
|
-
* Adds missing keys (e.g. BETTER_AUTH_*) without overwriting existing values.
|
|
158
|
-
* Returns the updated secrets if changes were made, or null if no changes needed.
|
|
159
|
-
* @internal Exported for testing
|
|
160
|
-
*/
|
|
161
|
-
export function reconcileSecrets(
|
|
162
|
-
secrets: StageSecrets,
|
|
163
|
-
workspace: NormalizedWorkspace,
|
|
164
|
-
): StageSecrets | null {
|
|
165
|
-
let changed = false;
|
|
166
|
-
let result = { ...secrets };
|
|
167
|
-
|
|
168
|
-
// Reconcile service credentials: add missing services
|
|
169
|
-
const serviceMap: {
|
|
170
|
-
key: keyof typeof workspace.services;
|
|
171
|
-
name: ComposeServiceName;
|
|
172
|
-
}[] = [
|
|
173
|
-
{ key: 'db', name: 'postgres' },
|
|
174
|
-
{ key: 'cache', name: 'redis' },
|
|
175
|
-
{ key: 'storage', name: 'minio' },
|
|
176
|
-
{ key: 'mail', name: 'mailpit' },
|
|
177
|
-
];
|
|
178
|
-
|
|
179
|
-
for (const { key, name } of serviceMap) {
|
|
180
|
-
if (workspace.services[key] && !result.services[name]) {
|
|
181
|
-
const creds = generateServiceCredentials(name);
|
|
182
|
-
// Override defaults with project-derived names
|
|
183
|
-
if (name === 'minio') {
|
|
184
|
-
creds.bucket = workspace.name;
|
|
185
|
-
creds.username = workspace.name;
|
|
186
|
-
}
|
|
187
|
-
result = {
|
|
188
|
-
...result,
|
|
189
|
-
services: { ...result.services, [name]: creds },
|
|
190
|
-
};
|
|
191
|
-
result.urls = generateConnectionUrls(
|
|
192
|
-
result.services,
|
|
193
|
-
result.eventsBackend,
|
|
194
|
-
);
|
|
195
|
-
logger.log(` 🔄 Adding missing service credentials: ${name}`);
|
|
196
|
-
changed = true;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Always add pgboss credentials when postgres is available
|
|
201
|
-
if (result.services.postgres && !result.services.pgboss) {
|
|
202
|
-
result = {
|
|
203
|
-
...result,
|
|
204
|
-
services: {
|
|
205
|
-
...result.services,
|
|
206
|
-
pgboss: {
|
|
207
|
-
host: result.services.postgres.host,
|
|
208
|
-
port: result.services.postgres.port,
|
|
209
|
-
username: 'pgboss',
|
|
210
|
-
password: generateSecurePassword(),
|
|
211
|
-
database: result.services.postgres.database ?? 'app',
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
result.urls = generateConnectionUrls(result.services, result.eventsBackend);
|
|
216
|
-
logger.log(' 🔄 Adding missing service credentials: pgboss');
|
|
217
|
-
changed = true;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Reconcile events backend
|
|
221
|
-
const eventsBackend = workspace.services.events;
|
|
222
|
-
if (eventsBackend && result.eventsBackend !== eventsBackend) {
|
|
223
|
-
result.eventsBackend = eventsBackend;
|
|
224
|
-
|
|
225
|
-
// Add localstack credentials if needed
|
|
226
|
-
if (eventsBackend === 'sns' && !result.services.localstack) {
|
|
227
|
-
result = {
|
|
228
|
-
...result,
|
|
229
|
-
services: {
|
|
230
|
-
...result.services,
|
|
231
|
-
localstack: generateLocalStackCredentials(),
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
logger.log(' 🔄 Adding missing service credentials: localstack');
|
|
235
|
-
changed = true;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Add rabbitmq credentials if needed (for rabbitmq events)
|
|
239
|
-
if (eventsBackend === 'rabbitmq' && !result.services.rabbitmq) {
|
|
240
|
-
result = {
|
|
241
|
-
...result,
|
|
242
|
-
services: {
|
|
243
|
-
...result.services,
|
|
244
|
-
rabbitmq: generateServiceCredentials('rabbitmq'),
|
|
245
|
-
},
|
|
246
|
-
};
|
|
247
|
-
logger.log(' 🔄 Adding missing service credentials: rabbitmq');
|
|
248
|
-
changed = true;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Regenerate URLs with new events backend
|
|
252
|
-
result.urls = generateConnectionUrls(result.services, eventsBackend);
|
|
253
|
-
changed = true;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Reconcile custom secrets for multi-app workspaces
|
|
257
|
-
const isMultiApp = Object.keys(workspace.apps).length > 1;
|
|
258
|
-
if (isMultiApp) {
|
|
259
|
-
const expected = generateFullstackCustomSecrets(workspace);
|
|
260
|
-
const missing: Record<string, string> = {};
|
|
261
|
-
|
|
262
|
-
for (const [key, value] of Object.entries(expected)) {
|
|
263
|
-
if (!(key in result.custom)) {
|
|
264
|
-
missing[key] = value;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (Object.keys(missing).length > 0) {
|
|
269
|
-
logger.log(
|
|
270
|
-
` 🔄 Adding missing secrets: ${Object.keys(missing).join(', ')}`,
|
|
271
|
-
);
|
|
272
|
-
result = {
|
|
273
|
-
...result,
|
|
274
|
-
custom: { ...result.custom, ...missing },
|
|
275
|
-
};
|
|
276
|
-
changed = true;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (!changed) {
|
|
281
|
-
return null;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return {
|
|
285
|
-
...result,
|
|
286
|
-
updatedAt: new Date().toISOString(),
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Build a fresh StageSecrets object for a workspace: service credentials,
|
|
292
|
-
* connection URLs, and custom secrets. Pure — does not write to disk or touch
|
|
293
|
-
* SSM. Service passwords are freshly randomized, so the result must be the same
|
|
294
|
-
* one used to start the matching Docker containers.
|
|
295
|
-
* @internal Exported for reuse by `gkm test` auto-setup.
|
|
296
|
-
*/
|
|
297
|
-
export function createFreshWorkspaceSecrets(
|
|
298
|
-
stage: string,
|
|
299
|
-
workspace: NormalizedWorkspace,
|
|
300
|
-
): StageSecrets {
|
|
301
|
-
// Determine services from workspace config
|
|
302
|
-
const serviceNames: ComposeServiceName[] = [];
|
|
303
|
-
if (workspace.services.db) serviceNames.push('postgres');
|
|
304
|
-
if (workspace.services.cache) serviceNames.push('redis');
|
|
305
|
-
if (workspace.services.storage) serviceNames.push('minio');
|
|
306
|
-
if (workspace.services.mail) serviceNames.push('mailpit');
|
|
307
|
-
if (workspace.services.events === 'sns') serviceNames.push('localstack');
|
|
308
|
-
if (workspace.services.events === 'rabbitmq') serviceNames.push('rabbitmq');
|
|
309
|
-
|
|
310
|
-
// Create base secrets with service credentials
|
|
311
|
-
const secrets = createStageSecrets(stage, serviceNames, {
|
|
312
|
-
projectName: workspace.name,
|
|
313
|
-
eventsBackend: workspace.services.events,
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
// Generate fullstack-aware custom secrets
|
|
317
|
-
const isMultiApp = Object.keys(workspace.apps).length > 1;
|
|
318
|
-
if (isMultiApp) {
|
|
319
|
-
secrets.custom = generateFullstackCustomSecrets(workspace);
|
|
320
|
-
} else {
|
|
321
|
-
secrets.custom = {
|
|
322
|
-
NODE_ENV: 'development',
|
|
323
|
-
PORT: '3000',
|
|
324
|
-
LOG_LEVEL: 'debug',
|
|
325
|
-
JWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return secrets;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Ensure a usable secret set exists for a stage, generating a fresh one from the
|
|
334
|
-
* workspace config when none is present. No-op if secrets already exist.
|
|
335
|
-
*
|
|
336
|
-
* Powers `gkm test --auto-setup` / `GKM_AUTO_SETUP`: CI can run without a
|
|
337
|
-
* committed secrets file or a shared encryption key — the stage is regenerated
|
|
338
|
-
* from the committed `gkm.config.ts`, and `writeStageSecrets` mints a local key.
|
|
339
|
-
*
|
|
340
|
-
* @returns true if fresh secrets were generated, false if existing ones were kept
|
|
341
|
-
*/
|
|
342
|
-
export async function ensureStageSecrets(
|
|
343
|
-
stage: string,
|
|
344
|
-
cwd: string = process.cwd(),
|
|
345
|
-
): Promise<boolean> {
|
|
346
|
-
const { workspace } = await loadWorkspaceConfig(cwd);
|
|
347
|
-
|
|
348
|
-
if (secretsExist(stage, workspace.root)) {
|
|
349
|
-
return false;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const secrets = createFreshWorkspaceSecrets(stage, workspace);
|
|
353
|
-
await writeStageSecrets(secrets, workspace.root);
|
|
354
|
-
return true;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Generate fresh secrets for the workspace.
|
|
359
|
-
*/
|
|
360
|
-
async function generateFreshSecrets(
|
|
361
|
-
stage: string,
|
|
362
|
-
workspace: NormalizedWorkspace,
|
|
363
|
-
options: SetupOptions,
|
|
364
|
-
) {
|
|
365
|
-
const secrets = createFreshWorkspaceSecrets(stage, workspace);
|
|
366
|
-
|
|
367
|
-
// Write secrets
|
|
368
|
-
await writeStageSecrets(secrets, workspace.root);
|
|
369
|
-
logger.log(` Secrets written to .gkm/secrets/${stage}.json`);
|
|
370
|
-
|
|
371
|
-
// Offer to push to SSM if configured
|
|
372
|
-
if (isSSMConfigured(workspace) && !options.yes) {
|
|
373
|
-
const { shouldPush } = await prompts({
|
|
374
|
-
type: 'confirm',
|
|
375
|
-
name: 'shouldPush',
|
|
376
|
-
message: 'Push secrets to SSM for team sharing?',
|
|
377
|
-
initial: true,
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
if (shouldPush) {
|
|
381
|
-
try {
|
|
382
|
-
await pushSecrets(stage, workspace);
|
|
383
|
-
logger.log('☁️ Secrets pushed to SSM');
|
|
384
|
-
} catch (error) {
|
|
385
|
-
logger.warn(`⚠️ Failed to push to SSM: ${(error as Error).message}`);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return secrets;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* Print setup summary with next steps.
|
|
395
|
-
*/
|
|
396
|
-
function printSummary(workspace: NormalizedWorkspace, stage: string): void {
|
|
397
|
-
logger.log(`\n${'─'.repeat(50)}`);
|
|
398
|
-
logger.log('\n✅ Development environment ready!\n');
|
|
399
|
-
|
|
400
|
-
logger.log('📋 Apps:');
|
|
401
|
-
for (const [name, app] of Object.entries(workspace.apps)) {
|
|
402
|
-
const icon =
|
|
403
|
-
app.type === 'web' ? '🌐' : app.type === 'mobile' ? '📱' : '🔧';
|
|
404
|
-
logger.log(` ${icon} ${name} → http://localhost:${app.port}`);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
logger.log('\n🚀 Next steps:');
|
|
408
|
-
logger.log(' gkm dev # Start all apps');
|
|
409
|
-
logger.log(` gkm secrets:show --stage ${stage} # View secrets`);
|
|
410
|
-
logger.log('');
|
|
411
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { normalizeWorkspace } from '../../../workspace/index';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Simulates the secrets that gkm init generates for a fullstack workspace.
|
|
5
|
-
* In production these come from the encrypted store via toEmbeddableSecrets.
|
|
6
|
-
*/
|
|
7
|
-
export function createFullstackSecrets(): Record<string, string> {
|
|
8
|
-
return {
|
|
9
|
-
NODE_ENV: 'development',
|
|
10
|
-
PORT: '3000',
|
|
11
|
-
LOG_LEVEL: 'debug',
|
|
12
|
-
JWT_SECRET: 'dev-jwt-secret',
|
|
13
|
-
// Per-app database URLs (fullstack workspace)
|
|
14
|
-
API_DATABASE_URL: 'postgresql://api:api-pass@localhost:5432/my-saas',
|
|
15
|
-
AUTH_DATABASE_URL: 'postgresql://auth:auth-pass@localhost:5432/my-saas',
|
|
16
|
-
API_DB_PASSWORD: 'api-pass',
|
|
17
|
-
AUTH_DB_PASSWORD: 'auth-pass',
|
|
18
|
-
// Auth service secrets
|
|
19
|
-
AUTH_PORT: '3002',
|
|
20
|
-
AUTH_URL: 'http://localhost:3002',
|
|
21
|
-
BETTER_AUTH_SECRET: 'better-auth-secret-123',
|
|
22
|
-
BETTER_AUTH_URL: 'http://localhost:3002',
|
|
23
|
-
BETTER_AUTH_TRUSTED_ORIGINS: 'http://localhost:3000,http://localhost:3001',
|
|
24
|
-
// Service credentials
|
|
25
|
-
POSTGRES_USER: 'api',
|
|
26
|
-
POSTGRES_PASSWORD: 'api-pass',
|
|
27
|
-
POSTGRES_DB: 'my-saas',
|
|
28
|
-
POSTGRES_HOST: 'localhost',
|
|
29
|
-
POSTGRES_PORT: '5432',
|
|
30
|
-
REDIS_PASSWORD: 'redis-pass',
|
|
31
|
-
REDIS_HOST: 'localhost',
|
|
32
|
-
REDIS_PORT: '6379',
|
|
33
|
-
// URLs
|
|
34
|
-
DATABASE_URL: 'postgresql://api:api-pass@localhost:5432/my-saas',
|
|
35
|
-
REDIS_URL: 'redis://:redis-pass@localhost:6379',
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function createFullstackWorkspace(): ReturnType<
|
|
40
|
-
typeof normalizeWorkspace
|
|
41
|
-
> {
|
|
42
|
-
return normalizeWorkspace(
|
|
43
|
-
{
|
|
44
|
-
apps: {
|
|
45
|
-
api: {
|
|
46
|
-
type: 'backend',
|
|
47
|
-
path: 'apps/api',
|
|
48
|
-
port: 3000,
|
|
49
|
-
routes: './src/endpoints/**/*.ts',
|
|
50
|
-
dependencies: [],
|
|
51
|
-
},
|
|
52
|
-
auth: {
|
|
53
|
-
type: 'backend',
|
|
54
|
-
path: 'apps/auth',
|
|
55
|
-
port: 3002,
|
|
56
|
-
entry: './src/index.ts',
|
|
57
|
-
dependencies: [],
|
|
58
|
-
},
|
|
59
|
-
web: {
|
|
60
|
-
type: 'web',
|
|
61
|
-
path: 'apps/web',
|
|
62
|
-
port: 3001,
|
|
63
|
-
framework: 'nextjs',
|
|
64
|
-
dependencies: ['api', 'auth'],
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
'/project',
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Simulates what loadSecretsForApp does for a specific app:
|
|
74
|
-
* maps {APP}_DATABASE_URL -> DATABASE_URL.
|
|
75
|
-
*/
|
|
76
|
-
export function mapSecretsForApp(
|
|
77
|
-
secrets: Record<string, string>,
|
|
78
|
-
appName: string,
|
|
79
|
-
): Record<string, string> {
|
|
80
|
-
const prefix = appName.toUpperCase();
|
|
81
|
-
const mapped = { ...secrets };
|
|
82
|
-
const appDbUrl = secrets[`${prefix}_DATABASE_URL`];
|
|
83
|
-
if (appDbUrl) {
|
|
84
|
-
mapped.DATABASE_URL = appDbUrl;
|
|
85
|
-
}
|
|
86
|
-
return mapped;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export const COMPOSE_FULL = `
|
|
90
|
-
services:
|
|
91
|
-
postgres:
|
|
92
|
-
image: postgres:17
|
|
93
|
-
ports:
|
|
94
|
-
- '\${POSTGRES_HOST_PORT:-5432}:5432'
|
|
95
|
-
redis:
|
|
96
|
-
image: redis:7
|
|
97
|
-
ports:
|
|
98
|
-
- '\${REDIS_HOST_PORT:-6379}:6379'
|
|
99
|
-
mailpit:
|
|
100
|
-
image: axllent/mailpit
|
|
101
|
-
ports:
|
|
102
|
-
- '\${SMTP_PORT:-1025}:1025'
|
|
103
|
-
- '\${MAILPIT_PORT:-8025}:8025'
|
|
104
|
-
`;
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { tmpdir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import {
|
|
5
|
-
afterAll,
|
|
6
|
-
afterEach,
|
|
7
|
-
beforeAll,
|
|
8
|
-
beforeEach,
|
|
9
|
-
describe,
|
|
10
|
-
expect,
|
|
11
|
-
it,
|
|
12
|
-
vi,
|
|
13
|
-
} from 'vitest';
|
|
14
|
-
import {
|
|
15
|
-
loadPortState,
|
|
16
|
-
parseComposePortMappings,
|
|
17
|
-
rewriteUrlsWithPorts,
|
|
18
|
-
savePortState,
|
|
19
|
-
} from '../../dev/index';
|
|
20
|
-
import { getDependencyEnvVars } from '../../workspace/index';
|
|
21
|
-
import { rewriteDatabaseUrlForTests } from '../index';
|
|
22
|
-
import {
|
|
23
|
-
COMPOSE_FULL,
|
|
24
|
-
createFullstackSecrets,
|
|
25
|
-
createFullstackWorkspace,
|
|
26
|
-
mapSecretsForApp,
|
|
27
|
-
} from './__fixtures__/workspace';
|
|
28
|
-
|
|
29
|
-
beforeAll(() => {
|
|
30
|
-
vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
afterAll(() => {
|
|
34
|
-
vi.restoreAllMocks();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
describe('api app context', () => {
|
|
38
|
-
let testDir: string;
|
|
39
|
-
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
testDir = join(tmpdir(), `gkm-api-test-${Date.now()}`);
|
|
42
|
-
mkdirSync(testDir, { recursive: true });
|
|
43
|
-
writeFileSync(join(testDir, 'docker-compose.yml'), COMPOSE_FULL);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
afterEach(() => {
|
|
47
|
-
rmSync(testDir, { recursive: true, force: true });
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should resolve DATABASE_URL from API_DATABASE_URL', () => {
|
|
51
|
-
const apiSecrets = mapSecretsForApp(createFullstackSecrets(), 'api');
|
|
52
|
-
|
|
53
|
-
expect(apiSecrets.DATABASE_URL).toBe(
|
|
54
|
-
'postgresql://api:api-pass@localhost:5432/my-saas',
|
|
55
|
-
);
|
|
56
|
-
expect(apiSecrets.API_DATABASE_URL).toBe(
|
|
57
|
-
'postgresql://api:api-pass@localhost:5432/my-saas',
|
|
58
|
-
);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should rewrite DATABASE_URL and REDIS_URL when ports are remapped', async () => {
|
|
62
|
-
await savePortState(testDir, {
|
|
63
|
-
POSTGRES_HOST_PORT: 5433,
|
|
64
|
-
REDIS_HOST_PORT: 6380,
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
let secrets = mapSecretsForApp(createFullstackSecrets(), 'api');
|
|
68
|
-
|
|
69
|
-
const mappings = parseComposePortMappings(
|
|
70
|
-
join(testDir, 'docker-compose.yml'),
|
|
71
|
-
);
|
|
72
|
-
const ports = await loadPortState(testDir);
|
|
73
|
-
secrets = rewriteUrlsWithPorts(secrets, {
|
|
74
|
-
dockerEnv: {},
|
|
75
|
-
ports,
|
|
76
|
-
mappings,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
expect(secrets.DATABASE_URL).toBe(
|
|
80
|
-
'postgresql://api:api-pass@localhost:5433/my-saas',
|
|
81
|
-
);
|
|
82
|
-
expect(secrets.API_DATABASE_URL).toBe(
|
|
83
|
-
'postgresql://api:api-pass@localhost:5433/my-saas',
|
|
84
|
-
);
|
|
85
|
-
expect(secrets.REDIS_URL).toBe('redis://:redis-pass@localhost:6380');
|
|
86
|
-
// AUTH_URL is an app URL, not a docker service
|
|
87
|
-
expect(secrets.AUTH_URL).toBe('http://localhost:3002');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should rewrite only postgres when redis port unchanged', async () => {
|
|
91
|
-
await savePortState(testDir, {
|
|
92
|
-
POSTGRES_HOST_PORT: 5433,
|
|
93
|
-
REDIS_HOST_PORT: 6379,
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
let secrets = mapSecretsForApp(createFullstackSecrets(), 'api');
|
|
97
|
-
|
|
98
|
-
const mappings = parseComposePortMappings(
|
|
99
|
-
join(testDir, 'docker-compose.yml'),
|
|
100
|
-
);
|
|
101
|
-
const ports = await loadPortState(testDir);
|
|
102
|
-
secrets = rewriteUrlsWithPorts(secrets, {
|
|
103
|
-
dockerEnv: {},
|
|
104
|
-
ports,
|
|
105
|
-
mappings,
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
expect(secrets.DATABASE_URL).toBe(
|
|
109
|
-
'postgresql://api:api-pass@localhost:5433/my-saas',
|
|
110
|
-
);
|
|
111
|
-
// Redis port unchanged — URL stays the same
|
|
112
|
-
expect(secrets.REDIS_URL).toBe('redis://:redis-pass@localhost:6379');
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('should apply full pipeline for gkm test in api context', async () => {
|
|
116
|
-
await savePortState(testDir, {
|
|
117
|
-
POSTGRES_HOST_PORT: 5433,
|
|
118
|
-
REDIS_HOST_PORT: 6380,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
let secrets = mapSecretsForApp(createFullstackSecrets(), 'api');
|
|
122
|
-
|
|
123
|
-
const mappings = parseComposePortMappings(
|
|
124
|
-
join(testDir, 'docker-compose.yml'),
|
|
125
|
-
);
|
|
126
|
-
const ports = await loadPortState(testDir);
|
|
127
|
-
secrets = rewriteUrlsWithPorts(secrets, {
|
|
128
|
-
dockerEnv: {},
|
|
129
|
-
ports,
|
|
130
|
-
mappings,
|
|
131
|
-
});
|
|
132
|
-
secrets = rewriteDatabaseUrlForTests(secrets);
|
|
133
|
-
|
|
134
|
-
// Port rewrite + _test suffix
|
|
135
|
-
expect(secrets.DATABASE_URL).toBe(
|
|
136
|
-
'postgresql://api:api-pass@localhost:5433/my-saas_test',
|
|
137
|
-
);
|
|
138
|
-
expect(secrets.API_DATABASE_URL).toBe(
|
|
139
|
-
'postgresql://api:api-pass@localhost:5433/my-saas_test',
|
|
140
|
-
);
|
|
141
|
-
// AUTH_DATABASE_URL also gets both rewrites
|
|
142
|
-
expect(secrets.AUTH_DATABASE_URL).toBe(
|
|
143
|
-
'postgresql://auth:auth-pass@localhost:5433/my-saas_test',
|
|
144
|
-
);
|
|
145
|
-
// Non-database URLs unaffected
|
|
146
|
-
expect(secrets.REDIS_URL).toBe('redis://:redis-pass@localhost:6380');
|
|
147
|
-
expect(secrets.AUTH_URL).toBe('http://localhost:3002');
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('should use default ports when no port state saved', async () => {
|
|
151
|
-
let secrets = mapSecretsForApp(createFullstackSecrets(), 'api');
|
|
152
|
-
|
|
153
|
-
const mappings = parseComposePortMappings(
|
|
154
|
-
join(testDir, 'docker-compose.yml'),
|
|
155
|
-
);
|
|
156
|
-
const ports = await loadPortState(testDir);
|
|
157
|
-
|
|
158
|
-
if (Object.keys(ports).length > 0) {
|
|
159
|
-
secrets = rewriteUrlsWithPorts(secrets, {
|
|
160
|
-
dockerEnv: {},
|
|
161
|
-
ports,
|
|
162
|
-
mappings,
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
secrets = rewriteDatabaseUrlForTests(secrets);
|
|
166
|
-
|
|
167
|
-
expect(secrets.DATABASE_URL).toBe(
|
|
168
|
-
'postgresql://api:api-pass@localhost:5432/my-saas_test',
|
|
169
|
-
);
|
|
170
|
-
expect(secrets.REDIS_URL).toBe('redis://:redis-pass@localhost:6379');
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('should not inject dependency URLs for api app (no dependencies)', () => {
|
|
174
|
-
const workspace = createFullstackWorkspace();
|
|
175
|
-
const depEnv = getDependencyEnvVars(workspace, 'api');
|
|
176
|
-
|
|
177
|
-
expect(depEnv).toEqual({});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('should keep BETTER_AUTH vars available for api to call auth service', async () => {
|
|
181
|
-
await savePortState(testDir, { POSTGRES_HOST_PORT: 5433 });
|
|
182
|
-
|
|
183
|
-
let secrets = mapSecretsForApp(createFullstackSecrets(), 'api');
|
|
184
|
-
|
|
185
|
-
const mappings = parseComposePortMappings(
|
|
186
|
-
join(testDir, 'docker-compose.yml'),
|
|
187
|
-
);
|
|
188
|
-
const ports = await loadPortState(testDir);
|
|
189
|
-
secrets = rewriteUrlsWithPorts(secrets, {
|
|
190
|
-
dockerEnv: {},
|
|
191
|
-
ports,
|
|
192
|
-
mappings,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
// API app may need AUTH_URL to call auth service internally
|
|
196
|
-
expect(secrets.AUTH_URL).toBe('http://localhost:3002');
|
|
197
|
-
expect(secrets.BETTER_AUTH_URL).toBe('http://localhost:3002');
|
|
198
|
-
});
|
|
199
|
-
});
|