@geekmidas/cli 10.0.0-alpha.116 → 10.0.0-alpha.118

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.
Files changed (134) hide show
  1. package/README.md +7 -2
  2. package/dist/{GoDaddyProvider-BDvIMTO-.cjs → GoDaddyProvider-B6SPHBCU.cjs} +2 -2
  3. package/dist/{GoDaddyProvider-BDvIMTO-.cjs.map → GoDaddyProvider-B6SPHBCU.cjs.map} +1 -1
  4. package/dist/{GoDaddyProvider-eW1mre1g.mjs → GoDaddyProvider-CcjbFkLt.mjs} +2 -2
  5. package/dist/{GoDaddyProvider-eW1mre1g.mjs.map → GoDaddyProvider-CcjbFkLt.mjs.map} +1 -1
  6. package/dist/{LegacyStateStore-DFeykTd8.cjs → LegacyStateStore-2l5jw_VI.cjs} +3 -3
  7. package/dist/{LegacyStateStore-DFeykTd8.cjs.map → LegacyStateStore-2l5jw_VI.cjs.map} +1 -1
  8. package/dist/{LegacyStateStore-Ba1_x0cr.mjs → LegacyStateStore-D-D6r_JT.mjs} +3 -3
  9. package/dist/{LegacyStateStore-Ba1_x0cr.mjs.map → LegacyStateStore-D-D6r_JT.mjs.map} +1 -1
  10. package/dist/{LocalStateStore-C1rUUvBr.mjs → LocalStateStore-DIAY7j1O.mjs} +2 -2
  11. package/dist/{LocalStateStore-C1rUUvBr.mjs.map → LocalStateStore-DIAY7j1O.mjs.map} +1 -1
  12. package/dist/{LocalStateStore-CV-04jpI.cjs → LocalStateStore-Dg3rvwwe.cjs} +2 -2
  13. package/dist/{LocalStateStore-CV-04jpI.cjs.map → LocalStateStore-Dg3rvwwe.cjs.map} +1 -1
  14. package/dist/{S3StateStore-Dszt4fN5.mjs → S3StateStore-BKi1eamw.mjs} +2 -2
  15. package/dist/{S3StateStore-Dszt4fN5.mjs.map → S3StateStore-BKi1eamw.mjs.map} +1 -1
  16. package/dist/{S3StateStore-CqYi-1sb.cjs → S3StateStore-BdcgQNhO.cjs} +2 -2
  17. package/dist/{S3StateStore-CqYi-1sb.cjs.map → S3StateStore-BdcgQNhO.cjs.map} +1 -1
  18. package/dist/{SSMStateStore-zpHjDCAW.cjs → SSMStateStore-CS-pAKT9.cjs} +2 -2
  19. package/dist/{SSMStateStore-zpHjDCAW.cjs.map → SSMStateStore-CS-pAKT9.cjs.map} +1 -1
  20. package/dist/{SSMStateStore-BYRUyMkE.mjs → SSMStateStore-DHgaNW75.mjs} +2 -2
  21. package/dist/{SSMStateStore-BYRUyMkE.mjs.map → SSMStateStore-DHgaNW75.mjs.map} +1 -1
  22. package/dist/{add-0XI8_HOf.cjs → add-6VPdRbRT.cjs} +3 -3
  23. package/dist/{add-0XI8_HOf.cjs.map → add-6VPdRbRT.cjs.map} +1 -1
  24. package/dist/{add-DXdJjp0b.mjs → add-BcZXHa3Z.mjs} +3 -3
  25. package/dist/{add-DXdJjp0b.mjs.map → add-BcZXHa3Z.mjs.map} +1 -1
  26. package/dist/{bundler-CgcwaVI0.mjs → bundler-Ciim6amq.mjs} +7 -59
  27. package/dist/bundler-Ciim6amq.mjs.map +1 -0
  28. package/dist/{bundler-B2_2-Dum.cjs → bundler-jjWtQ882.cjs} +6 -58
  29. package/dist/bundler-jjWtQ882.cjs.map +1 -0
  30. package/dist/{cli-H0uB_znq.mjs → cli-BkxlWYfI.mjs} +2 -2
  31. package/dist/{cli-H0uB_znq.mjs.map → cli-BkxlWYfI.mjs.map} +1 -1
  32. package/dist/{cli-5k6kV_i4.cjs → cli-CQ2ij0Mi.cjs} +2 -2
  33. package/dist/{cli-5k6kV_i4.cjs.map → cli-CQ2ij0Mi.cjs.map} +1 -1
  34. package/dist/{compose-CYeMW2_o.cjs → compose-JOasAHcd.cjs} +4 -4
  35. package/dist/{compose-CYeMW2_o.cjs.map → compose-JOasAHcd.cjs.map} +1 -1
  36. package/dist/{compose-BEiJWrB7.mjs → compose-qLTNYJAY.mjs} +4 -4
  37. package/dist/{compose-BEiJWrB7.mjs.map → compose-qLTNYJAY.mjs.map} +1 -1
  38. package/dist/deploy/public.cjs +6 -6
  39. package/dist/deploy/public.d.cts.map +1 -1
  40. package/dist/deploy/public.d.mts.map +1 -1
  41. package/dist/deploy/public.mjs +6 -6
  42. package/dist/{deploy-Q5qo1OP-.cjs → deploy-D-liNXfx.cjs} +5 -5
  43. package/dist/{deploy-Q5qo1OP-.cjs.map → deploy-D-liNXfx.cjs.map} +1 -1
  44. package/dist/{deploy-Cyx5fSb7.mjs → deploy-_g-2dX38.mjs} +5 -5
  45. package/dist/{deploy-Cyx5fSb7.mjs.map → deploy-_g-2dX38.mjs.map} +1 -1
  46. package/dist/{dns-CsApfzLc.mjs → dns-DGq4xkJT.mjs} +2 -2
  47. package/dist/{dns-CsApfzLc.mjs.map → dns-DGq4xkJT.mjs.map} +1 -1
  48. package/dist/{dns-v9viladZ.cjs → dns-DfQKqAyt.cjs} +2 -2
  49. package/dist/{dns-v9viladZ.cjs.map → dns-DfQKqAyt.cjs.map} +1 -1
  50. package/dist/{dokploy-DfUo_QRw.mjs → dokploy-ClIPZaPH.mjs} +2 -2
  51. package/dist/{dokploy-DfUo_QRw.mjs.map → dokploy-ClIPZaPH.mjs.map} +1 -1
  52. package/dist/{dokploy-Di7rC2z0.cjs → dokploy-D17I2BCE.cjs} +2 -2
  53. package/dist/{dokploy-Di7rC2z0.cjs.map → dokploy-D17I2BCE.cjs.map} +1 -1
  54. package/dist/{drivers-D11JHxrD.mjs → drivers-3klmg9Sk.mjs} +22 -4
  55. package/dist/drivers-3klmg9Sk.mjs.map +1 -0
  56. package/dist/{drivers-GKaA6ITM.cjs → drivers-CoqD5zYP.cjs} +27 -3
  57. package/dist/drivers-CoqD5zYP.cjs.map +1 -0
  58. package/dist/{eas-CTfRmndW.mjs → eas-DJXhARYb.mjs} +2 -2
  59. package/dist/{eas-CTfRmndW.mjs.map → eas-DJXhARYb.mjs.map} +1 -1
  60. package/dist/{eas-CIvNT6qa.cjs → eas-b95MCG14.cjs} +2 -2
  61. package/dist/{eas-CIvNT6qa.cjs.map → eas-b95MCG14.cjs.map} +1 -1
  62. package/dist/{encryption--U4NsK7N.cjs → encryption-C_NRQ9cY.cjs} +2 -2
  63. package/dist/{encryption--U4NsK7N.cjs.map → encryption-C_NRQ9cY.cjs.map} +1 -1
  64. package/dist/{encryption-BpTPmd7h.mjs → encryption-CldvLtip.mjs} +2 -2
  65. package/dist/{encryption-BpTPmd7h.mjs.map → encryption-CldvLtip.mjs.map} +1 -1
  66. package/dist/{engine-BFmHfek1.mjs → engine-BBnTj8OD.mjs} +12 -6
  67. package/dist/engine-BBnTj8OD.mjs.map +1 -0
  68. package/dist/{engine-Ovl1PB6i.cjs → engine-CKfdvEVt.cjs} +11 -5
  69. package/dist/engine-CKfdvEVt.cjs.map +1 -0
  70. package/dist/{github-tWAGuR9i.mjs → github-BMPci2wg.mjs} +4 -4
  71. package/dist/{github-tWAGuR9i.mjs.map → github-BMPci2wg.mjs.map} +1 -1
  72. package/dist/{github-CTlPQ5Ra.cjs → github-D5Ck3srU.cjs} +4 -4
  73. package/dist/{github-CTlPQ5Ra.cjs.map → github-D5Ck3srU.cjs.map} +1 -1
  74. package/dist/{googlePlay-BNH729It.cjs → googlePlay-C-GBRDMp.cjs} +3 -3
  75. package/dist/{googlePlay-BNH729It.cjs.map → googlePlay-C-GBRDMp.cjs.map} +1 -1
  76. package/dist/{googlePlay-m1De-qIJ.mjs → googlePlay-fw0VWly7.mjs} +3 -3
  77. package/dist/{googlePlay-m1De-qIJ.mjs.map → googlePlay-fw0VWly7.mjs.map} +1 -1
  78. package/dist/index.cjs +245 -139
  79. package/dist/index.cjs.map +1 -1
  80. package/dist/index.mjs +245 -139
  81. package/dist/index.mjs.map +1 -1
  82. package/dist/{migrate-4B4RgAjU.mjs → migrate-1bHqjfIe.mjs} +2 -2
  83. package/dist/{migrate-4B4RgAjU.mjs.map → migrate-1bHqjfIe.mjs.map} +1 -1
  84. package/dist/{migrate-DZ2--SaO.cjs → migrate-BndHuwqw.cjs} +2 -2
  85. package/dist/{migrate-DZ2--SaO.cjs.map → migrate-BndHuwqw.cjs.map} +1 -1
  86. package/dist/{migrate-X0Y7fz3N.mjs → migrate-WyWhSivN.mjs} +2 -2
  87. package/dist/{migrate-X0Y7fz3N.mjs.map → migrate-WyWhSivN.mjs.map} +1 -1
  88. package/dist/{migrate-BYEmpoIg.cjs → migrate-rke2Qvj2.cjs} +2 -2
  89. package/dist/{migrate-BYEmpoIg.cjs.map → migrate-rke2Qvj2.cjs.map} +1 -1
  90. package/dist/{publish-BUvYjiZH.cjs → publish-B22IhdS9.cjs} +2 -2
  91. package/dist/{publish-BUvYjiZH.cjs.map → publish-B22IhdS9.cjs.map} +1 -1
  92. package/dist/{publish-hhgraEhO.mjs → publish-BBG4zx8E.mjs} +2 -2
  93. package/dist/{publish-hhgraEhO.mjs.map → publish-BBG4zx8E.mjs.map} +1 -1
  94. package/dist/{ready-CIt5SOtg.mjs → ready-4hEoQ_cr.mjs} +2 -2
  95. package/dist/{ready-CIt5SOtg.mjs.map → ready-4hEoQ_cr.mjs.map} +1 -1
  96. package/dist/{ready-BMFjxBYA.cjs → ready-gc9IFByS.cjs} +2 -2
  97. package/dist/{ready-BMFjxBYA.cjs.map → ready-gc9IFByS.cjs.map} +1 -1
  98. package/dist/{resolve-DotGHvtX.mjs → resolve-CC6ndodR.mjs} +3 -3
  99. package/dist/{resolve-DotGHvtX.mjs.map → resolve-CC6ndodR.mjs.map} +1 -1
  100. package/dist/{resolve-DdFKTx8l.cjs → resolve-isFTuJp4.cjs} +3 -3
  101. package/dist/{resolve-DdFKTx8l.cjs.map → resolve-isFTuJp4.cjs.map} +1 -1
  102. package/dist/{rollback-9t9G3c_u.mjs → rollback-DaEmEC2Y.mjs} +4 -4
  103. package/dist/{rollback-9t9G3c_u.mjs.map → rollback-DaEmEC2Y.mjs.map} +1 -1
  104. package/dist/{rollback-D4xeUQvG.cjs → rollback-Lj9bQvHq.cjs} +4 -4
  105. package/dist/{rollback-D4xeUQvG.cjs.map → rollback-Lj9bQvHq.cjs.map} +1 -1
  106. package/dist/{seeds-DbKNcs3o.cjs → seeds-CF9Nx6_g.cjs} +33 -6
  107. package/dist/seeds-CF9Nx6_g.cjs.map +1 -0
  108. package/dist/{seeds-CRkKeyW0.mjs → seeds-CYzoBDg2.mjs} +33 -6
  109. package/dist/seeds-CYzoBDg2.mjs.map +1 -0
  110. package/dist/{serverSetup-DlRKRfTi.mjs → serverSetup-0h1Vh5un.mjs} +5 -5
  111. package/dist/{serverSetup-DlRKRfTi.mjs.map → serverSetup-0h1Vh5un.mjs.map} +1 -1
  112. package/dist/{serverSetup-CcWgNtiC.cjs → serverSetup-CbuJK4zg.cjs} +5 -5
  113. package/dist/{serverSetup-CcWgNtiC.cjs.map → serverSetup-CbuJK4zg.cjs.map} +1 -1
  114. package/dist/{sniffer-CakkKKqQ.mjs → sniffer-CRJHtBaK.mjs} +6 -6
  115. package/dist/{sniffer-CakkKKqQ.mjs.map → sniffer-CRJHtBaK.mjs.map} +1 -1
  116. package/dist/{sniffer-B6T6za4n.cjs → sniffer-Dz3Va1Jo.cjs} +6 -6
  117. package/dist/{sniffer-B6T6za4n.cjs.map → sniffer-Dz3Va1Jo.cjs.map} +1 -1
  118. package/dist/{stage-Mp6qQIoD.mjs → stage-CIo8s2WT.mjs} +4 -4
  119. package/dist/{stage-Mp6qQIoD.mjs.map → stage-CIo8s2WT.mjs.map} +1 -1
  120. package/dist/{stage-W3PUt7ar.cjs → stage-y9qFelxT.cjs} +4 -4
  121. package/dist/{stage-W3PUt7ar.cjs.map → stage-y9qFelxT.cjs.map} +1 -1
  122. package/dist/target/public.cjs +1 -1
  123. package/dist/target/public.mjs +1 -1
  124. package/dist/vitest.cjs +1 -1
  125. package/dist/vitest.mjs +1 -1
  126. package/package.json +15 -15
  127. package/dist/bundler-B2_2-Dum.cjs.map +0 -1
  128. package/dist/bundler-CgcwaVI0.mjs.map +0 -1
  129. package/dist/drivers-D11JHxrD.mjs.map +0 -1
  130. package/dist/drivers-GKaA6ITM.cjs.map +0 -1
  131. package/dist/engine-BFmHfek1.mjs.map +0 -1
  132. package/dist/engine-Ovl1PB6i.cjs.map +0 -1
  133. package/dist/seeds-CRkKeyW0.mjs.map +0 -1
  134. package/dist/seeds-DbKNcs3o.cjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -3,27 +3,28 @@ import { n as __require, t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mj
3
3
  import { n as isGkmError, t as GkmError } from "./errors-D8Gwp5kU.mjs";
4
4
  import { r as DEFAULT_TIMEOUT_MS, t as CommandFailed } from "./run-BJLIerMM.mjs";
5
5
  import { a as getDokployCredentials, d as removeGoDaddyCredentials, f as storeDokployCredentials, i as getCredentialsPath, l as readCredentials, m as storeHostingerToken, o as getDokployRegistryId, p as storeGoDaddyToken, s as getDokployToken, u as removeDokployCredentials } from "./credentials-B5N5yKk6.mjs";
6
- import { C as dockerCompose, S as sshTarget, _ as parseDigests, b as dockerHost, c as edgeRef, f as derivedCredentials, h as EDGE_PROJECT, i as ComposePushNeedsBuild, l as removeEdgeRoutes, m as stackPlan, o as stackOverrideFile, p as stackDir, r as ComposePinNeedsPull, t as composeTarget, u as composeProject, v as pinnedRef, w as projectNetwork, y as composeServer } from "./compose-BEiJWrB7.mjs";
6
+ import { C as dockerCompose, S as sshTarget, _ as parseDigests, b as dockerHost, c as edgeRef, f as derivedCredentials, h as EDGE_PROJECT, i as ComposePushNeedsBuild, l as removeEdgeRoutes, m as stackPlan, o as stackOverrideFile, p as stackDir, r as ComposePinNeedsPull, t as composeTarget, u as composeProject, v as pinnedRef, w as projectNetwork, y as composeServer } from "./compose-qLTNYJAY.mjs";
7
7
  import { A as InvalidStages, F as stageProblems, P as deployedProblems, R as stageSampleRate, a as allConstructGlobs, d as getAppGkmConfig, j as TEST_STAGE, u as getAppBuildOrder } from "./workspace-D1QbNd55.mjs";
8
- import { b as runTime, d as BACKUPS_URL_KEY, f as RUNNER_PATH, g as backupDatabases, u as BACKUPS_SERVICE, v as backupFile, x as stageBackups, y as backupsPrefix } from "./dns-CsApfzLc.mjs";
9
- import { $t as isUnder, An as appTelemetry, At as isPortAvailable, Bn as fakeKey, Bt as maskPassword, Ct as cacheBackendFor, Dn as TELEMETRY_CONTAINER, Dt as createCredentialsPreload, G as CronGenerator, Gn as LOCAL_LOGS_EMAIL, H as workerBundleName, Hn as portsOf, Ht as toEmbeddableSecrets, It as secretsStoreFor, L as dockerCommand, Mn as scopeTelemetryEnv, Mt as loadPortState, Nn as surfaceClientTraced, Nt as loadSecretsForApp, Ot as createEntryWrapper, Pn as telemetryOf, Pt as prepareEntryCredentials, Q as assertDevServicesFlag, Tt as providerOf, U as workerEntryDir, Ut as withCustomSecret, V as WorkerGenerator, W as QueueGenerator, Wn as primaryPortKey, Xt as imageBuildCredentials, Zt as isImageBuild, a as dnsResources, an as postgresDatabaseNames, bt as pgClient, c as describeActor, dt as constructGlobs, en as workerUnits, fn as readLocalCredentials, ft as derivedContainers, gn as projectKey, gt as forgetState, ht as LOCAL_CA_PATH, jt as loadEnvFiles, kt as findAvailablePort, lt as FAKE_ENV, mn as getKeyPath, pn as FileSecretsStore, pt as reconcileWorkspace, sn as quoteIdentifier, ut as backendsOf$1, wt as eventsBackendFor, xt as CLUSTER_DATABASE, zn as describeServices } from "./seeds-CRkKeyW0.mjs";
8
+ import { b as runTime, d as BACKUPS_URL_KEY, f as RUNNER_PATH, g as backupDatabases, u as BACKUPS_SERVICE, v as backupFile, x as stageBackups, y as backupsPrefix } from "./dns-DGq4xkJT.mjs";
9
+ import { o as email } from "./schemas-BCwKKA42.mjs";
10
+ import { $t as isUnder, An as appTelemetry, At as isPortAvailable, Bn as fakeKey, Bt as maskPassword, Ct as cacheBackendFor, Dn as TELEMETRY_CONTAINER, Dt as createCredentialsPreload, G as CronGenerator, Gn as LOCAL_LOGS_EMAIL, H as workerBundleName, Hn as portsOf, Ht as toEmbeddableSecrets, It as secretsStoreFor, L as dockerCommand, Mn as scopeTelemetryEnv, Mt as loadPortState, Nn as surfaceClientTraced, Nt as loadSecretsForApp, Ot as createEntryWrapper, Pn as telemetryOf, Pt as prepareEntryCredentials, Q as assertDevServicesFlag, Tt as providerOf, U as workerEntryDir, Ut as withCustomSecret, V as WorkerGenerator, W as QueueGenerator, Wn as primaryPortKey, Xt as imageBuildCredentials, Zt as isImageBuild, a as dnsResources, an as postgresDatabaseNames, bt as pgClient, c as describeActor, dt as constructGlobs, en as workerUnits, fn as readLocalCredentials, ft as derivedContainers, gn as projectKey, gt as forgetState, ht as LOCAL_CA_PATH, jt as loadEnvFiles, kt as findAvailablePort, lt as FAKE_ENV, mn as getKeyPath, pn as FileSecretsStore, pt as reconcileWorkspace, sn as quoteIdentifier, ut as backendsOf$1, wt as eventsBackendFor, xt as CLUSTER_DATABASE, zn as describeServices } from "./seeds-CYzoBDg2.mjs";
10
11
  import { t as appKey } from "./derive-B4vDpzgP.mjs";
11
12
  import { l as isCacheBackend, n as assertTestCredentials, t as SubscriberGenerator } from "./SubscriberGenerator-DHnIYwUU.mjs";
12
13
  import { n as deployIdentity } from "./identity-CBXr4wNi.mjs";
13
14
  import { a as startTelemetryCode, c as parseTelemetryFlag, i as routeTelemetry, n as runtimeFor, o as telemetryFor, r as mountRequestSpansCode, s as writeTelemetryModule, t as EndpointGenerator } from "./EndpointGenerator-CvLX8bpx.mjs";
14
15
  import { d as ConstructGenerator, i as discover, r as consumedBy, u as withOwningTsconfigJsx } from "./discover-Ca8U75dl.mjs";
15
16
  import { ConfigNotFound, NotABackendApp, NotInAnApp, loadAppConfig, loadConfig, loadWorkspaceConfig, loadWorkspaceSettings, parseModuleConfig } from "./config.mjs";
16
- import { d as awsEndpoint, f as awsProvisioningCredentials, t as deploy$1, u as awsClientConfig } from "./deploy-Cyx5fSb7.mjs";
17
+ import { d as awsEndpoint, f as awsProvisioningCredentials, t as deploy$1, u as awsClientConfig } from "./deploy-_g-2dX38.mjs";
17
18
  import { generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi.mjs";
18
19
  import { a as describeHolder, c as withAppPorts, i as assignAppPorts, o as describeMove, r as appTag, s as holderOf, t as APP_TAG_ENV } from "./appPorts-BoXMwolc.mjs";
19
- import { n as driversFor, r as eventsBackendsIn, t as cacheBackendsIn } from "./drivers-D11JHxrD.mjs";
20
+ import { a as opensKmsKeys, n as driversFor, r as eventsBackendsIn, t as cacheBackendsIn } from "./drivers-3klmg9Sk.mjs";
20
21
  import { n as withCompute, r as withRoutes, t as manifestModule } from "./emit-C1e8qD08.mjs";
21
22
  import { t as LocalSandbox } from "./local-BwC2v2Y8.mjs";
22
- import { S as createStateStore, k as keyFingerprint, n as sniffAppEnvironment, o as DokployApi } from "./sniffer-CakkKKqQ.mjs";
23
+ import { S as createStateStore, k as keyFingerprint, n as sniffAppEnvironment, o as DokployApi } from "./sniffer-CRJHtBaK.mjs";
23
24
  import { o as loadCredentialSchemas, t as CredentialsInvalid } from "./credentialSchemas-Cf5Pf8VE.mjs";
24
- import { t as LocalStateStore } from "./LocalStateStore-C1rUUvBr.mjs";
25
+ import { t as LocalStateStore } from "./LocalStateStore-DIAY7j1O.mjs";
25
26
  import { a as getExecCommand, c as validateProjectName, i as findWorkspaceRoot, n as detectPackageManager$1, o as getInstallCommand, r as findWorkspacePackages, s as getRunCommand, t as checkDirectoryExists } from "./utils-D_fxUqvU.mjs";
26
- import { a as writeTestHarness, i as TEST_MANIFEST_ENV, n as TEST_READY_FILE, t as TEST_READY_ENV } from "./ready-CIt5SOtg.mjs";
27
+ import { a as writeTestHarness, i as TEST_MANIFEST_ENV, n as TEST_READY_FILE, t as TEST_READY_ENV } from "./ready-4hEoQ_cr.mjs";
27
28
  import { createRequire } from "node:module";
28
29
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
29
30
  import { Command, Option } from "commander";
@@ -51,7 +52,7 @@ import crypto from "crypto";
51
52
  import { Function } from "@geekmidas/constructs/functions";
52
53
  import { Topic } from "@geekmidas/constructs/topic";
53
54
  //#region package.json
54
- var version = "10.0.0-alpha.116";
55
+ var version = "10.0.0-alpha.118";
55
56
  //#endregion
56
57
  //#region src/prompt.ts
57
58
  /**
@@ -134,7 +135,7 @@ const logger$8 = console;
134
135
  * Validate Dokploy token by making a test API call
135
136
  */
136
137
  async function validateDokployToken(endpoint, token) {
137
- const { DokployApi } = await import("./sniffer-CakkKKqQ.mjs").then((n) => n.c);
138
+ const { DokployApi } = await import("./sniffer-CRJHtBaK.mjs").then((n) => n.c);
138
139
  return new DokployApi({
139
140
  baseUrl: endpoint,
140
141
  token
@@ -2174,7 +2175,7 @@ async function execCommand(commandArgs, options = {}, stageDeps) {
2174
2175
  const cwd = options.cwd ?? process.cwd();
2175
2176
  if (!commandArgs[0]) throw new NoCommandSpecified();
2176
2177
  if (options.stage && !isImageBuild()) {
2177
- const { execOnStage } = await import("./stage-Mp6qQIoD.mjs").then((n) => n.n);
2178
+ const { execOnStage } = await import("./stage-CIo8s2WT.mjs").then((n) => n.n);
2178
2179
  const { loadWorkspaceConfig } = await import("./config.mjs");
2179
2180
  const { workspace } = await loadWorkspaceConfig(cwd);
2180
2181
  if (options.stage !== workspace.stages.local) {
@@ -2747,9 +2748,9 @@ async function workspaceDevCommand(configured, options) {
2747
2748
  for (const { id, port } of fakes) logger$5.log(`🎭 ${id} fake: http://localhost:${port}`);
2748
2749
  logger$5.log(options.migrate || options.seed ? "🗄️ Migrating the databases" : "🗄️ Checking for pending migrations");
2749
2750
  if (options.migrate || options.seed) {
2750
- const { prepareDevDatabases } = await import("./migrate-X0Y7fz3N.mjs");
2751
+ const { prepareDevDatabases } = await import("./migrate-WyWhSivN.mjs");
2751
2752
  await prepareDevDatabases(workspace, reconciled.env, { seed: !!options.seed });
2752
- } else await import("./migrate-X0Y7fz3N.mjs").then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
2753
+ } else await import("./migrate-WyWhSivN.mjs").then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
2753
2754
  logger$5.log(`⚠️ Could not check for pending migrations: ${error instanceof Error ? error.message : String(error)}`);
2754
2755
  });
2755
2756
  const appUrls = {};
@@ -3825,7 +3826,7 @@ async function buildApp(input) {
3825
3826
  ...production,
3826
3827
  ...telemetry ? { telemetry } : {}
3827
3828
  });
3828
- const { bundleServer } = await import("./bundler-CgcwaVI0.mjs");
3829
+ const { bundleServer } = await import("./bundler-Ciim6amq.mjs");
3829
3830
  await bundleServer({
3830
3831
  entryPoint,
3831
3832
  outputDir: join(outputDir, "dist"),
@@ -3900,7 +3901,8 @@ async function buildApp(input) {
3900
3901
  appRoot,
3901
3902
  reach,
3902
3903
  cacheBackend,
3903
- eventsBackend
3904
+ eventsBackend,
3905
+ target
3904
3906
  }));
3905
3907
  if (target === "server") buildContext.telemetry = telemetryFor({
3906
3908
  node: processTelemetry(declared, derived.surface?.id, servesOnly ? [] : hosted.map((unit) => unit.id)),
@@ -3933,7 +3935,8 @@ async function buildApp(input) {
3933
3935
  appRoot,
3934
3936
  reach: reachedBy(declared, [workerId], work),
3935
3937
  cacheBackend,
3936
- eventsBackend
3938
+ eventsBackend,
3939
+ target
3937
3940
  })
3938
3941
  }),
3939
3942
  telemetry: (workerId) => telemetryFor({
@@ -3983,7 +3986,8 @@ function processTelemetry(declared, surfaceId, workers) {
3983
3986
  * The drivers a process's entry registers, from the declarations it reaches:
3984
3987
  * the cache's — the declaration for one that named its database, the deploy
3985
3988
  * target's default for one that named nowhere — and the broker's, only when
3986
- * it reaches a topic or a queue (see `eventsBackendsIn`).
3989
+ * it reaches a topic or a queue (see `eventsBackendsIn`) — and the KMS
3990
+ * cipher, only built for AWS and only when it reaches an `Encryption`.
3987
3991
  */
3988
3992
  function runtimeDrivers(options) {
3989
3993
  const eventsBackends = eventsBackendsIn(options.reach, options.eventsBackend);
@@ -3991,7 +3995,8 @@ function runtimeDrivers(options) {
3991
3995
  storageDrivers: driversFor({
3992
3996
  appRoot: options.appRoot,
3993
3997
  cache: cacheBackendsIn(options.reach, options.cacheBackend),
3994
- events: eventsBackends
3998
+ events: eventsBackends,
3999
+ kms: opensKmsKeys(options.reach, options.target)
3995
4000
  }),
3996
4001
  eventsBackends
3997
4002
  };
@@ -4024,7 +4029,7 @@ async function buildWorkers(input) {
4024
4029
  });
4025
4030
  logger$4.log(`Generated worker ${worker.id}: ${crons.length} crons, ${queues.length} queues, ${subscribers.length} subscribers`);
4026
4031
  if (!input.bundle) continue;
4027
- const { bundleServer } = await import("./bundler-CgcwaVI0.mjs");
4032
+ const { bundleServer } = await import("./bundler-Ciim6amq.mjs");
4028
4033
  const outfile = workerBundleName(worker.id);
4029
4034
  await bundleServer({
4030
4035
  entryPoint,
@@ -4110,7 +4115,7 @@ async function buildForTarget(target, context, appRoot, workspaceRoot, endpointG
4110
4115
  let masterKey;
4111
4116
  if (context.production?.bundle && !skipBundle) {
4112
4117
  logger$4.log(`\n📦 Bundling production server...`);
4113
- const { bundleServer } = await import("./bundler-CgcwaVI0.mjs");
4118
+ const { bundleServer } = await import("./bundler-Ciim6amq.mjs");
4114
4119
  const allConstructs = [
4115
4120
  ...endpoints.map((e) => e.construct),
4116
4121
  ...functions.map((f) => f.construct),
@@ -5944,25 +5949,25 @@ function loadPackageJson() {
5944
5949
  * Run: pnpm --filter @geekmidas/cli sync-versions
5945
5950
  */
5946
5951
  const GEEKMIDAS_VERSIONS = {
5947
- "@geekmidas/audit": "~10.0.0-alpha.116",
5948
- "@geekmidas/auth": "~10.0.0-alpha.116",
5949
- "@geekmidas/cache": "~10.0.0-alpha.116",
5950
- "@geekmidas/client": "~10.0.0-alpha.116",
5951
- "@geekmidas/cloud": "~10.0.0-alpha.116",
5952
- "@geekmidas/constructs": "~10.0.0-alpha.116",
5953
- "@geekmidas/db": "~10.0.0-alpha.116",
5954
- "@geekmidas/emailkit": "~10.0.0-alpha.116",
5955
- "@geekmidas/envkit": "~10.0.0-alpha.116",
5956
- "@geekmidas/errors": "~10.0.0-alpha.116",
5957
- "@geekmidas/events": "~10.0.0-alpha.116",
5958
- "@geekmidas/logger": "~10.0.0-alpha.116",
5959
- "@geekmidas/manifest": "~10.0.0-alpha.116",
5960
- "@geekmidas/rate-limit": "~10.0.0-alpha.116",
5961
- "@geekmidas/schema": "~10.0.0-alpha.116",
5962
- "@geekmidas/services": "~10.0.0-alpha.116",
5963
- "@geekmidas/storage": "~10.0.0-alpha.116",
5964
- "@geekmidas/telescope": "~10.0.0-alpha.116",
5965
- "@geekmidas/testkit": "~10.0.0-alpha.116",
5952
+ "@geekmidas/audit": "~10.0.0-alpha.118",
5953
+ "@geekmidas/auth": "~10.0.0-alpha.118",
5954
+ "@geekmidas/cache": "~10.0.0-alpha.118",
5955
+ "@geekmidas/client": "~10.0.0-alpha.118",
5956
+ "@geekmidas/cloud": "~10.0.0-alpha.118",
5957
+ "@geekmidas/constructs": "~10.0.0-alpha.118",
5958
+ "@geekmidas/db": "~10.0.0-alpha.118",
5959
+ "@geekmidas/emailkit": "~10.0.0-alpha.118",
5960
+ "@geekmidas/envkit": "~10.0.0-alpha.118",
5961
+ "@geekmidas/errors": "~10.0.0-alpha.118",
5962
+ "@geekmidas/events": "~10.0.0-alpha.118",
5963
+ "@geekmidas/logger": "~10.0.0-alpha.118",
5964
+ "@geekmidas/manifest": "~10.0.0-alpha.118",
5965
+ "@geekmidas/rate-limit": "~10.0.0-alpha.118",
5966
+ "@geekmidas/schema": "~10.0.0-alpha.118",
5967
+ "@geekmidas/services": "~10.0.0-alpha.118",
5968
+ "@geekmidas/storage": "~10.0.0-alpha.118",
5969
+ "@geekmidas/telescope": "~10.0.0-alpha.118",
5970
+ "@geekmidas/testkit": "~10.0.0-alpha.118",
5966
5971
  "@geekmidas/cli": `~${loadPackageJson().version}`
5967
5972
  };
5968
5973
  //#endregion
@@ -7155,7 +7160,7 @@ const COMMIT = /^[0-9a-f]{40}$/;
7155
7160
  * The `uses:` value for the stages action, with a comment saying which CLI
7156
7161
  * release the pinned commit is.
7157
7162
  */
7158
- function stagesActionUses(commit = "8441f7be92366877d6802babf8ee655bcdde2489", version = cliVersion()) {
7163
+ function stagesActionUses(commit = "01a325bb2dfb75faf9c255cb3f1d9288c6c42c1e", version = cliVersion()) {
7159
7164
  return commit && COMMIT.test(commit) ? `${STAGES_ACTION}@${commit} # @geekmidas/cli ${version}` : `${STAGES_ACTION}@main # pin to a commit SHA: see the action's README`;
7160
7165
  }
7161
7166
  //#endregion
@@ -9066,6 +9071,10 @@ interface SignedIn {
9066
9071
  * The \`users\` row for whoever signed in, made the first time they call the
9067
9072
  * API and given the Member role. The auth server owns who someone is; this
9068
9073
  * row is what the application's own tables refer to.
9074
+ *
9075
+ * Someone the seeds named before they signed in — an admin, in
9076
+ * \`03_admins.ts\` — already has a row with their email and no auth user: their
9077
+ * first sign-in claims it, roles and all.
9069
9078
  */
9070
9079
  export async function memberFor(db: Kysely<Database>, user: SignedIn) {
9071
9080
  const found = await db
@@ -9075,13 +9084,23 @@ export async function memberFor(db: Kysely<Database>, user: SignedIn) {
9075
9084
  .executeTakeFirst();
9076
9085
  if (found) return found;
9077
9086
 
9078
- const member = await db
9079
- .insertInto('users')
9080
- .values({ authUserId: user.id, email: user.email, name: user.name })
9081
- // Two first requests at once: the second finds the first's row.
9082
- .onConflict((oc) => oc.column('authUserId').doUpdateSet({ email: user.email }))
9083
- .returningAll()
9084
- .executeTakeFirstOrThrow();
9087
+ const member =
9088
+ (await db
9089
+ .updateTable('users')
9090
+ .set({ authUserId: user.id, ...(user.name ? { name: user.name } : {}) })
9091
+ .where('email', '=', user.email)
9092
+ .where('authUserId', 'is', null)
9093
+ .returningAll()
9094
+ .executeTakeFirst()) ??
9095
+ (await db
9096
+ .insertInto('users')
9097
+ .values({ authUserId: user.id, email: user.email, name: user.name })
9098
+ // Two first requests at once: the second finds the first's row.
9099
+ .onConflict((oc) =>
9100
+ oc.column('authUserId').doUpdateSet({ email: user.email }),
9101
+ )
9102
+ .returningAll()
9103
+ .executeTakeFirstOrThrow());
9085
9104
 
9086
9105
  const memberRole = await db
9087
9106
  .selectFrom('roles')
@@ -9244,65 +9263,6 @@ export const AdminUsersSchema = z
9244
9263
  }];
9245
9264
  }
9246
9265
  /**
9247
- * `scripts/grant-admin.ts`: the first Super admin. Nobody can grant a role
9248
- * before someone has one, so the first is granted from a terminal.
9249
- */
9250
- function grantAdminScript(options) {
9251
- return {
9252
- path: "scripts/grant-admin.ts",
9253
- content: `/**
9254
- * Make someone a Super admin — the first one, before the admin panel can.
9255
- *
9256
- * gkm exec -- tsx scripts/grant-admin.ts you@example.com
9257
- *
9258
- * They need to have signed in once (the web site, the admin panel or the app),
9259
- * which is what makes their \`users\` row.
9260
- */
9261
- import { database } from '@${options.name}/constructs/database.ts';
9262
- import { SYSTEM_ROLES } from '@${options.name}/models/access';
9263
- import { EnvironmentParser } from '@geekmidas/envkit';
9264
-
9265
- const email = process.argv[2]?.trim().toLowerCase();
9266
- if (!email) {
9267
- console.error('Usage: gkm exec -- tsx scripts/grant-admin.ts <email>');
9268
- process.exit(1);
9269
- }
9270
-
9271
- const db = await database.service.register({
9272
- envParser: new EnvironmentParser({ ...process.env }),
9273
- } as never);
9274
-
9275
- try {
9276
- const user = await db
9277
- .selectFrom('users')
9278
- .select('id')
9279
- .where('email', '=', email)
9280
- .executeTakeFirst();
9281
- if (!user) {
9282
- console.error(\`No one has signed in as \${email} yet. Sign in once, then run this again.\`);
9283
- process.exit(1);
9284
- }
9285
-
9286
- const role = await db
9287
- .selectFrom('roles')
9288
- .select('id')
9289
- .where('name', '=', SYSTEM_ROLES.SuperAdmin.name)
9290
- .executeTakeFirstOrThrow();
9291
-
9292
- await db
9293
- .insertInto('userRoles')
9294
- .values({ userId: user.id, roleId: role.id })
9295
- .onConflict((oc) => oc.columns(['userId', 'roleId']).doNothing())
9296
- .execute();
9297
-
9298
- console.log(\`\${email} is a \${SYSTEM_ROLES.SuperAdmin.name}.\`);
9299
- } finally {
9300
- await db.destroy();
9301
- }
9302
- `
9303
- };
9304
- }
9305
- /**
9306
9266
  * The API's feature tests: signing in by email end to end, and the admin
9307
9267
  * panel's gate. Each runs in a transaction, against the real auth server and
9308
9268
  * the real mail catcher.
@@ -9365,6 +9325,39 @@ describe('the admin panel', () => {
9365
9325
 
9366
9326
  expect(users).toContainEqual(expect.objectContaining({ id: me.id }));
9367
9327
  });
9328
+
9329
+ it('lets in an admin the seeds named, on their first sign-in', async ({
9330
+ browser,
9331
+ db,
9332
+ faker,
9333
+ }) => {
9334
+ // What \`03_admins.ts\` writes: a row with no auth user yet, and the role.
9335
+ const email = faker.internet.email();
9336
+ const app = await db.get('database');
9337
+ const admin = await app
9338
+ .insertInto('users')
9339
+ .values({ email, name: 'Admin' })
9340
+ .returning('id')
9341
+ .executeTakeFirstOrThrow();
9342
+ const superAdmin = await app
9343
+ .selectFrom('roles')
9344
+ .select('id')
9345
+ .where('name', '=', SYSTEM_ROLES.SuperAdmin.name)
9346
+ .executeTakeFirstOrThrow();
9347
+ await app
9348
+ .insertInto('userRoles')
9349
+ .values({ userId: admin.id, roleId: superAdmin.id })
9350
+ .execute();
9351
+
9352
+ await browser.signIn(email);
9353
+
9354
+ expect(await browser.api.get('/profiles/me')).toMatchObject({
9355
+ id: admin.id,
9356
+ email,
9357
+ });
9358
+ const { users } = await browser.api.get('/admin/users');
9359
+ expect(users).toContainEqual(expect.objectContaining({ id: admin.id }));
9360
+ });
9368
9361
  });
9369
9362
  `;
9370
9363
  }
@@ -9663,9 +9656,11 @@ export interface Database {
9663
9656
  id: Generated<string>;
9664
9657
  /**
9665
9658
  * The Better Auth user this person signs in as. The auth schema is its
9666
- * own, so this is a plain column, not a foreign key into it.
9659
+ * own, so this is a plain column, not a foreign key into it. Null for
9660
+ * someone the seeds named who has not signed in yet: their first sign-in
9661
+ * claims the row by email.
9667
9662
  */
9668
- authUserId: string;
9663
+ authUserId: string | null;
9669
9664
  name: string;
9670
9665
  email: string;
9671
9666
  createdAt: Generated<Date>;
@@ -9952,8 +9947,9 @@ export async function up(db: Kysely<unknown>): Promise<void> {
9952
9947
  col.primaryKey().defaultTo(db.fn('gen_random_uuid')),
9953
9948
  )
9954
9949
  // The Better Auth user this person signs in as. A plain column: the auth
9955
- // schema is its own, and the id's format is Better Auth's to choose.
9956
- .addColumn('auth_user_id', 'text', (col) => col.notNull().unique())
9950
+ // schema is its own, and the id's format is Better Auth's to choose. Null
9951
+ // until someone the seeds named (an admin) first signs in.
9952
+ .addColumn('auth_user_id', 'text', (col) => col.unique())
9957
9953
  .addColumn('name', 'varchar(255)', (col) => col.notNull())
9958
9954
  .addColumn('email', 'varchar(255)', (col) => col.notNull().unique())
9959
9955
  .addColumn('created_at', 'timestamptz', (col) =>
@@ -10058,11 +10054,13 @@ export async function down(db: Kysely<unknown>): Promise<void> {
10058
10054
  * upserts, run after every migration, so a changed list is applied by running
10059
10055
  * them again.
10060
10056
  */
10061
- function accessControlSeeds(name) {
10057
+ function accessControlSeeds(options) {
10058
+ const { name } = options;
10062
10059
  const folder = seedFolder(databaseFor().id);
10063
- return [{
10064
- path: `${folder}/01_permissions.ts`,
10065
- content: `import { PERMISSION_KEYS, PERMISSIONS } from '@${name}/models/access';
10060
+ return [
10061
+ {
10062
+ path: `${folder}/01_permissions.ts`,
10063
+ content: `import { PERMISSION_KEYS, PERMISSIONS } from '@${name}/models/access';
10066
10064
  import type { Kysely } from 'kysely';
10067
10065
 
10068
10066
  type Tables = { permissions: { key: string; description: string } };
@@ -10093,9 +10091,10 @@ export async function seed(db: Kysely<unknown>): Promise<void> {
10093
10091
  .execute();
10094
10092
  }
10095
10093
  `
10096
- }, {
10097
- path: `${folder}/02_system_roles.ts`,
10098
- content: `import { SYSTEM_ROLES } from '@${name}/models/access';
10094
+ },
10095
+ {
10096
+ path: `${folder}/02_system_roles.ts`,
10097
+ content: `import { SYSTEM_ROLES } from '@${name}/models/access';
10099
10098
  import type { Kysely } from 'kysely';
10100
10099
 
10101
10100
  type Tables = {
@@ -10142,7 +10141,76 @@ export async function seed(db: Kysely<unknown>): Promise<void> {
10142
10141
  }
10143
10142
  }
10144
10143
  `
10145
- }];
10144
+ },
10145
+ adminsSeed(folder, options)
10146
+ ];
10147
+ }
10148
+ /**
10149
+ * The Super admins, by email — the first one asked for by `gkm init`. Each
10150
+ * gets a `users` row before they have signed in, which their first sign-in
10151
+ * claims (`memberFor`), so the admin panel lets them in straight away.
10152
+ */
10153
+ function adminsSeed(folder, options) {
10154
+ const admins = options.adminEmail ? `[\n '${options.adminEmail}',\n]` : "[\n // 'you@example.com',\n]";
10155
+ return {
10156
+ path: `${folder}/03_admins.ts`,
10157
+ content: `import { SYSTEM_ROLES } from '@${options.name}/models/access';
10158
+ import type { Kysely } from 'kysely';
10159
+
10160
+ /**
10161
+ * Who is a Super admin, by the address they sign in with. Add someone here and
10162
+ * run the seeds (\`gkm dev --seed\`, or the next deploy); taking them off the
10163
+ * list does not take the role away — the admin panel does that.
10164
+ */
10165
+ const ADMINS: string[] = ${admins};
10166
+
10167
+ type Tables = {
10168
+ users: { id?: string; email: string; name: string };
10169
+ roles: { id: string; name: string; is_system: boolean };
10170
+ user_roles: { user_id: string; role_id: string };
10171
+ };
10172
+
10173
+ /**
10174
+ * A \`users\` row for each admin who has none — their first sign-in claims it —
10175
+ * and the Member and Super admin roles. Runs after the system roles seed.
10176
+ */
10177
+ export async function seed(db: Kysely<unknown>): Promise<void> {
10178
+ // Better Auth stores addresses lowercased; so does every \`users\` row.
10179
+ const emails = ADMINS.map((email) => email.trim().toLowerCase());
10180
+ if (emails.length === 0) return;
10181
+
10182
+ const tables = db.withTables<Tables>();
10183
+
10184
+ await tables
10185
+ .insertInto('users')
10186
+ .values(emails.map((email) => ({ email, name: email.split('@')[0]! })))
10187
+ .onConflict((oc) => oc.column('email').doNothing())
10188
+ .execute();
10189
+
10190
+ const users = await tables
10191
+ .selectFrom('users')
10192
+ .select('id')
10193
+ .where('email', 'in', emails)
10194
+ .execute();
10195
+ const roles = await tables
10196
+ .selectFrom('roles')
10197
+ .select('id')
10198
+ .where('is_system', '=', true)
10199
+ .where('name', 'in', [SYSTEM_ROLES.Member.name, SYSTEM_ROLES.SuperAdmin.name])
10200
+ .execute();
10201
+
10202
+ await tables
10203
+ .insertInto('user_roles')
10204
+ .values(
10205
+ users.flatMap((user) =>
10206
+ roles.map((role) => ({ user_id: user.id!, role_id: role.id })),
10207
+ ),
10208
+ )
10209
+ .onConflict((oc) => oc.columns(['user_id', 'role_id']).doNothing())
10210
+ .execute();
10211
+ }
10212
+ `
10213
+ };
10146
10214
  }
10147
10215
  //#endregion
10148
10216
  //#region src/init/generators/monorepo.ts
@@ -10659,8 +10727,7 @@ export const logger = createLogger();
10659
10727
  },
10660
10728
  workspaceUsersMigration(),
10661
10729
  accessControlMigration(),
10662
- ...accessControlSeeds(options.name),
10663
- grantAdminScript(options)
10730
+ ...accessControlSeeds(options)
10664
10731
  ];
10665
10732
  if (uploads) {
10666
10733
  const bucket = storageFor();
@@ -14870,6 +14937,27 @@ function isFullstackTemplate(name) {
14870
14937
  //#region src/init/index.ts
14871
14938
  /** `' staging, prod '` → `['staging', 'prod']`. */
14872
14939
  const stageList = (value) => value.split(",").map((name) => name.trim()).filter(Boolean);
14940
+ /** Whether `value` is an email address, as the API's models check one. */
14941
+ const isEmail = (value) => email().safeParse(value.trim()).success;
14942
+ /**
14943
+ * Who `git` says you are, offered as the first admin: the address you most
14944
+ * likely sign in with. Nothing when git has none.
14945
+ */
14946
+ function gitEmail() {
14947
+ try {
14948
+ const email = execSync("git config user.email", {
14949
+ encoding: "utf-8",
14950
+ stdio: [
14951
+ "ignore",
14952
+ "pipe",
14953
+ "ignore"
14954
+ ]
14955
+ }).trim();
14956
+ return isEmail(email) ? email.toLowerCase() : void 0;
14957
+ } catch {
14958
+ return;
14959
+ }
14960
+ }
14873
14961
  /** `eu-west-1`, `us-gov-west-1`, `ap-southeast-2`. */
14874
14962
  const AWS_REGION = /^[a-z]{2}(-gov)?-[a-z]+-\d$/;
14875
14963
  /**
@@ -14881,6 +14969,7 @@ async function initCommand(projectName, options = {}) {
14881
14969
  if (options.deploy && !deployTargetChoices.some((choice) => choice.value === options.deploy)) throw new UnknownDeployTarget(options.deploy, deployTargetChoices.map((c) => c.value));
14882
14970
  if (options.web && !frontendFrameworkChoices.some((choice) => choice.value === options.web)) throw new UnknownWebFramework(options.web, frontendFrameworkChoices.map((c) => c.value));
14883
14971
  if (options.region && !AWS_REGION.test(options.region)) throw new NotAnAwsRegion(options.region);
14972
+ if (options.adminEmail && !isEmail(options.adminEmail)) throw new NotAnEmail(options.adminEmail);
14884
14973
  if (options.stages || options.localStage || options.protectedStage) {
14885
14974
  const deployed = stageList(options.stages ?? "");
14886
14975
  const problems = [
@@ -15019,6 +15108,13 @@ async function initCommand(projectName, options = {}) {
15019
15108
  name: "mobileApp",
15020
15109
  message: "Include a mobile app? (Expo, with its sign-in and a site for App Store and Play Store reviewers)",
15021
15110
  initial: true
15111
+ },
15112
+ {
15113
+ type: (_prev, values) => !options.yes && !options.adminEmail && (options.template === "fullstack" || values.template === "fullstack") ? "text" : null,
15114
+ name: "adminEmail",
15115
+ message: "Admin email (the first Super admin of the admin panel):",
15116
+ initial: gitEmail() ?? "",
15117
+ validate: (value) => isEmail(value) || "An email address, like you@example.com"
15022
15118
  }
15023
15119
  ], { onCancel });
15024
15120
  const name = projectName || options.name || answers.name;
@@ -15053,6 +15149,7 @@ async function initCommand(projectName, options = {}) {
15053
15149
  const deployTarget = options.deploy ?? (options.yes ? "none" : answers.deployTarget ?? "none");
15054
15150
  const frontendFramework = isFullstack ? options.web ?? (options.yes ? "nextjs" : answers.frontendFramework ?? "nextjs") : void 0;
15055
15151
  const mobileApp = isFullstack ? options.mobileApp ?? (options.yes ? true : answers.mobileApp ?? true) : void 0;
15152
+ const adminEmail = isFullstack ? (options.adminEmail ?? (options.yes ? gitEmail() : answers.adminEmail))?.trim().toLowerCase() : void 0;
15056
15153
  const templateOptions = {
15057
15154
  name,
15058
15155
  template,
@@ -15068,7 +15165,8 @@ async function initCommand(projectName, options = {}) {
15068
15165
  ...deployTarget === "sst" ? { region: options.region ?? (options.yes ? "eu-west-1" : answers.region?.trim()) } : {},
15069
15166
  constructs,
15070
15167
  frontendFramework,
15071
- ...mobileApp !== void 0 ? { mobileApp } : {}
15168
+ ...mobileApp !== void 0 ? { mobileApp } : {},
15169
+ ...adminEmail ? { adminEmail } : {}
15072
15170
  };
15073
15171
  const targetDir = join(cwd, name);
15074
15172
  const baseTemplate = getTemplate(templateOptions.template);
@@ -15307,6 +15405,14 @@ function defaultRegistry(name) {
15307
15405
  return `ghcr.io/${(name ?? "my-org").toLowerCase()}`;
15308
15406
  }
15309
15407
  /** `--region` that is not shaped like one, e.g. `europe` for `eu-west-1`. */
15408
+ var NotAnEmail = class extends GkmError {
15409
+ value;
15410
+ constructor(value) {
15411
+ super(`"${value}" is not an email address. Give --admin-email the address the first admin signs in with.`);
15412
+ this.value = value;
15413
+ this.name = "NotAnEmail";
15414
+ }
15415
+ };
15310
15416
  var NotAnAwsRegion = class extends GkmError {
15311
15417
  region;
15312
15418
  constructor(region) {
@@ -16026,7 +16132,7 @@ function testDatabases(reconciled) {
16026
16132
  * starts without the reference data the app needs.
16027
16133
  */
16028
16134
  async function migrateTestStage(workspace, env) {
16029
- const { migrateAndSeed } = await import("./migrate-X0Y7fz3N.mjs");
16135
+ const { migrateAndSeed } = await import("./migrate-WyWhSivN.mjs");
16030
16136
  const { discover } = await import("./discover-Ca8U75dl.mjs").then((n) => n.a);
16031
16137
  const sources = {};
16032
16138
  const manifest = await discover({
@@ -16362,7 +16468,7 @@ const program = new Command();
16362
16468
  program.name("gkm").description("GeekMidas backend framework CLI").version(version).option("--cwd <path>", "Change working directory").option("--debug", "Enable debug mode (verbose errors with stack traces)").hook("preAction", () => {
16363
16469
  if (program.opts().debug) enableDebug();
16364
16470
  });
16365
- program.command("init").description("Scaffold a new project").argument("[name]", "Project name").option("--template <template>", "Project template (minimal, api, fullstack, serverless, worker)").option("--skip-install", "Skip dependency installation", false).option("-y, --yes", "Skip prompts, use defaults", false).option("--monorepo", "Setup as monorepo with packages/models", false).option("--api-path <path>", "API app path in monorepo (default: apps/api)").option("--pm <manager>", "Package manager (pnpm, npm, yarn, bun)").option("--deploy <target>", "Where it deploys (dokploy, compose, sst, none)").option("--region <region>", "AWS region for an SST deploy (e.g. eu-west-1)").option("--registry <registry>", "Container registry for a compose deploy (e.g. ghcr.io/acme)").option("--stages <names>", "Deployed stages, comma-separated (e.g. staging,prod)").option("--protected-stage <name>", "Which deployed stage is production").option("--local-stage <name>", "What gkm dev runs as (e.g. dev)").option("--web <framework>", "Fullstack: what the web site and admin panel use (nextjs, tanstack-start)").option("--mobile-app", "Fullstack: include the Expo app and its store-reviewer site").option("--no-mobile-app", "Fullstack: no mobile app").action(async (name, options) => {
16471
+ program.command("init").description("Scaffold a new project").argument("[name]", "Project name").option("--template <template>", "Project template (minimal, api, fullstack, serverless, worker)").option("--skip-install", "Skip dependency installation", false).option("-y, --yes", "Skip prompts, use defaults", false).option("--monorepo", "Setup as monorepo with packages/models", false).option("--api-path <path>", "API app path in monorepo (default: apps/api)").option("--pm <manager>", "Package manager (pnpm, npm, yarn, bun)").option("--deploy <target>", "Where it deploys (dokploy, compose, sst, none)").option("--region <region>", "AWS region for an SST deploy (e.g. eu-west-1)").option("--registry <registry>", "Container registry for a compose deploy (e.g. ghcr.io/acme)").option("--stages <names>", "Deployed stages, comma-separated (e.g. staging,prod)").option("--protected-stage <name>", "Which deployed stage is production").option("--local-stage <name>", "What gkm dev runs as (e.g. dev)").option("--web <framework>", "Fullstack: what the web site and admin panel use (nextjs, tanstack-start)").option("--mobile-app", "Fullstack: include the Expo app and its store-reviewer site").option("--no-mobile-app", "Fullstack: no mobile app").option("--admin-email <email>", "Fullstack: who the seeds make the first Super admin").action(async (name, options) => {
16366
16472
  try {
16367
16473
  const globalOptions = program.opts();
16368
16474
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
@@ -16450,7 +16556,7 @@ program.command("eas:sync").description("Set up a mobile app's EAS project for a
16450
16556
  try {
16451
16557
  const globalOptions = program.opts();
16452
16558
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16453
- const { easSync } = await import("./eas-CTfRmndW.mjs");
16559
+ const { easSync } = await import("./eas-DJXhARYb.mjs");
16454
16560
  await easSync(options);
16455
16561
  } catch (error) {
16456
16562
  exitWithError(error);
@@ -16460,7 +16566,7 @@ program.command("publish").description("Ship a mobile app for a deployed stage:
16460
16566
  try {
16461
16567
  const globalOptions = program.opts();
16462
16568
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16463
- const { publish, PublishModeConflict } = await import("./publish-hhgraEhO.mjs");
16569
+ const { publish, PublishModeConflict } = await import("./publish-BBG4zx8E.mjs");
16464
16570
  if (options.build && options.update) throw new PublishModeConflict();
16465
16571
  const { build, update, ...rest } = options;
16466
16572
  await publish({
@@ -16476,7 +16582,7 @@ program.command("deploy:google-play").description("Let EAS Submit publish a mobi
16476
16582
  try {
16477
16583
  const globalOptions = program.opts();
16478
16584
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16479
- const { deployGooglePlay } = await import("./googlePlay-m1De-qIJ.mjs");
16585
+ const { deployGooglePlay } = await import("./googlePlay-fw0VWly7.mjs");
16480
16586
  await deployGooglePlay(options);
16481
16587
  } catch (error) {
16482
16588
  exitWithError(error);
@@ -16498,7 +16604,7 @@ program.command("migrate").description("Apply each database construct's migratio
16498
16604
  try {
16499
16605
  const globalOptions = program.opts();
16500
16606
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16501
- const { migrateCommand } = await import("./migrate-X0Y7fz3N.mjs");
16607
+ const { migrateCommand } = await import("./migrate-WyWhSivN.mjs");
16502
16608
  await migrateCommand({
16503
16609
  ...options,
16504
16610
  ...construct ? { construct } : {}
@@ -16511,7 +16617,7 @@ program.command("seed").description("Migrate, then run each database construct's
16511
16617
  try {
16512
16618
  const globalOptions = program.opts();
16513
16619
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16514
- const { seedCommand } = await import("./migrate-X0Y7fz3N.mjs");
16620
+ const { seedCommand } = await import("./migrate-WyWhSivN.mjs");
16515
16621
  await seedCommand({
16516
16622
  ...options,
16517
16623
  ...construct ? { construct } : {}
@@ -16524,7 +16630,7 @@ program.command("migration").description("Write a construct's next migration: an
16524
16630
  try {
16525
16631
  const globalOptions = program.opts();
16526
16632
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16527
- const { migrationCommand } = await import("./migrate-X0Y7fz3N.mjs");
16633
+ const { migrationCommand } = await import("./migrate-WyWhSivN.mjs");
16528
16634
  await migrationCommand({
16529
16635
  construct,
16530
16636
  ...name ? { name } : {}
@@ -16624,7 +16730,7 @@ program.command("secrets:add").description("Build the keys a stage must be given
16624
16730
  try {
16625
16731
  const globalOptions = program.opts();
16626
16732
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16627
- const { secretsAddCommand } = await import("./add-DXdJjp0b.mjs");
16733
+ const { secretsAddCommand } = await import("./add-BcZXHa3Z.mjs");
16628
16734
  await secretsAddCommand(options);
16629
16735
  } catch (error) {
16630
16736
  exitWithError(error);
@@ -16634,7 +16740,7 @@ program.command("encryption:rotate").description("Add a new current key to an En
16634
16740
  try {
16635
16741
  const globalOptions = program.opts();
16636
16742
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16637
- const { encryptionRotateCommand } = await import("./encryption-BpTPmd7h.mjs");
16743
+ const { encryptionRotateCommand } = await import("./encryption-CldvLtip.mjs");
16638
16744
  await encryptionRotateCommand(construct, options);
16639
16745
  } catch (error) {
16640
16746
  exitWithError(error);
@@ -16644,7 +16750,7 @@ program.command("encryption:retire").description("Remove an old key from an Encr
16644
16750
  try {
16645
16751
  const globalOptions = program.opts();
16646
16752
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16647
- const { encryptionRetireCommand } = await import("./encryption-BpTPmd7h.mjs");
16753
+ const { encryptionRetireCommand } = await import("./encryption-CldvLtip.mjs");
16648
16754
  await encryptionRetireCommand(construct, key, options);
16649
16755
  } catch (error) {
16650
16756
  exitWithError(error);
@@ -16683,7 +16789,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
16683
16789
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16684
16790
  const { loadWorkspaceConfig } = await import("./config.mjs");
16685
16791
  const { reconcileMissingSecrets } = await import("./reconcile--I7V4Klj.mjs");
16686
- const { secretsStoreFor } = await import("./seeds-CRkKeyW0.mjs").then((n) => n.Rt);
16792
+ const { secretsStoreFor } = await import("./seeds-CYzoBDg2.mjs").then((n) => n.Rt);
16687
16793
  const { workspace } = await loadWorkspaceConfig();
16688
16794
  const stage = options.stage ?? workspace.stages.local;
16689
16795
  const store = await secretsStoreFor(workspace, stage);
@@ -16692,7 +16798,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
16692
16798
  console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
16693
16799
  process.exit(1);
16694
16800
  }
16695
- const { derivedContainers } = await import("./seeds-CRkKeyW0.mjs").then((n) => n.mt);
16801
+ const { derivedContainers } = await import("./seeds-CYzoBDg2.mjs").then((n) => n.mt);
16696
16802
  const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, stage));
16697
16803
  if (!result) {
16698
16804
  console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
@@ -16709,14 +16815,14 @@ program.command("secrets:migrate").description("Copy a deployed stage's secrets
16709
16815
  try {
16710
16816
  const globalOptions = program.opts();
16711
16817
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16712
- const { secretsMigrateCommand } = await import("./migrate-4B4RgAjU.mjs");
16818
+ const { secretsMigrateCommand } = await import("./migrate-1bHqjfIe.mjs");
16713
16819
  await secretsMigrateCommand(options);
16714
16820
  } catch (error) {
16715
16821
  exitWithError(error);
16716
16822
  }
16717
16823
  });
16718
16824
  program.command("deploy").description("Deploy a stage through its target").option("--target <name>", "Deploy target: dokploy, compose, sst, or one named in deploy.targets (default: deploy.default)").option("--provider <provider>", "[DEPRECATED] Use --target instead").requiredOption("--stage <stage>", "Deployment stage (e.g., production, staging)").option("--tag <tag>", "Image tag (default: stage-timestamp; compose: the commit). Compose pulls a given tag").option("--skip-push", "Skip pushing image to registry").option("--skip-build", "Skip build step (use existing build)").option("--json", "Write events as JSON lines instead of progress; never prompts").option("--dry-run", "Show what would be created or reused; change, build and push nothing").option("--atomic", "If the release fails, roll back every app it released, not only the failed ones").option("--allow-dev-services", "Server targets: run the dev service (MinIO, Mailpit) for every bucket and mail the stage doesn't account for. Not production-grade").option("--skip-dns", "Compose: neither write the public hosts' DNS records nor check they point at GKM_SERVER_IPV4 (a CDN or proxy in front, or records written elsewhere)").option("--rotate-keys", "Deployed stage: each provider issues its runtime keys a successor (the old one is deleted by the next deploy)").option("--retire-old-keys", "Deployed stage: delete a rotated-out key now instead of on the next deploy").action(async (options) => {
16719
- const { deployCli } = await import("./cli-H0uB_znq.mjs");
16825
+ const { deployCli } = await import("./cli-BkxlWYfI.mjs");
16720
16826
  const globalOptions = program.opts();
16721
16827
  const code = await deployCli({
16722
16828
  cwd: resolve(globalOptions.cwd ?? process.cwd()),
@@ -16736,7 +16842,7 @@ program.command("deploy").description("Deploy a stage through its target").optio
16736
16842
  });
16737
16843
  program.command("deploy:rollback").description("Put a stage's app back on its previous release (Dokploy): one app with --app, every app with --atomic").requiredOption("--stage <stage>", "A deployed stage").option("--app <app>", "The app to roll back").option("--atomic", "Roll back every app that has an earlier release").action(async (options) => {
16738
16844
  try {
16739
- const { rollbackStage } = await import("./rollback-9t9G3c_u.mjs").then((n) => n.a);
16845
+ const { rollbackStage } = await import("./rollback-DaEmEC2Y.mjs").then((n) => n.a);
16740
16846
  const { terminalCredentials } = await import("./terminal-CybB-cjk.mjs");
16741
16847
  const globalOptions = program.opts();
16742
16848
  await rollbackStage({
@@ -16755,7 +16861,7 @@ program.command("compose:server").description("Set up a stage's server for compo
16755
16861
  try {
16756
16862
  const globalOptions = program.opts();
16757
16863
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16758
- const { composeServerCommand } = await import("./serverSetup-DlRKRfTi.mjs");
16864
+ const { composeServerCommand } = await import("./serverSetup-0h1Vh5un.mjs");
16759
16865
  await composeServerCommand(options);
16760
16866
  } catch (error) {
16761
16867
  exitWithError(error);
@@ -16780,7 +16886,7 @@ program.command("deploy:github").description("Let GitHub Actions deploy a stage:
16780
16886
  try {
16781
16887
  const globalOptions = program.opts();
16782
16888
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
16783
- const { deployGithubCommand } = await import("./github-tWAGuR9i.mjs");
16889
+ const { deployGithubCommand } = await import("./github-BMPci2wg.mjs");
16784
16890
  await deployGithubCommand(options);
16785
16891
  } catch (error) {
16786
16892
  exitWithError(error);