@geekmidas/cli 2.0.2 → 10.0.0-alpha.0
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 +71 -120
- 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 +2329 -1584
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2306 -1561
- 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 -623
- 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/secrets/index.ts
DELETED
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import { loadConfig, loadWorkspaceConfig } from '../config';
|
|
4
|
-
import { generateFullstackCustomSecrets } from '../setup/fullstack-secrets';
|
|
5
|
-
import type { ComposeServiceName, ComposeServicesConfig } from '../types';
|
|
6
|
-
import { createStageSecrets, rotateServicePassword } from './generator';
|
|
7
|
-
import {
|
|
8
|
-
maskPassword,
|
|
9
|
-
readStageSecrets,
|
|
10
|
-
secretsExist,
|
|
11
|
-
setCustomSecret,
|
|
12
|
-
writeStageSecrets,
|
|
13
|
-
} from './storage';
|
|
14
|
-
|
|
15
|
-
const logger = console;
|
|
16
|
-
|
|
17
|
-
export interface SecretsInitOptions {
|
|
18
|
-
stage: string;
|
|
19
|
-
force?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface SecretsSetOptions {
|
|
23
|
-
stage: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface SecretsShowOptions {
|
|
27
|
-
stage: string;
|
|
28
|
-
reveal?: boolean;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface SecretsRotateOptions {
|
|
32
|
-
stage: string;
|
|
33
|
-
service?: ComposeServiceName;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface SecretsImportOptions {
|
|
37
|
-
stage: string;
|
|
38
|
-
/** Merge with existing secrets (default: true) */
|
|
39
|
-
merge?: boolean;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Extract service names from compose config.
|
|
44
|
-
*/
|
|
45
|
-
export function getServicesFromConfig(
|
|
46
|
-
services: ComposeServicesConfig | ComposeServiceName[] | undefined,
|
|
47
|
-
): ComposeServiceName[] {
|
|
48
|
-
if (!services) {
|
|
49
|
-
return [];
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (Array.isArray(services)) {
|
|
53
|
-
return services;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Object format - get keys where value is truthy
|
|
57
|
-
return (Object.entries(services) as [ComposeServiceName, unknown][])
|
|
58
|
-
.filter(([, config]) => config)
|
|
59
|
-
.map(([name]) => name);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Initialize secrets for a stage.
|
|
64
|
-
* Generates secure random passwords for configured services.
|
|
65
|
-
*/
|
|
66
|
-
export async function secretsInitCommand(
|
|
67
|
-
options: SecretsInitOptions,
|
|
68
|
-
): Promise<void> {
|
|
69
|
-
const { stage, force } = options;
|
|
70
|
-
|
|
71
|
-
// Check if secrets already exist
|
|
72
|
-
if (!force && secretsExist(stage)) {
|
|
73
|
-
logger.error(
|
|
74
|
-
`Secrets already exist for stage "${stage}". Use --force to overwrite.`,
|
|
75
|
-
);
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Load config to get services
|
|
80
|
-
const config = await loadConfig();
|
|
81
|
-
const services = getServicesFromConfig(config.docker?.compose?.services);
|
|
82
|
-
|
|
83
|
-
if (services.length === 0) {
|
|
84
|
-
logger.warn(
|
|
85
|
-
'No services configured in docker.compose.services. Creating secrets with empty services.',
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Detect workspace mode for project name and fullstack secrets
|
|
90
|
-
let projectName: string | undefined;
|
|
91
|
-
let workspaceSecrets: Record<string, string> | undefined;
|
|
92
|
-
try {
|
|
93
|
-
const loaded = await loadWorkspaceConfig();
|
|
94
|
-
projectName = loaded.workspace.name;
|
|
95
|
-
const isMultiApp = Object.keys(loaded.workspace.apps).length > 1;
|
|
96
|
-
|
|
97
|
-
if (isMultiApp) {
|
|
98
|
-
workspaceSecrets = generateFullstackCustomSecrets(loaded.workspace);
|
|
99
|
-
logger.log(' Detected workspace mode — generating per-app secrets');
|
|
100
|
-
}
|
|
101
|
-
} catch {
|
|
102
|
-
// Not a workspace — single-app mode, skip custom secrets
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Generate secrets (with project name so DATABASE_URL matches app-specific URLs)
|
|
106
|
-
const secrets = createStageSecrets(stage, services, { projectName });
|
|
107
|
-
|
|
108
|
-
if (workspaceSecrets) {
|
|
109
|
-
secrets.custom = workspaceSecrets;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Write to file
|
|
113
|
-
await writeStageSecrets(secrets);
|
|
114
|
-
|
|
115
|
-
logger.log(`\n✓ Secrets initialized for stage "${stage}"`);
|
|
116
|
-
logger.log(` Location: .gkm/secrets/${stage}.json`);
|
|
117
|
-
logger.log('\n Generated credentials for:');
|
|
118
|
-
|
|
119
|
-
for (const service of services) {
|
|
120
|
-
logger.log(` - ${service}`);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (secrets.urls.DATABASE_URL) {
|
|
124
|
-
logger.log(`\n DATABASE_URL: ${maskUrl(secrets.urls.DATABASE_URL)}`);
|
|
125
|
-
}
|
|
126
|
-
if (secrets.urls.REDIS_URL) {
|
|
127
|
-
logger.log(` REDIS_URL: ${maskUrl(secrets.urls.REDIS_URL)}`);
|
|
128
|
-
}
|
|
129
|
-
if (secrets.urls.RABBITMQ_URL) {
|
|
130
|
-
logger.log(` RABBITMQ_URL: ${maskUrl(secrets.urls.RABBITMQ_URL)}`);
|
|
131
|
-
}
|
|
132
|
-
if (secrets.urls.STORAGE_ENDPOINT) {
|
|
133
|
-
logger.log(` STORAGE_ENDPOINT: ${secrets.urls.STORAGE_ENDPOINT}`);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (Object.keys(secrets.custom).length > 0) {
|
|
137
|
-
logger.log(`\n Custom secrets: ${Object.keys(secrets.custom).length}`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
logger.log(`\n Use "gkm secrets:show --stage ${stage}" to view secrets`);
|
|
141
|
-
logger.log(
|
|
142
|
-
' Use "gkm secrets:set <KEY> <VALUE> --stage ' +
|
|
143
|
-
stage +
|
|
144
|
-
'" to add custom secrets',
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Read all data from stdin.
|
|
150
|
-
*/
|
|
151
|
-
async function readStdin(): Promise<string> {
|
|
152
|
-
const chunks: Buffer[] = [];
|
|
153
|
-
|
|
154
|
-
for await (const chunk of process.stdin) {
|
|
155
|
-
chunks.push(chunk);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return Buffer.concat(chunks).toString('utf-8').trim();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Set a custom secret.
|
|
163
|
-
* If value is not provided, reads from stdin.
|
|
164
|
-
*/
|
|
165
|
-
export async function secretsSetCommand(
|
|
166
|
-
key: string,
|
|
167
|
-
value: string | undefined,
|
|
168
|
-
options: SecretsSetOptions,
|
|
169
|
-
): Promise<void> {
|
|
170
|
-
const { stage } = options;
|
|
171
|
-
|
|
172
|
-
// Read from stdin if value not provided
|
|
173
|
-
let secretValue = value;
|
|
174
|
-
if (!secretValue) {
|
|
175
|
-
if (process.stdin.isTTY) {
|
|
176
|
-
logger.error(
|
|
177
|
-
'No value provided. Use: gkm secrets:set KEY VALUE --stage <stage>',
|
|
178
|
-
);
|
|
179
|
-
logger.error(
|
|
180
|
-
'Or pipe from stdin: echo "value" | gkm secrets:set KEY --stage <stage>',
|
|
181
|
-
);
|
|
182
|
-
process.exit(1);
|
|
183
|
-
}
|
|
184
|
-
secretValue = await readStdin();
|
|
185
|
-
if (!secretValue) {
|
|
186
|
-
logger.error('No value received from stdin');
|
|
187
|
-
process.exit(1);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
try {
|
|
192
|
-
await setCustomSecret(stage, key, secretValue);
|
|
193
|
-
logger.log(`\n✓ Secret "${key}" set for stage "${stage}"`);
|
|
194
|
-
} catch (error) {
|
|
195
|
-
logger.error(
|
|
196
|
-
error instanceof Error ? error.message : 'Failed to set secret',
|
|
197
|
-
);
|
|
198
|
-
process.exit(1);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Show secrets for a stage.
|
|
204
|
-
*/
|
|
205
|
-
export async function secretsShowCommand(
|
|
206
|
-
options: SecretsShowOptions,
|
|
207
|
-
): Promise<void> {
|
|
208
|
-
const { stage, reveal } = options;
|
|
209
|
-
|
|
210
|
-
const secrets = await readStageSecrets(stage);
|
|
211
|
-
|
|
212
|
-
if (!secrets) {
|
|
213
|
-
logger.error(
|
|
214
|
-
`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`,
|
|
215
|
-
);
|
|
216
|
-
process.exit(1);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
logger.log(`\nSecrets for stage "${stage}":`);
|
|
220
|
-
logger.log(` Created: ${secrets.createdAt}`);
|
|
221
|
-
logger.log(` Updated: ${secrets.updatedAt}`);
|
|
222
|
-
|
|
223
|
-
// Show service credentials
|
|
224
|
-
logger.log('\nService Credentials:');
|
|
225
|
-
for (const [service, creds] of Object.entries(secrets.services)) {
|
|
226
|
-
if (creds) {
|
|
227
|
-
logger.log(`\n ${service}:`);
|
|
228
|
-
logger.log(` host: ${creds.host}`);
|
|
229
|
-
logger.log(` port: ${creds.port}`);
|
|
230
|
-
logger.log(` username: ${creds.username}`);
|
|
231
|
-
logger.log(
|
|
232
|
-
` password: ${reveal ? creds.password : maskPassword(creds.password)}`,
|
|
233
|
-
);
|
|
234
|
-
if (creds.database) {
|
|
235
|
-
logger.log(` database: ${creds.database}`);
|
|
236
|
-
}
|
|
237
|
-
if (creds.vhost) {
|
|
238
|
-
logger.log(` vhost: ${creds.vhost}`);
|
|
239
|
-
}
|
|
240
|
-
if (creds.bucket) {
|
|
241
|
-
logger.log(` bucket: ${creds.bucket}`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Show URLs
|
|
247
|
-
logger.log('\nConnection URLs:');
|
|
248
|
-
if (secrets.urls.DATABASE_URL) {
|
|
249
|
-
logger.log(
|
|
250
|
-
` DATABASE_URL: ${reveal ? secrets.urls.DATABASE_URL : maskUrl(secrets.urls.DATABASE_URL)}`,
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
if (secrets.urls.REDIS_URL) {
|
|
254
|
-
logger.log(
|
|
255
|
-
` REDIS_URL: ${reveal ? secrets.urls.REDIS_URL : maskUrl(secrets.urls.REDIS_URL)}`,
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
if (secrets.urls.RABBITMQ_URL) {
|
|
259
|
-
logger.log(
|
|
260
|
-
` RABBITMQ_URL: ${reveal ? secrets.urls.RABBITMQ_URL : maskUrl(secrets.urls.RABBITMQ_URL)}`,
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
if (secrets.urls.STORAGE_ENDPOINT) {
|
|
264
|
-
logger.log(` STORAGE_ENDPOINT: ${secrets.urls.STORAGE_ENDPOINT}`);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Show custom secrets
|
|
268
|
-
const customKeys = Object.keys(secrets.custom);
|
|
269
|
-
if (customKeys.length > 0) {
|
|
270
|
-
logger.log('\nCustom Secrets:');
|
|
271
|
-
for (const [key, value] of Object.entries(secrets.custom)) {
|
|
272
|
-
logger.log(` ${key}: ${reveal ? value : maskPassword(value)}`);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (!reveal) {
|
|
277
|
-
logger.log('\nUse --reveal to show actual values');
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Rotate passwords for services.
|
|
283
|
-
*/
|
|
284
|
-
export async function secretsRotateCommand(
|
|
285
|
-
options: SecretsRotateOptions,
|
|
286
|
-
): Promise<void> {
|
|
287
|
-
const { stage, service } = options;
|
|
288
|
-
|
|
289
|
-
const secrets = await readStageSecrets(stage);
|
|
290
|
-
|
|
291
|
-
if (!secrets) {
|
|
292
|
-
logger.error(
|
|
293
|
-
`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`,
|
|
294
|
-
);
|
|
295
|
-
process.exit(1);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (service) {
|
|
299
|
-
// Rotate specific service
|
|
300
|
-
if (!secrets.services[service]) {
|
|
301
|
-
logger.error(`Service "${service}" not configured in stage "${stage}"`);
|
|
302
|
-
process.exit(1);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const updated = rotateServicePassword(secrets, service);
|
|
306
|
-
await writeStageSecrets(updated);
|
|
307
|
-
logger.log(`\n✓ Password rotated for ${service} in stage "${stage}"`);
|
|
308
|
-
} else {
|
|
309
|
-
// Rotate all services
|
|
310
|
-
let updated = secrets;
|
|
311
|
-
const services = Object.keys(secrets.services) as ComposeServiceName[];
|
|
312
|
-
|
|
313
|
-
for (const svc of services) {
|
|
314
|
-
updated = rotateServicePassword(updated, svc);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
await writeStageSecrets(updated);
|
|
318
|
-
logger.log(
|
|
319
|
-
`\n✓ Passwords rotated for all services in stage "${stage}": ${services.join(', ')}`,
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
logger.log(`\nUse "gkm secrets:show --stage ${stage}" to view new values`);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Import secrets from a JSON file.
|
|
328
|
-
*/
|
|
329
|
-
export async function secretsImportCommand(
|
|
330
|
-
file: string,
|
|
331
|
-
options: SecretsImportOptions,
|
|
332
|
-
): Promise<void> {
|
|
333
|
-
const { stage, merge = true } = options;
|
|
334
|
-
|
|
335
|
-
// Check if file exists
|
|
336
|
-
if (!existsSync(file)) {
|
|
337
|
-
logger.error(`File not found: ${file}`);
|
|
338
|
-
process.exit(1);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// Read and parse JSON file
|
|
342
|
-
let importedSecrets: Record<string, string>;
|
|
343
|
-
try {
|
|
344
|
-
const content = await readFile(file, 'utf-8');
|
|
345
|
-
importedSecrets = JSON.parse(content);
|
|
346
|
-
|
|
347
|
-
// Validate it's a flat object with string values
|
|
348
|
-
if (typeof importedSecrets !== 'object' || importedSecrets === null) {
|
|
349
|
-
throw new Error('JSON must be an object');
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
for (const [key, value] of Object.entries(importedSecrets)) {
|
|
353
|
-
if (typeof value !== 'string') {
|
|
354
|
-
throw new Error(
|
|
355
|
-
`Value for "${key}" must be a string, got ${typeof value}`,
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
} catch (error) {
|
|
360
|
-
logger.error(
|
|
361
|
-
`Failed to parse JSON file: ${error instanceof Error ? error.message : 'Invalid JSON'}`,
|
|
362
|
-
);
|
|
363
|
-
process.exit(1);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Check if secrets exist for stage
|
|
367
|
-
const secrets = await readStageSecrets(stage);
|
|
368
|
-
|
|
369
|
-
if (!secrets) {
|
|
370
|
-
logger.error(
|
|
371
|
-
`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`,
|
|
372
|
-
);
|
|
373
|
-
process.exit(1);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Merge or replace custom secrets
|
|
377
|
-
const updatedCustom = merge
|
|
378
|
-
? { ...secrets.custom, ...importedSecrets }
|
|
379
|
-
: importedSecrets;
|
|
380
|
-
|
|
381
|
-
const updated = {
|
|
382
|
-
...secrets,
|
|
383
|
-
updatedAt: new Date().toISOString(),
|
|
384
|
-
custom: updatedCustom,
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
await writeStageSecrets(updated);
|
|
388
|
-
|
|
389
|
-
const importedCount = Object.keys(importedSecrets).length;
|
|
390
|
-
const totalCount = Object.keys(updatedCustom).length;
|
|
391
|
-
|
|
392
|
-
logger.log(`\n✓ Imported ${importedCount} secrets for stage "${stage}"`);
|
|
393
|
-
|
|
394
|
-
if (merge && totalCount > importedCount) {
|
|
395
|
-
logger.log(` Total custom secrets: ${totalCount}`);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
logger.log('\n Imported keys:');
|
|
399
|
-
for (const key of Object.keys(importedSecrets)) {
|
|
400
|
-
logger.log(` - ${key}`);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Mask password in a URL for display.
|
|
406
|
-
*/
|
|
407
|
-
export function maskUrl(url: string): string {
|
|
408
|
-
try {
|
|
409
|
-
const parsed = new URL(url);
|
|
410
|
-
if (parsed.password) {
|
|
411
|
-
parsed.password = maskPassword(parsed.password);
|
|
412
|
-
}
|
|
413
|
-
return parsed.toString();
|
|
414
|
-
} catch {
|
|
415
|
-
return url;
|
|
416
|
-
}
|
|
417
|
-
}
|
package/src/secrets/keystore.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from 'node:crypto';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
3
|
-
import { chmod, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
4
|
-
import { homedir } from 'node:os';
|
|
5
|
-
import { basename, join } from 'node:path';
|
|
6
|
-
|
|
7
|
-
/** Key length for AES-256 encryption */
|
|
8
|
-
const KEY_LENGTH = 32; // 256 bits
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Get the keystore directory for a project.
|
|
12
|
-
* Keys are stored at ~/.gkm/{project-name}/
|
|
13
|
-
*
|
|
14
|
-
* @param projectName - Name of the project (defaults to current directory name)
|
|
15
|
-
* @returns Path to the keystore directory
|
|
16
|
-
*/
|
|
17
|
-
export function getKeystoreDir(projectName?: string): string {
|
|
18
|
-
const name = projectName ?? basename(process.cwd());
|
|
19
|
-
return join(homedir(), '.gkm', name);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get the path to a stage's encryption key.
|
|
24
|
-
*
|
|
25
|
-
* @param stage - Stage name (e.g., 'development', 'production')
|
|
26
|
-
* @param projectName - Name of the project (defaults to current directory name)
|
|
27
|
-
* @returns Path to the key file
|
|
28
|
-
*/
|
|
29
|
-
export function getKeyPath(stage: string, projectName?: string): string {
|
|
30
|
-
return join(getKeystoreDir(projectName), `${stage}.key`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Check if a key exists for a stage.
|
|
35
|
-
*/
|
|
36
|
-
export function keyExists(stage: string, projectName?: string): boolean {
|
|
37
|
-
return existsSync(getKeyPath(stage, projectName));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Generate a new encryption key for a stage.
|
|
42
|
-
* The key is stored at ~/.gkm/{project-name}/{stage}.key with restricted permissions.
|
|
43
|
-
*
|
|
44
|
-
* @param stage - Stage name
|
|
45
|
-
* @param projectName - Project name (defaults to current directory name)
|
|
46
|
-
* @returns The generated key as a hex string
|
|
47
|
-
*/
|
|
48
|
-
export async function generateKey(
|
|
49
|
-
stage: string,
|
|
50
|
-
projectName?: string,
|
|
51
|
-
): Promise<string> {
|
|
52
|
-
const keyDir = getKeystoreDir(projectName);
|
|
53
|
-
const keyPath = getKeyPath(stage, projectName);
|
|
54
|
-
|
|
55
|
-
// Ensure keystore directory exists with restricted permissions
|
|
56
|
-
await mkdir(keyDir, { recursive: true, mode: 0o700 });
|
|
57
|
-
|
|
58
|
-
// Generate random key
|
|
59
|
-
const key = randomBytes(KEY_LENGTH).toString('hex');
|
|
60
|
-
|
|
61
|
-
// Write key with restricted permissions (owner read/write only)
|
|
62
|
-
await writeFile(keyPath, key, { mode: 0o600, encoding: 'utf-8' });
|
|
63
|
-
|
|
64
|
-
// Ensure permissions are set correctly (in case file existed)
|
|
65
|
-
await chmod(keyPath, 0o600);
|
|
66
|
-
|
|
67
|
-
return key;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Read an encryption key for a stage.
|
|
72
|
-
*
|
|
73
|
-
* @param stage - Stage name
|
|
74
|
-
* @param projectName - Project name (defaults to current directory name)
|
|
75
|
-
* @returns The key as a hex string, or null if not found
|
|
76
|
-
*/
|
|
77
|
-
export async function readKey(
|
|
78
|
-
stage: string,
|
|
79
|
-
projectName?: string,
|
|
80
|
-
): Promise<string | null> {
|
|
81
|
-
const keyPath = getKeyPath(stage, projectName);
|
|
82
|
-
|
|
83
|
-
if (!existsSync(keyPath)) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const key = await readFile(keyPath, 'utf-8');
|
|
88
|
-
return key.trim();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Read an encryption key for a stage, throwing if not found.
|
|
93
|
-
*/
|
|
94
|
-
export async function requireKey(
|
|
95
|
-
stage: string,
|
|
96
|
-
projectName?: string,
|
|
97
|
-
): Promise<string> {
|
|
98
|
-
const key = await readKey(stage, projectName);
|
|
99
|
-
|
|
100
|
-
if (!key) {
|
|
101
|
-
const name = projectName ?? basename(process.cwd());
|
|
102
|
-
throw new Error(
|
|
103
|
-
`Encryption key not found for stage "${stage}" in project "${name}". ` +
|
|
104
|
-
`Expected key at: ${getKeyPath(stage, projectName)}`,
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return key;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Delete a key for a stage.
|
|
113
|
-
*/
|
|
114
|
-
export async function deleteKey(
|
|
115
|
-
stage: string,
|
|
116
|
-
projectName?: string,
|
|
117
|
-
): Promise<void> {
|
|
118
|
-
const keyPath = getKeyPath(stage, projectName);
|
|
119
|
-
|
|
120
|
-
if (existsSync(keyPath)) {
|
|
121
|
-
await rm(keyPath);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Get or create a key for a stage.
|
|
127
|
-
* If the key already exists, it is returned. Otherwise, a new key is generated.
|
|
128
|
-
*
|
|
129
|
-
* @param stage - Stage name
|
|
130
|
-
* @param projectName - Project name (defaults to current directory name)
|
|
131
|
-
* @returns The key as a hex string
|
|
132
|
-
*/
|
|
133
|
-
export async function getOrCreateKey(
|
|
134
|
-
stage: string,
|
|
135
|
-
projectName?: string,
|
|
136
|
-
): Promise<string> {
|
|
137
|
-
const existingKey = await readKey(stage, projectName);
|
|
138
|
-
|
|
139
|
-
if (existingKey) {
|
|
140
|
-
return existingKey;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return generateKey(stage, projectName);
|
|
144
|
-
}
|
package/src/secrets/reconcile.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { generateFullstackCustomSecrets } from '../setup/fullstack-secrets.js';
|
|
2
|
-
import type { NormalizedWorkspace } from '../workspace/types.js';
|
|
3
|
-
import type { StageSecrets } from './types.js';
|
|
4
|
-
|
|
5
|
-
export interface ReconcileResult {
|
|
6
|
-
/** The updated secrets with missing keys backfilled */
|
|
7
|
-
secrets: StageSecrets;
|
|
8
|
-
/** Keys that were added */
|
|
9
|
-
addedKeys: string[];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Reconcile missing custom secrets for a workspace.
|
|
14
|
-
*
|
|
15
|
-
* Compares current secrets against what generateFullstackCustomSecrets()
|
|
16
|
-
* would produce and backfills any missing keys without overwriting
|
|
17
|
-
* existing values.
|
|
18
|
-
*
|
|
19
|
-
* @returns ReconcileResult if keys were added, null if secrets are up-to-date
|
|
20
|
-
*/
|
|
21
|
-
export function reconcileMissingSecrets(
|
|
22
|
-
secrets: StageSecrets,
|
|
23
|
-
workspace: NormalizedWorkspace,
|
|
24
|
-
): ReconcileResult | null {
|
|
25
|
-
const isMultiApp = Object.keys(workspace.apps).length > 1;
|
|
26
|
-
if (!isMultiApp) {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const expectedCustom = generateFullstackCustomSecrets(workspace);
|
|
31
|
-
const addedKeys: string[] = [];
|
|
32
|
-
const mergedCustom = { ...secrets.custom };
|
|
33
|
-
|
|
34
|
-
for (const [key, value] of Object.entries(expectedCustom)) {
|
|
35
|
-
if (!(key in mergedCustom)) {
|
|
36
|
-
mergedCustom[key] = value;
|
|
37
|
-
addedKeys.push(key);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (addedKeys.length === 0) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
secrets: {
|
|
47
|
-
...secrets,
|
|
48
|
-
updatedAt: new Date().toISOString(),
|
|
49
|
-
custom: mergedCustom,
|
|
50
|
-
},
|
|
51
|
-
addedKeys,
|
|
52
|
-
};
|
|
53
|
-
}
|