@geekmidas/cli 10.0.0-alpha.60 → 10.0.0-alpha.62

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 (151) hide show
  1. package/dist/{HostingerProvider-DgzKa_Tj.mjs → HostingerProvider-B92qH4dC.mjs} +2 -2
  2. package/dist/{HostingerProvider-DgzKa_Tj.mjs.map → HostingerProvider-B92qH4dC.mjs.map} +1 -1
  3. package/dist/{HostingerProvider-BTZd2u0f.cjs → HostingerProvider-DyD1Hin8.cjs} +2 -2
  4. package/dist/{HostingerProvider-BTZd2u0f.cjs.map → HostingerProvider-DyD1Hin8.cjs.map} +1 -1
  5. package/dist/{LegacyStateStore-CToa2hga.mjs → LegacyStateStore-A8d2GdT7.mjs} +2 -2
  6. package/dist/{LegacyStateStore-CToa2hga.mjs.map → LegacyStateStore-A8d2GdT7.mjs.map} +1 -1
  7. package/dist/{LegacyStateStore-CidlPT0N.cjs → LegacyStateStore-UHJEBLdn.cjs} +2 -2
  8. package/dist/{LegacyStateStore-CidlPT0N.cjs.map → LegacyStateStore-UHJEBLdn.cjs.map} +1 -1
  9. package/dist/{LocalStateStore-BFLiOocU.mjs → LocalStateStore-B51rnfgn.mjs} +2 -2
  10. package/dist/{LocalStateStore-BFLiOocU.mjs.map → LocalStateStore-B51rnfgn.mjs.map} +1 -1
  11. package/dist/{LocalStateStore-Dpuqka1N.cjs → LocalStateStore-COW3Ldwa.cjs} +2 -2
  12. package/dist/{LocalStateStore-Dpuqka1N.cjs.map → LocalStateStore-COW3Ldwa.cjs.map} +1 -1
  13. package/dist/{OpenApiTsGenerator-BTuUumsV.cjs → OpenApiTsGenerator-BSrgw7B0.cjs} +31 -2
  14. package/dist/OpenApiTsGenerator-BSrgw7B0.cjs.map +1 -0
  15. package/dist/{OpenApiTsGenerator-CvVr1Ilz.mjs → OpenApiTsGenerator-q5B0z8Xg.mjs} +31 -2
  16. package/dist/OpenApiTsGenerator-q5B0z8Xg.mjs.map +1 -0
  17. package/dist/{S3StateStore-aaGkjcxO.mjs → S3StateStore-CJewPhgz.mjs} +2 -2
  18. package/dist/{S3StateStore-aaGkjcxO.mjs.map → S3StateStore-CJewPhgz.mjs.map} +1 -1
  19. package/dist/{S3StateStore-cnm813Xn.cjs → S3StateStore-WUJGdRNL.cjs} +2 -2
  20. package/dist/{S3StateStore-cnm813Xn.cjs.map → S3StateStore-WUJGdRNL.cjs.map} +1 -1
  21. package/dist/{SSMStateStore-DwaGprVX.cjs → SSMStateStore-Zejt42V8.cjs} +2 -2
  22. package/dist/{SSMStateStore-DwaGprVX.cjs.map → SSMStateStore-Zejt42V8.cjs.map} +1 -1
  23. package/dist/{SSMStateStore-BllaJKGo.mjs → SSMStateStore-iK5UKp9d.mjs} +2 -2
  24. package/dist/{SSMStateStore-BllaJKGo.mjs.map → SSMStateStore-iK5UKp9d.mjs.map} +1 -1
  25. package/dist/{bundler-CzXZPSBJ.cjs → bundler-CfH9frOS.cjs} +2 -2
  26. package/dist/{bundler-CzXZPSBJ.cjs.map → bundler-CfH9frOS.cjs.map} +1 -1
  27. package/dist/{bundler-DJVR4QlW.mjs → bundler-DN5r4x5b.mjs} +2 -2
  28. package/dist/{bundler-DJVR4QlW.mjs.map → bundler-DN5r4x5b.mjs.map} +1 -1
  29. package/dist/{cli-D_qTl20Z.cjs → cli-DOAUp80L.cjs} +12 -16
  30. package/dist/cli-DOAUp80L.cjs.map +1 -0
  31. package/dist/{cli-DzR1hpum.mjs → cli-DYwxmfsW.mjs} +10 -14
  32. package/dist/cli-DYwxmfsW.mjs.map +1 -0
  33. package/dist/{config-DXnkCEq0.cjs → config-BYh9S0cZ.cjs} +2 -2
  34. package/dist/config-BYh9S0cZ.cjs.map +1 -0
  35. package/dist/{config-C5-EEdmr.mjs → config-Bf4-bROQ.mjs} +2 -2
  36. package/dist/config-Bf4-bROQ.mjs.map +1 -0
  37. package/dist/config.cjs +2 -2
  38. package/dist/config.d.cts +2 -2
  39. package/dist/config.d.mts +2 -2
  40. package/dist/config.mjs +2 -2
  41. package/dist/define-CHBIEc5j.mjs +94 -0
  42. package/dist/define-CHBIEc5j.mjs.map +1 -0
  43. package/dist/define-Cv_QvDrg.cjs +141 -0
  44. package/dist/define-Cv_QvDrg.cjs.map +1 -0
  45. package/dist/deploy/public.cjs +28 -13
  46. package/dist/deploy/public.d.cts +38 -315
  47. package/dist/deploy/public.d.cts.map +1 -1
  48. package/dist/deploy/public.d.mts +38 -315
  49. package/dist/deploy/public.d.mts.map +1 -1
  50. package/dist/deploy/public.mjs +8 -3
  51. package/dist/{deploy-D6Q09OkA.mjs → deploy-B7jvUORo.mjs} +155 -682
  52. package/dist/deploy-B7jvUORo.mjs.map +1 -0
  53. package/dist/deploy-Cg9fae7a.mjs +133 -0
  54. package/dist/deploy-Cg9fae7a.mjs.map +1 -0
  55. package/dist/deploy-D8Qr-Xto.cjs +138 -0
  56. package/dist/deploy-D8Qr-Xto.cjs.map +1 -0
  57. package/dist/{deploy-0fBVeWO-.cjs → deploy-DSaCYvcO.cjs} +182 -727
  58. package/dist/deploy-DSaCYvcO.cjs.map +1 -0
  59. package/dist/dokploy-CD9PY-3D.mjs +32 -0
  60. package/dist/dokploy-CD9PY-3D.mjs.map +1 -0
  61. package/dist/dokploy-Ey2foJLv.cjs +32 -0
  62. package/dist/dokploy-Ey2foJLv.cjs.map +1 -0
  63. package/dist/{encryption-aDA2AzVx.mjs → encryption-CVwvGbsL.mjs} +4 -4
  64. package/dist/{encryption-aDA2AzVx.mjs.map → encryption-CVwvGbsL.mjs.map} +1 -1
  65. package/dist/{encryption-CML4UaPi.cjs → encryption-ChBk3hTj.cjs} +4 -4
  66. package/dist/{encryption-CML4UaPi.cjs.map → encryption-ChBk3hTj.cjs.map} +1 -1
  67. package/dist/{github-DmCj2u95.mjs → github-BCB3_LBX.mjs} +3 -3
  68. package/dist/{github-DmCj2u95.mjs.map → github-BCB3_LBX.mjs.map} +1 -1
  69. package/dist/{github-Cq57poPj.cjs → github-OUgPDlqg.cjs} +3 -3
  70. package/dist/{github-Cq57poPj.cjs.map → github-OUgPDlqg.cjs.map} +1 -1
  71. package/dist/{index-UiWCaGzU.d.cts → index-BtXDZQuF.d.cts} +2 -2
  72. package/dist/{index-Da1-oa9W.d.mts.map → index-BtXDZQuF.d.cts.map} +1 -1
  73. package/dist/{index-Da1-oa9W.d.mts → index-DrKzpHl-.d.mts} +2 -2
  74. package/dist/{index-UiWCaGzU.d.cts.map → index-DrKzpHl-.d.mts.map} +1 -1
  75. package/dist/index.cjs +1728 -146
  76. package/dist/index.cjs.map +1 -1
  77. package/dist/index.mjs +1719 -153
  78. package/dist/index.mjs.map +1 -1
  79. package/dist/migrate-BoHMqdCu.mjs +265 -0
  80. package/dist/migrate-BoHMqdCu.mjs.map +1 -0
  81. package/dist/migrate-dnaFMvOm.cjs +270 -0
  82. package/dist/migrate-dnaFMvOm.cjs.map +1 -0
  83. package/dist/openapi.cjs +2 -2
  84. package/dist/openapi.d.cts +1 -1
  85. package/dist/openapi.d.mts +1 -1
  86. package/dist/openapi.mjs +2 -2
  87. package/dist/{ready-CIHpnUc5.mjs → ready-DQIy21W5.mjs} +2 -2
  88. package/dist/{ready-CIHpnUc5.mjs.map → ready-DQIy21W5.mjs.map} +1 -1
  89. package/dist/{ready-CCLIAkwR.cjs → ready-XlNx-Gbo.cjs} +2 -2
  90. package/dist/{ready-CCLIAkwR.cjs.map → ready-XlNx-Gbo.cjs.map} +1 -1
  91. package/dist/reconcile/public.d.cts +1 -1
  92. package/dist/reconcile/public.d.mts +1 -1
  93. package/dist/resolve-CFCIkm7m.mjs +170 -0
  94. package/dist/resolve-CFCIkm7m.mjs.map +1 -0
  95. package/dist/resolve-wbv66HjD.cjs +217 -0
  96. package/dist/resolve-wbv66HjD.cjs.map +1 -0
  97. package/dist/runtime-CMwtq0AL.cjs +163 -0
  98. package/dist/runtime-CMwtq0AL.cjs.map +1 -0
  99. package/dist/runtime-CXPlkZzs.d.mts +90 -0
  100. package/dist/runtime-CXPlkZzs.d.mts.map +1 -0
  101. package/dist/runtime-DbakJS8u.mjs +134 -0
  102. package/dist/runtime-DbakJS8u.mjs.map +1 -0
  103. package/dist/runtime-Dn_n-29S.d.cts +90 -0
  104. package/dist/runtime-Dn_n-29S.d.cts.map +1 -0
  105. package/dist/{sniffer-DIv12ncU.cjs → sniffer-BsfPa-GA.cjs} +2581 -2170
  106. package/dist/sniffer-BsfPa-GA.cjs.map +1 -0
  107. package/dist/{sniffer-BM8fpCas.mjs → sniffer-DHE2Nafd.mjs} +2428 -2185
  108. package/dist/sniffer-DHE2Nafd.mjs.map +1 -0
  109. package/dist/target/public.cjs +15 -0
  110. package/dist/target/public.d.cts +28 -0
  111. package/dist/target/public.d.cts.map +1 -0
  112. package/dist/target/public.d.mts +28 -0
  113. package/dist/target/public.d.mts.map +1 -0
  114. package/dist/target/public.mjs +4 -0
  115. package/dist/terminal-6oL0vANs.cjs +576 -0
  116. package/dist/terminal-6oL0vANs.cjs.map +1 -0
  117. package/dist/terminal-ByZNjuig.mjs +517 -0
  118. package/dist/terminal-ByZNjuig.mjs.map +1 -0
  119. package/dist/{types-efNLu9xu.d.cts → types-CfLKGfC_.d.mts} +624 -34
  120. package/dist/types-CfLKGfC_.d.mts.map +1 -0
  121. package/dist/{types-Bp1mVxG0.d.mts → types-DIA7Li-J.d.cts} +626 -34
  122. package/dist/types-DIA7Li-J.d.cts.map +1 -0
  123. package/dist/vitest.cjs +1 -1
  124. package/dist/vitest.mjs +1 -1
  125. package/dist/workspace/index.cjs +1 -1
  126. package/dist/workspace/index.d.cts +3 -3
  127. package/dist/workspace/index.d.mts +3 -3
  128. package/dist/workspace/index.mjs +1 -1
  129. package/dist/{workspace-B64Xk1Mb.cjs → workspace-B6zQO6RY.cjs} +229 -23
  130. package/dist/workspace-B6zQO6RY.cjs.map +1 -0
  131. package/dist/{workspace-Bp1xVaOz.mjs → workspace-BFe57es7.mjs} +229 -23
  132. package/dist/workspace-BFe57es7.mjs.map +1 -0
  133. package/package.json +23 -13
  134. package/dist/OpenApiTsGenerator-BTuUumsV.cjs.map +0 -1
  135. package/dist/OpenApiTsGenerator-CvVr1Ilz.mjs.map +0 -1
  136. package/dist/cli-D_qTl20Z.cjs.map +0 -1
  137. package/dist/cli-DzR1hpum.mjs.map +0 -1
  138. package/dist/config-C5-EEdmr.mjs.map +0 -1
  139. package/dist/config-DXnkCEq0.cjs.map +0 -1
  140. package/dist/deploy-0fBVeWO-.cjs.map +0 -1
  141. package/dist/deploy-D6Q09OkA.mjs.map +0 -1
  142. package/dist/migrate-BTqIflwc.cjs +0 -743
  143. package/dist/migrate-BTqIflwc.cjs.map +0 -1
  144. package/dist/migrate-B_6KofUo.mjs +0 -736
  145. package/dist/migrate-B_6KofUo.mjs.map +0 -1
  146. package/dist/sniffer-BM8fpCas.mjs.map +0 -1
  147. package/dist/sniffer-DIv12ncU.cjs.map +0 -1
  148. package/dist/types-Bp1mVxG0.d.mts.map +0 -1
  149. package/dist/types-efNLu9xu.d.cts.map +0 -1
  150. package/dist/workspace-B64Xk1Mb.cjs.map +0 -1
  151. package/dist/workspace-Bp1xVaOz.mjs.map +0 -1
@@ -1,110 +1,19 @@
1
- import { B as providerOf, C as run, D as constructGlobs, L as resourceName, N as applyPostgres, R as cacheBackendFor, S as keyFingerprint, V as storageBackendFor, a as dockerCommand, b as encryptSecrets, c as resolveHost, ct as storeDokployCredentials, f as StateStoreBusy, g as createStateStore, i as DockerPushFailed, lt as canPrompt, m as StateVersionConflict, o as validateImageRef, r as DockerBuildFailed, s as isMainFrontendApp, st as readCredentials, t as sniffAllApps, tt as validateDokployToken, ut as prompt, v as DokployApi, w as runOutput, y as DokployApiError, z as eventsBackendFor } from "./sniffer-BM8fpCas.mjs";
2
- import { n as gkmHome } from "./home-GI7pJl1M.mjs";
3
- import { a as output, o as withOutput, t as discover } from "./discover-FrYvzkeC.mjs";
4
- import { f as appKey, l as loadWorkspaceConfig, p as derivedApps } from "./config-C5-EEdmr.mjs";
5
- import { D as assertDeployedStage, a as getAppBuildOrder, b as getDeployTargetError, m as stripPublicPrefix, p as getPublicEnvPrefix, x as isDeployTargetSupported } from "./workspace-Bp1xVaOz.mjs";
1
+ import { A as StateStoreBusy, B as run, C as setDnsRecord, E as setPostgresBackupId, I as withGeneratedSecrets, L as encryptSecrets, M as StateVersionConflict, S as setDeployedImage, T as setGeneratedSecret, V as runOutput, W as constructGlobs, X as applyPostgres, _ as getBackupState, a as DockerBuildFailed, b as setApplicationId, c as dockerCommand, dt as providerOf, ft as storageBackendFor, g as createEmptyState, h as resolveHost, i as DokployApiError, lt as cacheBackendFor, m as isMainFrontendApp, o as DockerPushFailed, p as validateImageRef, r as DokployApi, st as resourceName, t as sniffAllApps, ut as eventsBackendFor, v as getGeneratedSecret, w as setDnsVerification, x as setBackupState, y as isDnsVerified, z as keyFingerprint } from "./sniffer-DHE2Nafd.mjs";
2
+ import { a as output, t as discover } from "./discover-FrYvzkeC.mjs";
3
+ import { f as appKey } from "./config-Bf4-bROQ.mjs";
4
+ import { a as getAppBuildOrder, m as stripPublicPrefix, p as getPublicEnvPrefix } from "./workspace-BFe57es7.mjs";
6
5
  import { i as toEmbeddableSecrets, t as initStageSecrets } from "./storage-BzaUxmqe.mjs";
7
- import { d as imageName, f as imageRef, g as projectName, h as ownershipMarker, l as applicationName, m as markerOf, n as secretsStoreFor, p as isOwnedBy, u as deployIdentity } from "./store-BS8A7NcA.mjs";
6
+ import { d as imageName, f as imageRef, g as projectName, h as ownershipMarker, l as applicationName, m as markerOf, p as isOwnedBy } from "./store-BS8A7NcA.mjs";
7
+ import { c as MissingCredential, o as eventError } from "./terminal-ByZNjuig.mjs";
8
8
  import { join, resolve } from "node:path";
9
9
  import { chmod, mkdtemp, rm, writeFile } from "node:fs/promises";
10
10
  import { tmpdir } from "node:os";
11
11
  import { cacheTable, cloudName, cookieDomain, dependentsOf, externalApiUrl, mobileOrigins, provideKey, provisionOrder, schemeBase } from "@geekmidas/manifest";
12
12
  import { createHash, randomBytes } from "node:crypto";
13
- import { generateKeyring } from "@geekmidas/constructs/encryption";
14
13
  import { ownerRole, readerRole, roleStatements } from "@geekmidas/db/pg/roles";
15
14
  import { Client } from "pg";
16
15
  import { cacheTableStatements } from "@geekmidas/cache/postgres";
17
16
  import { lookup } from "node:dns/promises";
18
- //#region src/deploy/credentials.ts
19
- /**
20
- * How a deploy gets the credentials it acts with.
21
- *
22
- * `deploy()` never prompts and never reads a terminal: it asks a
23
- * `CredentialProvider` and, when the provider has nothing, stops with
24
- * `MissingCredential` naming what it needed and how to supply it. Whether to
25
- * ask a person, read a vault or fail is the caller's decision — `gkm deploy`
26
- * prompts at a terminal and stores what was typed; a CI job sets the
27
- * environment; a host passes its own provider.
28
- */
29
- /** How to supply each kind, for the error that says it is missing. */
30
- const HOW_TO_PROVIDE = {
31
- dokploy: "Set DOKPLOY_API_TOKEN (and DOKPLOY_ENDPOINT, or deploy.dokploy.endpoint in gkm.config.ts), run `gkm login --provider dokploy`, or pass them through the deploy's CredentialProvider.",
32
- registry: "Add the registry in Dokploy (Settings → Docker Registry) and set deploy.dokploy.registryId, set DOCKER_REGISTRY_USERNAME and DOCKER_REGISTRY_PASSWORD, or run `gkm deploy` at a terminal to be asked for them."
33
- };
34
- /** A deploy needed a credential, and its provider had none. */
35
- var MissingCredential = class extends Error {
36
- kind;
37
- target;
38
- howToProvide;
39
- constructor(kind, target, howToProvide = HOW_TO_PROVIDE[kind]) {
40
- const what = kind === "dokploy" ? `No Dokploy credentials${target ? ` for ${target}` : ""}.` : `Dokploy has no registry for ${target ?? "the configured registry"}, and there are no credentials to create one with.`;
41
- super(`${what} ${howToProvide}`);
42
- this.kind = kind;
43
- this.target = target;
44
- this.howToProvide = howToProvide;
45
- this.name = "MissingCredential";
46
- }
47
- };
48
- /** Whatever was asked for, from the first provider that has it. */
49
- function chainCredentials(...providers) {
50
- return { async get(request, options) {
51
- for (const provider of providers) {
52
- const found = await provider.get(request, options);
53
- if (found) return found;
54
- }
55
- } };
56
- }
57
- /**
58
- * Credentials from the environment, then from what `gkm login` stored. What
59
- * `deploy()` uses when it is handed no provider.
60
- *
61
- * - Dokploy: `DOKPLOY_API_TOKEN` / `DOKPLOY_ENDPOINT`, each falling back to
62
- * the stored login, and the endpoint finally to `deploy.dokploy.endpoint`.
63
- * Each half is read on its own: a token is a secret and belongs in the
64
- * environment, an endpoint is configuration and belongs in the config.
65
- * - Registry: `DOCKER_REGISTRY_USERNAME` / `DOCKER_REGISTRY_PASSWORD`.
66
- */
67
- function storedCredentials(options = {}) {
68
- const env = options.env ?? process.env;
69
- return { async get(asked) {
70
- const request = asked;
71
- switch (request.kind) {
72
- case "dokploy": {
73
- const stored = (await readCredentials(options.home ? { home: options.home } : void 0)).dokploy;
74
- const token = env.DOKPLOY_API_TOKEN ?? stored?.token;
75
- const endpoint = env.DOKPLOY_ENDPOINT ?? stored?.endpoint ?? request.endpoint;
76
- if (!token || !endpoint) return void 0;
77
- return {
78
- endpoint: endpoint.replace(/\/$/, ""),
79
- token
80
- };
81
- }
82
- case "registry": {
83
- const username = env.DOCKER_REGISTRY_USERNAME;
84
- const password = env.DOCKER_REGISTRY_PASSWORD;
85
- if (!username || !password) return void 0;
86
- return {
87
- username,
88
- password
89
- };
90
- }
91
- }
92
- } };
93
- }
94
- //#endregion
95
- //#region src/deploy/events.ts
96
- /** An error as an event carries it: its name and message, nothing else. */
97
- function eventError(error) {
98
- if (error instanceof Error) return {
99
- name: error.name,
100
- message: error.message
101
- };
102
- return {
103
- name: "Error",
104
- message: String(error)
105
- };
106
- }
107
- //#endregion
108
17
  //#region src/deploy/fromManifest.ts
109
18
  /**
110
19
  * The Dokploy target, read off the construct manifest.
@@ -855,102 +764,6 @@ function surfaceAddresses(manifest, appUrls) {
855
764
  return addresses;
856
765
  }
857
766
  //#endregion
858
- //#region src/deploy/state.ts
859
- /**
860
- * Create a new empty state for a stage
861
- */
862
- function createEmptyState(stage, projectId, environmentId) {
863
- return {
864
- provider: "dokploy",
865
- stage,
866
- projectId,
867
- environmentId,
868
- applications: {},
869
- services: {},
870
- lastDeployedAt: (/* @__PURE__ */ new Date()).toISOString()
871
- };
872
- }
873
- /**
874
- * Set application ID in state (mutates state)
875
- */
876
- function setApplicationId(state, appName, applicationId) {
877
- state.applications[appName] = applicationId;
878
- }
879
- /**
880
- * Record the image an app was deployed with (mutates state)
881
- */
882
- function setDeployedImage(state, appName, image) {
883
- state.images = {
884
- ...state.images,
885
- [appName]: image
886
- };
887
- }
888
- /**
889
- * Get a generated secret for an app
890
- */
891
- function getGeneratedSecret(state, appName, secretName) {
892
- return state?.generatedSecrets?.[appName]?.[secretName];
893
- }
894
- /**
895
- * Set a generated secret for an app (mutates state)
896
- */
897
- function setGeneratedSecret(state, appName, secretName, value) {
898
- if (!state.generatedSecrets) state.generatedSecrets = {};
899
- if (!state.generatedSecrets[appName]) state.generatedSecrets[appName] = {};
900
- state.generatedSecrets[appName][secretName] = value;
901
- }
902
- /**
903
- * Set DNS verification record for a hostname (mutates state)
904
- */
905
- function setDnsVerification(state, hostname, serverIp) {
906
- if (!state.dnsVerified) state.dnsVerified = {};
907
- state.dnsVerified[hostname] = {
908
- serverIp,
909
- verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
910
- };
911
- }
912
- /**
913
- * Check if a hostname is already verified with the given IP
914
- */
915
- function isDnsVerified(state, hostname, serverIp) {
916
- return (state?.dnsVerified?.[hostname])?.serverIp === serverIp;
917
- }
918
- /**
919
- * Get the key for a DNS record in state
920
- */
921
- function getDnsRecordKey(name, type) {
922
- return `${name}:${type}`;
923
- }
924
- /**
925
- * Set a created DNS record in state (mutates state)
926
- */
927
- function setDnsRecord(state, record) {
928
- if (!state.dnsRecords) state.dnsRecords = {};
929
- const key = getDnsRecordKey(record.name, record.type);
930
- state.dnsRecords[key] = {
931
- ...record,
932
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
933
- };
934
- }
935
- /**
936
- * Get backup state from state
937
- */
938
- function getBackupState(state) {
939
- return state?.backups;
940
- }
941
- /**
942
- * Set backup state (mutates state)
943
- */
944
- function setBackupState(state, backupState) {
945
- state.backups = backupState;
946
- }
947
- /**
948
- * Set postgres backup ID in state (mutates state)
949
- */
950
- function setPostgresBackupId(state, backupId) {
951
- if (state.backups) state.backups.postgresBackupId = backupId;
952
- }
953
- //#endregion
954
767
  //#region src/deploy/dns/DnsProvider.ts
955
768
  /**
956
769
  * Check if value is a DnsProvider implementation.
@@ -972,7 +785,7 @@ async function createDnsProvider(options) {
972
785
  if (isDnsProvider(config.provider)) return config.provider;
973
786
  const provider = config.provider;
974
787
  if (provider === "hostinger") {
975
- const { HostingerProvider } = await import("./HostingerProvider-DgzKa_Tj.mjs");
788
+ const { HostingerProvider } = await import("./HostingerProvider-B92qH4dC.mjs");
976
789
  return new HostingerProvider();
977
790
  }
978
791
  if (provider === "route53") {
@@ -994,7 +807,7 @@ async function createDnsProvider(options) {
994
807
  *
995
808
  * Handles automatic DNS record creation for deployed applications.
996
809
  */
997
- const logger$3 = output;
810
+ const logger$2 = output;
998
811
  /**
999
812
  * Check if DNS config is legacy format (single domain with `domain` property)
1000
813
  */
@@ -1031,7 +844,7 @@ function groupHostnamesByDomain(appHostnames, dnsConfig) {
1031
844
  for (const [appName, hostname] of appHostnames) {
1032
845
  const rootDomain = findRootDomain(hostname, dnsConfig);
1033
846
  if (!rootDomain) {
1034
- logger$3.log(` ⚠ No DNS config found for hostname: ${hostname}`);
847
+ logger$2.log(` ⚠ No DNS config found for hostname: ${hostname}`);
1035
848
  continue;
1036
849
  }
1037
850
  if (!grouped.has(rootDomain)) grouped.set(rootDomain, /* @__PURE__ */ new Map());
@@ -1081,10 +894,10 @@ function generateRequiredRecords(appHostnames, rootDomain, serverIp) {
1081
894
  * Print DNS records table
1082
895
  */
1083
896
  function printDnsRecordsTable(records, rootDomain) {
1084
- logger$3.log(`\n 📋 DNS Records for ${rootDomain}:`);
1085
- logger$3.log(" ┌─────────────────────────────────────┬──────┬─────────────────┬────────┐");
1086
- logger$3.log(" │ Subdomain │ Type │ Value │ Status │");
1087
- logger$3.log(" ├─────────────────────────────────────┼──────┼─────────────────┼────────┤");
897
+ logger$2.log(`\n 📋 DNS Records for ${rootDomain}:`);
898
+ logger$2.log(" ┌─────────────────────────────────────┬──────┬─────────────────┬────────┐");
899
+ logger$2.log(" │ Subdomain │ Type │ Value │ Status │");
900
+ logger$2.log(" ├─────────────────────────────────────┼──────┼─────────────────┼────────┤");
1088
901
  for (const record of records) {
1089
902
  const subdomain = record.subdomain.padEnd(35);
1090
903
  const type = record.type.padEnd(4);
@@ -1094,18 +907,18 @@ function printDnsRecordsTable(records, rootDomain) {
1094
907
  else if (record.created) status = "✓ new";
1095
908
  else if (record.existed) status = "✓";
1096
909
  else status = "?";
1097
- logger$3.log(` │ ${subdomain} │ ${type} │ ${value} │ ${status.padEnd(6)} │`);
910
+ logger$2.log(` │ ${subdomain} │ ${type} │ ${value} │ ${status.padEnd(6)} │`);
1098
911
  }
1099
- logger$3.log(" └─────────────────────────────────────┴──────┴─────────────────┴────────┘");
912
+ logger$2.log(" └─────────────────────────────────────┴──────┴─────────────────┴────────┘");
1100
913
  }
1101
914
  /**
1102
915
  * Print DNS records in a simple format for manual setup
1103
916
  */
1104
917
  function printDnsRecordsSimple(records, rootDomain) {
1105
- logger$3.log("\n 📋 Required DNS Records:");
1106
- logger$3.log(` Add these A records to your DNS provider (${rootDomain}):\n`);
1107
- for (const record of records) logger$3.log(` ${record.subdomain} → ${record.value} (A record)`);
1108
- logger$3.log("");
918
+ logger$2.log("\n 📋 Required DNS Records:");
919
+ logger$2.log(` Add these A records to your DNS provider (${rootDomain}):\n`);
920
+ for (const record of records) logger$2.log(` ${record.subdomain} → ${record.value} (A record)`);
921
+ logger$2.log("");
1109
922
  }
1110
923
  /**
1111
924
  * Create DNS records for a single domain using its configured provider
@@ -1117,7 +930,7 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
1117
930
  provider = await createDnsProvider({ config: providerConfig });
1118
931
  } catch (error) {
1119
932
  const message = error instanceof Error ? error.message : "Unknown error";
1120
- logger$3.log(` ⚠ Failed to create DNS provider for ${rootDomain}: ${message}`);
933
+ logger$2.log(` ⚠ Failed to create DNS provider for ${rootDomain}: ${message}`);
1121
934
  return records.map((r) => ({
1122
935
  ...r,
1123
936
  error: message
@@ -1171,7 +984,7 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
1171
984
  }
1172
985
  } catch (error) {
1173
986
  const message = error instanceof Error ? error.message : "Unknown error";
1174
- logger$3.log(` ⚠ Failed to create DNS records for ${rootDomain}: ${message}`);
987
+ logger$2.log(` ⚠ Failed to create DNS records for ${rootDomain}: ${message}`);
1175
988
  return records.map((r) => ({
1176
989
  hostname: r.hostname,
1177
990
  subdomain: r.subdomain,
@@ -1198,20 +1011,20 @@ async function createDnsRecordsForDomain(records, rootDomain, providerConfig) {
1198
1011
  async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
1199
1012
  if (!dnsConfig) return null;
1200
1013
  const normalizedConfig = normalizeDnsConfig(dnsConfig);
1201
- logger$3.log("\n🌐 Setting up DNS records...");
1014
+ logger$2.log("\n🌐 Setting up DNS records...");
1202
1015
  let serverIp;
1203
1016
  try {
1204
1017
  const endpointUrl = new URL(dokployEndpoint);
1205
1018
  serverIp = await resolveHostnameToIp(endpointUrl.hostname);
1206
- logger$3.log(` Server IP: ${serverIp} (from ${endpointUrl.hostname})`);
1019
+ logger$2.log(` Server IP: ${serverIp} (from ${endpointUrl.hostname})`);
1207
1020
  } catch (error) {
1208
1021
  const message = error instanceof Error ? error.message : "Unknown error";
1209
- logger$3.log(` ⚠ Failed to resolve server IP: ${message}`);
1022
+ logger$2.log(` ⚠ Failed to resolve server IP: ${message}`);
1210
1023
  return null;
1211
1024
  }
1212
1025
  const groupedHostnames = groupHostnamesByDomain(appHostnames, normalizedConfig);
1213
1026
  if (groupedHostnames.size === 0) {
1214
- logger$3.log(" No DNS records needed (no hostnames match configured domains)");
1027
+ logger$2.log(" No DNS records needed (no hostnames match configured domains)");
1215
1028
  return {
1216
1029
  records: [],
1217
1030
  success: true,
@@ -1223,22 +1036,22 @@ async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
1223
1036
  for (const [rootDomain, domainHostnames] of groupedHostnames) {
1224
1037
  const providerConfig = normalizedConfig[rootDomain];
1225
1038
  if (!providerConfig) {
1226
- logger$3.log(` ⚠ No provider config for ${rootDomain}`);
1039
+ logger$2.log(` ⚠ No provider config for ${rootDomain}`);
1227
1040
  continue;
1228
1041
  }
1229
1042
  const providerName = typeof providerConfig.provider === "string" ? providerConfig.provider : "custom";
1230
1043
  const requiredRecords = generateRequiredRecords(domainHostnames, rootDomain, serverIp);
1231
1044
  if (requiredRecords.length === 0) continue;
1232
- logger$3.log(` Creating DNS records for ${rootDomain} (${providerName})...`);
1045
+ logger$2.log(` Creating DNS records for ${rootDomain} (${providerName})...`);
1233
1046
  const domainRecords = await createDnsRecordsForDomain(requiredRecords, rootDomain, providerConfig);
1234
1047
  allRecords.push(...domainRecords);
1235
1048
  const created = domainRecords.filter((r) => r.created).length;
1236
1049
  const existed = domainRecords.filter((r) => r.existed).length;
1237
1050
  const failed = domainRecords.filter((r) => r.error).length;
1238
- if (created > 0) logger$3.log(` ✓ Created ${created} DNS record(s) for ${rootDomain}`);
1239
- if (existed > 0) logger$3.log(` ✓ ${existed} record(s) already exist for ${rootDomain}`);
1051
+ if (created > 0) logger$2.log(` ✓ Created ${created} DNS record(s) for ${rootDomain}`);
1052
+ if (existed > 0) logger$2.log(` ✓ ${existed} record(s) already exist for ${rootDomain}`);
1240
1053
  if (failed > 0) {
1241
- logger$3.log(` ⚠ ${failed} record(s) failed for ${rootDomain}`);
1054
+ logger$2.log(` ⚠ ${failed} record(s) failed for ${rootDomain}`);
1242
1055
  hasFailures = true;
1243
1056
  }
1244
1057
  if (state) {
@@ -1275,10 +1088,10 @@ async function orchestrateDns(appHostnames, dnsConfig, dokployEndpoint, state) {
1275
1088
  */
1276
1089
  async function verifyDnsRecords(appHostnames, serverIp, state) {
1277
1090
  const results = [];
1278
- logger$3.log("\n🔍 Verifying DNS records...");
1091
+ logger$2.log("\n🔍 Verifying DNS records...");
1279
1092
  for (const [appName, hostname] of appHostnames) {
1280
1093
  if (isDnsVerified(state, hostname, serverIp)) {
1281
- logger$3.log(` ✓ ${hostname} (previously verified)`);
1094
+ logger$2.log(` ✓ ${hostname} (previously verified)`);
1282
1095
  results.push({
1283
1096
  hostname,
1284
1097
  appName,
@@ -1292,7 +1105,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
1292
1105
  const resolvedIp = await resolveHostnameToIp(hostname);
1293
1106
  if (resolvedIp === serverIp) {
1294
1107
  setDnsVerification(state, hostname, serverIp);
1295
- logger$3.log(` ✓ ${hostname} → ${resolvedIp}`);
1108
+ logger$2.log(` ✓ ${hostname} → ${resolvedIp}`);
1296
1109
  results.push({
1297
1110
  hostname,
1298
1111
  appName,
@@ -1301,7 +1114,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
1301
1114
  expectedIp: serverIp
1302
1115
  });
1303
1116
  } else {
1304
- logger$3.log(` ⚠ ${hostname} resolves to ${resolvedIp}, expected ${serverIp}`);
1117
+ logger$2.log(` ⚠ ${hostname} resolves to ${resolvedIp}, expected ${serverIp}`);
1305
1118
  results.push({
1306
1119
  hostname,
1307
1120
  appName,
@@ -1312,7 +1125,7 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
1312
1125
  }
1313
1126
  } catch (error) {
1314
1127
  const message = error instanceof Error ? error.message : "Unknown error";
1315
- logger$3.log(` ⚠ ${hostname} DNS not propagated (${message})`);
1128
+ logger$2.log(` ⚠ ${hostname} DNS not propagated (${message})`);
1316
1129
  results.push({
1317
1130
  hostname,
1318
1131
  appName,
@@ -1326,14 +1139,14 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
1326
1139
  const skipped = results.filter((r) => r.skipped).length;
1327
1140
  const pending = results.filter((r) => !r.verified).length;
1328
1141
  if (pending > 0) {
1329
- logger$3.log(`\n ${verified} verified, ${pending} pending propagation`);
1330
- logger$3.log(" DNS changes may take 5-30 minutes to propagate");
1331
- } else if (skipped > 0) logger$3.log(` ${verified} verified (${skipped} from cache)`);
1142
+ logger$2.log(`\n ${verified} verified, ${pending} pending propagation`);
1143
+ logger$2.log(" DNS changes may take 5-30 minutes to propagate");
1144
+ } else if (skipped > 0) logger$2.log(` ${verified} verified (${skipped} from cache)`);
1332
1145
  return results;
1333
1146
  }
1334
1147
  //#endregion
1335
1148
  //#region src/deploy/docker.ts
1336
- const logger$2 = output;
1149
+ const logger$1 = output;
1337
1150
  /**
1338
1151
  * The id the Dockerfile templates mount the encrypted credentials under:
1339
1152
  * `RUN --mount=type=secret,id=gkm_credentials`.
@@ -1396,8 +1209,8 @@ async function writeCredentialsFile(credentials) {
1396
1209
  * @param credentials - Encrypted credentials, passed as a build secret
1397
1210
  */
1398
1211
  async function buildImage(imageRef, buildArgs, credentials, { cwd, signal, stdio }) {
1399
- logger$2.log(`\n🔨 Building Docker image: ${imageRef}`);
1400
- logger$2.log(" Generating Dockerfile for the pre-built bundle...");
1212
+ logger$1.log(`\n🔨 Building Docker image: ${imageRef}`);
1213
+ logger$1.log(" Generating Dockerfile for the pre-built bundle...");
1401
1214
  await dockerCommand({
1402
1215
  slim: true,
1403
1216
  cwd
@@ -1419,7 +1232,7 @@ async function buildImage(imageRef, buildArgs, credentials, { cwd, signal, stdio
1419
1232
  ...signal ? { signal } : {},
1420
1233
  ...stdio ? { stdio } : {}
1421
1234
  });
1422
- logger$2.log(`✅ Image built: ${imageRef}`);
1235
+ logger$1.log(`✅ Image built: ${imageRef}`);
1423
1236
  } catch (error) {
1424
1237
  throw new DockerBuildFailed(imageRef, error);
1425
1238
  } finally {
@@ -1430,14 +1243,14 @@ async function buildImage(imageRef, buildArgs, credentials, { cwd, signal, stdio
1430
1243
  * Push Docker image to registry
1431
1244
  */
1432
1245
  async function pushImage(imageRef, { cwd, signal, stdio }) {
1433
- logger$2.log(`\n☁️ Pushing image: ${imageRef}`);
1246
+ logger$1.log(`\n☁️ Pushing image: ${imageRef}`);
1434
1247
  try {
1435
1248
  await run("docker", ["push", imageRef], {
1436
1249
  cwd,
1437
1250
  ...signal ? { signal } : {},
1438
1251
  ...stdio ? { stdio } : {}
1439
1252
  });
1440
- logger$2.log(`✅ Image pushed: ${imageRef}`);
1253
+ logger$1.log(`✅ Image pushed: ${imageRef}`);
1441
1254
  } catch (error) {
1442
1255
  throw new DockerPushFailed(imageRef, error);
1443
1256
  }
@@ -1487,17 +1300,17 @@ async function deployDocker(options) {
1487
1300
  await buildImage(imageRef, buildArgs, credentials, docker);
1488
1301
  let digest;
1489
1302
  if (!skipPush) {
1490
- if (!config.registry) logger$2.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
1303
+ if (!config.registry) logger$1.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
1491
1304
  else {
1492
1305
  await pushImage(imageRef, docker);
1493
1306
  digest = await pushedDigest(imageRef, docker);
1494
1307
  }
1495
1308
  }
1496
- logger$2.log("\n✅ Docker deployment ready!");
1497
- logger$2.log(`\n📋 Deployment details:`);
1498
- logger$2.log(` Image: ${imageRef}`);
1499
- logger$2.log(` Stage: ${stage}`);
1500
- if (masterKey) logger$2.log(`\n🔐 Run the container with GKM_MASTER_KEY set to the key with fingerprint ${keyFingerprint(masterKey)}.`);
1309
+ logger$1.log("\n✅ Docker deployment ready!");
1310
+ logger$1.log(`\n📋 Deployment details:`);
1311
+ logger$1.log(` Image: ${imageRef}`);
1312
+ logger$1.log(` Stage: ${stage}`);
1313
+ if (masterKey) logger$1.log(`\n🔐 Run the container with GKM_MASTER_KEY set to the key with fingerprint ${keyFingerprint(masterKey)}.`);
1501
1314
  return {
1502
1315
  imageRef,
1503
1316
  ...digest ? { digest } : {},
@@ -1591,57 +1404,6 @@ function validateEnvVars(requiredVars, context) {
1591
1404
  };
1592
1405
  }
1593
1406
  //#endregion
1594
- //#region src/deploy/generated.ts
1595
- /**
1596
- * The values a deployed stage generates once and keeps: what nothing can
1597
- * provision and nobody else issues.
1598
- *
1599
- * - **A seed**, which salts every password a deploy derives — a database's
1600
- * master and roles, a bucket's root user. Derived from repo facts alone
1601
- * (project, stage, construct id), those passwords were computable by anyone
1602
- * who could read the repo.
1603
- * - **Each `secret` construct's value** — an auth server's signing secret —
1604
- * random, rather than derived.
1605
- * - **Each `encryption` construct's keyring** — one random key and an index
1606
- * key. Later keys are added by `gkm encryption:rotate`, never by a deploy.
1607
- *
1608
- * Both are generated on the first deploy that needs them and written to the
1609
- * stage's store, so every later deploy reads the same values: sessions survive
1610
- * a redeploy, and a role's password does not move. A value set by hand with
1611
- * `gkm secrets:set` is kept, never replaced.
1612
- */
1613
- /**
1614
- * The stage's secrets with its seed and every declared `secret`'s value
1615
- * present, generating what is missing. Pure: the caller writes the result
1616
- * back to the stage's store when `generated` is not empty.
1617
- */
1618
- function withGeneratedSecrets(secrets, manifest) {
1619
- const generated = [];
1620
- const custom = { ...secrets.custom };
1621
- for (const declaration of Object.values(manifest)) {
1622
- if (declaration?.kind !== "secret" && declaration?.kind !== "encryption") continue;
1623
- const key = declaration.provides?.[0];
1624
- if (!key || custom[key]) continue;
1625
- custom[key] = declaration.kind === "encryption" ? generateKeyring() : random();
1626
- generated.push(key);
1627
- }
1628
- const seed = secrets.seed ?? random();
1629
- if (!secrets.seed) generated.push("seed");
1630
- return {
1631
- secrets: generated.length ? {
1632
- ...secrets,
1633
- seed,
1634
- custom,
1635
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1636
- } : secrets,
1637
- generated
1638
- };
1639
- }
1640
- /** 256 bits, URL-safe. */
1641
- function random() {
1642
- return randomBytes(32).toString("base64url");
1643
- }
1644
- //#endregion
1645
1407
  //#region src/deploy/journal.ts
1646
1408
  var DeployJournal = class DeployJournal {
1647
1409
  store;
@@ -2059,83 +1821,6 @@ function generateSecretsReport(encryptedApps, sniffedApps) {
2059
1821
  };
2060
1822
  }
2061
1823
  //#endregion
2062
- //#region src/deploy/terminal.ts
2063
- /**
2064
- * The credentials `gkm deploy` can ask a person for. CLI layer only.
2065
- *
2066
- * `deploy()` asks its `CredentialProvider` and stops with `MissingCredential`
2067
- * when the answer is nothing. At a terminal, `gkm deploy` would rather ask:
2068
- * this provider reads the environment and the stored login first, and only
2069
- * when both are empty prompts — and stores a Dokploy login it validated, so
2070
- * the next deploy does not ask again. With no terminal it answers nothing, and
2071
- * the deploy says what was missing instead of waiting on a prompt nobody sees.
2072
- */
2073
- const logger$1 = output;
2074
- /** What answers a deploy prompt without a terminal. */
2075
- const INSTEAD = "Please configure manually.";
2076
- /** The Dokploy URL typed at the prompt is not a URL. */
2077
- var DokployEndpointInvalid = class extends Error {
2078
- endpoint;
2079
- constructor(endpoint) {
2080
- super("Invalid URL format");
2081
- this.endpoint = endpoint;
2082
- this.name = "DokployEndpointInvalid";
2083
- }
2084
- };
2085
- /** Dokploy refused the token typed at the prompt; nothing was stored. */
2086
- var DokployTokenRejected = class extends Error {
2087
- endpoint;
2088
- constructor(endpoint) {
2089
- super("Invalid credentials. Please check your token.");
2090
- this.endpoint = endpoint;
2091
- this.name = "DokployTokenRejected";
2092
- }
2093
- };
2094
- /** Asks the person at the terminal for what nothing else supplied. */
2095
- function asking() {
2096
- return { async get(asked) {
2097
- if (!canPrompt()) return void 0;
2098
- const request = asked;
2099
- if (request.kind === "dokploy") {
2100
- logger$1.log("\n📋 Dokploy credentials not found. Let's set them up.");
2101
- const endpoint = (await prompt("Dokploy URL (e.g., https://dokploy.example.com): ", { instead: INSTEAD })).replace(/\/$/, "");
2102
- try {
2103
- new URL(endpoint);
2104
- } catch {
2105
- throw new DokployEndpointInvalid(endpoint);
2106
- }
2107
- logger$1.log(`\nGenerate a token at: ${endpoint}/settings/profile\n`);
2108
- const token = await prompt("API Token: ", {
2109
- hidden: true,
2110
- instead: INSTEAD
2111
- });
2112
- logger$1.log("\nValidating credentials...");
2113
- if (!await validateDokployToken(endpoint, token)) throw new DokployTokenRejected(endpoint);
2114
- await storeDokployCredentials(token, endpoint);
2115
- logger$1.log("✓ Credentials saved");
2116
- return {
2117
- endpoint,
2118
- token
2119
- };
2120
- }
2121
- logger$1.log(` Dokploy has no registry for ${request.url}. Let's create one.`);
2122
- return {
2123
- username: await prompt("Registry username: ", { instead: INSTEAD }),
2124
- password: await prompt("Registry password/token: ", {
2125
- hidden: true,
2126
- instead: INSTEAD
2127
- })
2128
- };
2129
- } };
2130
- }
2131
- /**
2132
- * The environment, then the stored login, then — at a terminal — the person
2133
- * running the command.
2134
- */
2135
- function terminalCredentials(base = storedCredentials()) {
2136
- return chainCredentials(base, asking());
2137
- }
2138
- //#endregion
2139
1824
  //#region src/deploy/index.ts
2140
1825
  /**
2141
1826
  * Deploy Module
@@ -2336,22 +2021,6 @@ function getServerHostname(endpoint) {
2336
2021
  return new URL(endpoint).hostname;
2337
2022
  }
2338
2023
  /**
2339
- * Generate image tag from stage and timestamp
2340
- */
2341
- function generateTag(stage) {
2342
- return `${stage}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}`;
2343
- }
2344
- /**
2345
- * The things this deploy creates a container for.
2346
- *
2347
- * A deploy unit is a *declaration*, not a config entry — and since that is now
2348
- * true of every app, not just the ones being deployed, this is the workspace's
2349
- * own derivation under the name the deploy phases call it by.
2350
- */
2351
- function deployUnits(manifest, workspace) {
2352
- return derivedApps(manifest, workspace);
2353
- }
2354
- /**
2355
2024
  * The variables an app cannot start without.
2356
2025
  *
2357
2026
  * The sniffer reports every key it saw in `requiredEnvVars` and says which of
@@ -2369,26 +2038,6 @@ function requiredOf(requirements) {
2369
2038
  const optional = new Set(requirements.optionalEnvVars);
2370
2039
  return requirements.requiredEnvVars.map((name) => name.endsWith("?") ? name.slice(0, -1) : name).filter((name) => !optional.has(name));
2371
2040
  }
2372
- /** Apps were asked for by name that the workspace does not have. */
2373
- var UnknownDeployApps = class extends Error {
2374
- apps;
2375
- available;
2376
- constructor(apps, available) {
2377
- super(`Unknown apps: ${apps.join(", ")}\nAvailable apps: ${available.join(", ")}`);
2378
- this.apps = apps;
2379
- this.available = available;
2380
- this.name = "UnknownDeployApps";
2381
- }
2382
- };
2383
- /** Every app asked for deploys somewhere other than Dokploy. */
2384
- var NoDeployableApps = class extends Error {
2385
- stage;
2386
- constructor(stage) {
2387
- super("No apps to deploy. All selected apps have unsupported deploy targets.");
2388
- this.stage = stage;
2389
- this.name = "NoDeployableApps";
2390
- }
2391
- };
2392
2041
  /** A backend failed, so the run stopped before deploying anything after it. */
2393
2042
  var BackendDeployFailed = class extends Error {
2394
2043
  app;
@@ -2411,23 +2060,24 @@ var MissingEnvVars = class extends Error {
2411
2060
  this.name = "MissingEnvVars";
2412
2061
  }
2413
2062
  };
2414
- /** Workspace deploys go to Dokploy; another provider was asked for. */
2415
- var DeployProviderUnsupported = class extends Error {
2416
- provider;
2417
- constructor(provider) {
2418
- super(`Workspace deployment only supports Dokploy. Got: ${provider}`);
2419
- this.provider = provider;
2420
- this.name = "DeployProviderUnsupported";
2421
- }
2422
- };
2423
2063
  /** How `resolveProject` found a project, in the journal's words. */
2424
2064
  const PROJECT_VIA = {
2425
2065
  state: "recorded",
2426
2066
  marker: "found",
2427
2067
  created: "created"
2428
2068
  };
2069
+ /** `childOutput` as `spawn` reads it, where it is not the default. */
2070
+ const CHILD_STDIO = {
2071
+ stderr: [
2072
+ "ignore",
2073
+ 2,
2074
+ 2
2075
+ ],
2076
+ ignore: "ignore"
2077
+ };
2429
2078
  /**
2430
- * Deploy every app in a workspace to Dokploy.
2079
+ * Deploy every app in a workspace to Dokploy: the engine under the built-in
2080
+ * `dokploy` target.
2431
2081
  *
2432
2082
  * Two-phase orchestration:
2433
2083
  * - PHASE 1: Deploy backend apps (with encrypted secrets)
@@ -2438,119 +2088,60 @@ const PROJECT_VIA = {
2438
2088
  * - Only GKM_MASTER_KEY is injected as Dokploy env var
2439
2089
  * - Frontend apps get public URLs baked in at build time (no secrets)
2440
2090
  *
2441
- * The engine under `deploy()` and `gkm deploy`. It never prompts and never
2442
- * exits: credentials come from `ctx.credentials`, progress goes to
2443
- * `ctx.emit` and to `output`, and every failure is thrown.
2091
+ * The run around it — the target, the apps, the lock, the phase events — is
2092
+ * `runDeploy`'s. This says what it is doing and checks what Dokploy needs.
2444
2093
  *
2445
2094
  * @internal
2446
2095
  */
2447
- async function runDeploy(source, request, ctx) {
2448
- const { stage, tag, apps: selectedApps } = request;
2449
- ctx.emit({
2450
- type: "phase.started",
2451
- phase: "validate"
2452
- });
2453
- const configured = typeof source === "function" ? await source() : source;
2454
- const manifest = await discover({
2455
- patterns: constructGlobs(configured),
2456
- cwd: configured.root
2457
- });
2458
- const units = deployUnits(manifest, configured);
2459
- const workspace = Object.keys(units).length > 0 ? {
2460
- ...configured,
2461
- apps: units
2462
- } : configured;
2463
- const identity = deployIdentity(workspace, stage);
2096
+ async function validateDokploy(phase) {
2097
+ const { workspace, stage, identity, tag: imageTag } = phase;
2098
+ const ctx = {
2099
+ emit: phase.emit,
2100
+ credentials: phase.credentials,
2101
+ signal: phase.signal,
2102
+ dryRun: phase.dryRun,
2103
+ ...phase.childOutput !== "inherit" ? { stdio: CHILD_STDIO[phase.childOutput] } : {}
2104
+ };
2464
2105
  logger.log(`\n🚀 Deploying workspace "${workspace.name}" to Dokploy...`);
2465
2106
  logger.log(` Stage: ${stage}`);
2466
- const imageTag = tag ?? generateTag(stage);
2467
2107
  logger.log(` Tag: ${imageTag}`);
2468
- const buildOrder = getAppBuildOrder(workspace);
2469
- let appsToDeployNames = buildOrder;
2470
- if (selectedApps && selectedApps.length > 0) {
2471
- const invalidApps = selectedApps.filter((name) => !workspace.apps[name]);
2472
- if (invalidApps.length > 0) throw new UnknownDeployApps(invalidApps, Object.keys(workspace.apps));
2473
- appsToDeployNames = buildOrder.filter((name) => selectedApps.includes(name));
2474
- logger.log(` Deploying apps: ${appsToDeployNames.join(", ")}`);
2475
- } else logger.log(` Deploying all apps: ${appsToDeployNames.join(", ")}`);
2476
- const skipped = [];
2477
- const skip = (app, reason) => {
2478
- skipped.push({
2479
- app,
2480
- reason
2481
- });
2482
- ctx.emit({
2483
- type: "app.skipped",
2484
- app,
2485
- reason
2486
- });
2487
- };
2488
- const dokployApps = appsToDeployNames.filter((name) => {
2489
- const target = workspace.apps[name].resolvedDeployTarget;
2490
- if (target === "sst") {
2491
- const reason = `it deploys with SST — run \`gkm build && sst deploy --stage ${stage}\``;
2492
- logger.log(` ⚠️ Skipping ${name}: ${reason}`);
2493
- skip(name, reason);
2494
- return false;
2495
- }
2496
- if (!isDeployTargetSupported(target)) {
2497
- const reason = getDeployTargetError(target, name);
2498
- logger.log(` ⚠️ Skipping ${name}: ${reason}`);
2499
- skip(name, reason);
2500
- return false;
2501
- }
2502
- return true;
2503
- });
2504
- if (dokployApps.length === 0) throw new NoDeployableApps(stage);
2505
- appsToDeployNames = dokployApps;
2506
- for (const name of appsToDeployNames) if (workspace.apps[name].type === "mobile") skip(name, MOBILE_SKIP_REASON);
2507
- ctx.emit({
2508
- type: "deploy.started",
2509
- stage,
2510
- identity: identity.key,
2511
- tag: imageTag,
2512
- apps: appsToDeployNames.filter((name) => workspace.apps[name].type !== "mobile"),
2513
- dryRun: ctx.dryRun
2514
- });
2515
- const store = await createStateStore({
2516
- config: workspace.state,
2517
- workspaceRoot: workspace.root,
2518
- workspaceName: workspace.name
2519
- });
2108
+ const askedFor = /* @__PURE__ */ new Set([...phase.apps, ...phase.skipped.map((skipped) => skipped.app)]);
2109
+ const asked = getAppBuildOrder(workspace).filter((name) => askedFor.has(name));
2110
+ logger.log(asked.length === Object.keys(workspace.apps).length ? ` Deploying all apps: ${asked.join(", ")}` : ` Deploying apps: ${asked.join(", ")}`);
2111
+ for (const { app, reason } of phase.skipped) logger.log(` ⚠️ Skipping ${app}: ${reason}`);
2112
+ const appsToDeployNames = [...phase.apps];
2113
+ for (const name of appsToDeployNames) if (workspace.apps[name].type === "mobile") phase.skip(name, MOBILE_SKIP_REASON);
2520
2114
  const run = {
2521
2115
  workspace,
2522
- manifest,
2116
+ manifest: phase.manifest,
2523
2117
  stage,
2524
2118
  imageTag,
2525
2119
  appsToDeployNames,
2526
2120
  identity,
2527
- store,
2528
- skipped,
2121
+ store: phase.state,
2122
+ skipped: phase.skipped,
2123
+ secrets: phase.secrets,
2529
2124
  ctx
2530
2125
  };
2531
- if (ctx.dryRun) return planDeploy(run);
2532
- const lock = await store.lock(stage, { operation: "deploy" });
2533
- try {
2534
- return await deployLocked(run);
2535
- } finally {
2536
- await lock.release();
2537
- }
2126
+ return {
2127
+ ...run,
2128
+ preflight: await preflight(run)
2129
+ };
2538
2130
  }
2539
2131
  /**
2540
2132
  * The stage's secrets and every app's environment requirements. A dry run
2541
2133
  * reads the secrets and generates nothing into the store.
2542
2134
  */
2543
- async function preflight({ workspace, manifest, stage, ctx }) {
2135
+ async function preflight({ workspace, manifest, stage, secrets: secretsStore, ctx }) {
2544
2136
  logger.log("\n🔐 Loading secrets and analyzing environment requirements...");
2545
- const secretsStore = await secretsStoreFor(workspace, stage, { ...ctx.home ? { home: ctx.home } : {} });
2546
- const stored = await secretsStore.read(stage);
2137
+ const stored = await secretsStore.read();
2547
2138
  if (!stored) logger.log(` ⚠️ No secrets found for stage "${stage}"; starting them`);
2548
2139
  const { secrets: stageSecrets, generated } = withGeneratedSecrets(stored ?? initStageSecrets(stage), manifest);
2549
2140
  if (generated.length > 0) {
2550
- if (ctx.dryRun) logger.log(` 🔑 Would generate for "${stage}" (${secretsStore.name}): ${generated.join(", ")}`);
2141
+ if (ctx.dryRun) logger.log(` 🔑 Would generate for "${stage}" (${secretsStore.store}): ${generated.join(", ")}`);
2551
2142
  else {
2552
- await secretsStore.write(stage, stageSecrets);
2553
- logger.log(` 🔑 Generated for "${stage}" (${secretsStore.name}): ${generated.join(", ")}`);
2143
+ await secretsStore.write(stageSecrets);
2144
+ logger.log(` 🔑 Generated for "${stage}" (${secretsStore.store}): ${generated.join(", ")}`);
2554
2145
  }
2555
2146
  }
2556
2147
  const sniffedApps = await sniffAllApps(workspace.apps, workspace.root);
@@ -2566,14 +2157,14 @@ async function preflight({ workspace, manifest, stage, ctx }) {
2566
2157
  encryptedSecrets
2567
2158
  };
2568
2159
  }
2569
- /** Everything a deploy does while it holds the stage's lock. */
2570
- async function deployLocked(run) {
2571
- const { workspace, manifest, stage, imageTag, appsToDeployNames, identity, store, ctx } = run;
2572
- const { stageSecrets, sniffedApps, encryptedSecrets } = await preflight(run);
2573
- ctx.emit({
2574
- type: "phase.finished",
2575
- phase: "validate"
2576
- });
2160
+ /**
2161
+ * The project, environment and registry, then what the manifest declares.
2162
+ * Each is looked up — by the id the stage's state recorded, else by name —
2163
+ * before it is created, so a run stopped part way is finished by the next.
2164
+ */
2165
+ async function provisionDokploy(run) {
2166
+ const { workspace, manifest, stage, appsToDeployNames, identity, store, ctx } = run;
2167
+ const { stageSecrets } = run.preflight;
2577
2168
  const changes = [];
2578
2169
  const applied = (change, via) => {
2579
2170
  changes.push(change);
@@ -2583,11 +2174,6 @@ async function deployLocked(run) {
2583
2174
  via
2584
2175
  });
2585
2176
  };
2586
- ctx.signal?.throwIfAborted();
2587
- ctx.emit({
2588
- type: "phase.started",
2589
- phase: "provision"
2590
- });
2591
2177
  const { api, endpoint } = await dokployApi(workspace, ctx);
2592
2178
  logger.log("\n📋 Loading deploy state...");
2593
2179
  const journal = await DeployJournal.open(store, stage, () => createEmptyState(stage, "", ""));
@@ -2730,7 +2316,7 @@ async function deployLocked(run) {
2730
2316
  const backupSchedule = workspace.deploy.backups.schedule ?? "0 2 * * *";
2731
2317
  const backupRetention = workspace.deploy.backups.retention ?? 30;
2732
2318
  logger.log(" Creating postgres backup schedule...");
2733
- setPostgresBackupId(state, (await api.createPostgresBackup({
2319
+ const backup = await api.createPostgresBackup({
2734
2320
  schedule: backupSchedule,
2735
2321
  prefix: `${stage}/postgres`,
2736
2322
  destinationId: backupState.destinationId,
@@ -2738,14 +2324,39 @@ async function deployLocked(run) {
2738
2324
  postgresId: backupCluster.postgresId,
2739
2325
  enabled: true,
2740
2326
  keepLatestCount: backupRetention
2741
- })).backupId);
2327
+ });
2328
+ setPostgresBackupId(state, backup.backupId);
2742
2329
  logger.log(` ✓ Postgres backup schedule created (${backupSchedule})`);
2743
2330
  } else logger.log(" ✓ Using existing postgres backup schedule");
2744
2331
  }
2745
- ctx.emit({
2746
- type: "phase.finished",
2747
- phase: "provision"
2748
- });
2332
+ run.provisioned = {
2333
+ api,
2334
+ endpoint,
2335
+ journal,
2336
+ state,
2337
+ projectId: project.projectId,
2338
+ environmentId,
2339
+ registry,
2340
+ registryId,
2341
+ declaredEnv,
2342
+ changes,
2343
+ applied
2344
+ };
2345
+ }
2346
+ /**
2347
+ * Each app's image built and pushed, its application configured and
2348
+ * deployed, and its domain attached: backends first, each failure stopping
2349
+ * the run; then sites, whose build args are the backends' public URLs.
2350
+ *
2351
+ * Building is here rather than in a `build` phase of its own because an
2352
+ * image is built beside its application — a site's build args are resolved
2353
+ * per app, against the backends released before it.
2354
+ */
2355
+ async function releaseDokploy(run) {
2356
+ const { workspace, stage, imageTag, appsToDeployNames, identity, ctx } = run;
2357
+ const { stageSecrets, sniffedApps, encryptedSecrets } = run.preflight;
2358
+ const { api, journal, state, environmentId, registry, registryId, declaredEnv, changes, applied } = run.provisioned;
2359
+ const project = { projectId: run.provisioned.projectId };
2749
2360
  const backendApps = appsToDeployNames.filter((name) => workspace.apps[name].type === "backend");
2750
2361
  const frontendApps = appsToDeployNames.filter((name) => workspace.apps[name].type === "web");
2751
2362
  const publicUrls = {};
@@ -2806,11 +2417,6 @@ async function deployLocked(run) {
2806
2417
  };
2807
2418
  const frontendUrls = [];
2808
2419
  for (const appName of frontendApps) frontendUrls.push(`https://${hostOf(workspace, appName, stage)}`);
2809
- ctx.signal?.throwIfAborted();
2810
- ctx.emit({
2811
- type: "phase.started",
2812
- phase: "release"
2813
- });
2814
2420
  if (backendApps.length > 0) {
2815
2421
  logger.log("\n📦 PHASE 1: Deploying backend applications...");
2816
2422
  for (const appName of backendApps) {
@@ -2976,15 +2582,17 @@ async function deployLocked(run) {
2976
2582
  logger.log("\n📋 Saving deploy state...");
2977
2583
  await journal.save();
2978
2584
  logger.log(" ✓ State saved");
2979
- ctx.emit({
2980
- type: "phase.finished",
2981
- phase: "release"
2982
- });
2983
- ctx.signal?.throwIfAborted();
2984
- ctx.emit({
2985
- type: "phase.started",
2986
- phase: "verify"
2987
- });
2585
+ run.released = {
2586
+ results,
2587
+ publicUrls,
2588
+ appHostnames
2589
+ };
2590
+ }
2591
+ /** DNS records for each released app, and Dokploy's validation of each domain. */
2592
+ async function verifyDokploy(run) {
2593
+ const { workspace } = run;
2594
+ const { api, endpoint, journal, state } = run.provisioned;
2595
+ const { appHostnames } = run.released;
2988
2596
  const dnsConfig = workspace.deploy.dns;
2989
2597
  if (dnsConfig && appHostnames.size > 0) {
2990
2598
  const dnsResult = await orchestrateDns(appHostnames, dnsConfig, endpoint);
@@ -3004,10 +2612,14 @@ async function deployLocked(run) {
3004
2612
  }
3005
2613
  }
3006
2614
  }
3007
- ctx.emit({
3008
- type: "phase.finished",
3009
- phase: "verify"
3010
- });
2615
+ }
2616
+ /** What the run did, printed as the summary it always ended with. */
2617
+ function dokployResult(run) {
2618
+ if (run.result) return run.result;
2619
+ const { stage, identity, imageTag } = run;
2620
+ const { projectId, environmentId, changes } = run.provisioned;
2621
+ const { results, publicUrls } = run.released;
2622
+ const project = { projectId };
3011
2623
  const successCount = results.filter((r) => r.success).length;
3012
2624
  const failedCount = results.filter((r) => !r.success).length;
3013
2625
  logger.log(`\n${"─".repeat(50)}`);
@@ -3029,7 +2641,7 @@ async function deployLocked(run) {
3029
2641
  identity: identity.key,
3030
2642
  tag: imageTag,
3031
2643
  dryRun: false,
3032
- skipped: run.skipped,
2644
+ skipped: [...run.skipped],
3033
2645
  urls: publicUrls,
3034
2646
  changes
3035
2647
  };
@@ -3150,19 +2762,9 @@ function hostOf(workspace, appName, stage) {
3150
2762
  * else: no lock, no state written, no secret generated, no Dokploy resource
3151
2763
  * created or changed, no image built or pushed.
3152
2764
  */
3153
- async function planDeploy(run) {
2765
+ async function planDokploy(run) {
3154
2766
  const { workspace, manifest, stage, imageTag, appsToDeployNames, identity } = run;
3155
2767
  const { ctx } = run;
3156
- await preflight(run);
3157
- ctx.emit({
3158
- type: "phase.finished",
3159
- phase: "validate"
3160
- });
3161
- ctx.signal?.throwIfAborted();
3162
- ctx.emit({
3163
- type: "phase.started",
3164
- phase: "plan"
3165
- });
3166
2768
  logger.log("\n🔎 Dry run: nothing will be created, changed, built or pushed.");
3167
2769
  const changes = [];
3168
2770
  const plan = (change, detail) => {
@@ -3277,11 +2879,7 @@ async function planDeploy(run) {
3277
2879
  }
3278
2880
  const creates = changes.filter((c) => c.action !== "reuse").length;
3279
2881
  logger.log(`\n✅ Dry run complete: ${creates} to create or build, ${changes.length - creates} to reuse.`);
3280
- ctx.emit({
3281
- type: "phase.finished",
3282
- phase: "plan"
3283
- });
3284
- return {
2882
+ run.result = {
3285
2883
  apps,
3286
2884
  projectId: project?.projectId ?? "",
3287
2885
  environmentId: environment?.environmentId ?? "",
@@ -3291,7 +2889,7 @@ async function planDeploy(run) {
3291
2889
  identity: identity.key,
3292
2890
  tag: imageTag,
3293
2891
  dryRun: true,
3294
- skipped: run.skipped,
2892
+ skipped: [...run.skipped],
3295
2893
  urls,
3296
2894
  changes
3297
2895
  };
@@ -3299,131 +2897,6 @@ async function planDeploy(run) {
3299
2897
  /** Why a mobile app is left out of a Dokploy deploy. */
3300
2898
  const MOBILE_SKIP_REASON = "deploys via its framework toolchain";
3301
2899
  //#endregion
3302
- //#region src/deploy/deploy.ts
3303
- /**
3304
- * `deploy()`: a deploy as a library call.
3305
- *
3306
- * `gkm deploy` could only be driven from an interactive terminal: it prompted
3307
- * for what it lacked and exited the process on failure, worked out of
3308
- * `process.cwd()`, and reported progress by printing. Here the caller says
3309
- * where the project is, hands over the credentials and a signal, and gets back
3310
- * a run — events to iterate while it goes, and a structured result at the end.
3311
- * Nothing below this asks a person anything or ends the process; `gkm deploy`
3312
- * is a thin wrapper that does both.
3313
- */
3314
- /**
3315
- * Every event a run emits, kept so that each iteration — however late it
3316
- * starts — sees the run from its first event to its last.
3317
- */
3318
- var EventLog = class {
3319
- events = [];
3320
- closed = false;
3321
- waiting = [];
3322
- push(event) {
3323
- this.events.push(event);
3324
- this.wake();
3325
- }
3326
- close() {
3327
- this.closed = true;
3328
- this.wake();
3329
- }
3330
- wake() {
3331
- const waiting = this.waiting;
3332
- this.waiting = [];
3333
- for (const resume of waiting) resume();
3334
- }
3335
- async *iterate() {
3336
- let next = 0;
3337
- while (true) if (next < this.events.length) yield this.events[next++];
3338
- else if (this.closed) return;
3339
- else await new Promise((resume) => this.waiting.push(resume));
3340
- }
3341
- };
3342
- /** `childOutput` as `spawn` reads it, where it is not the default. */
3343
- const CHILD_STDIO = {
3344
- stderr: [
3345
- "ignore",
3346
- 2,
3347
- 2
3348
- ],
3349
- ignore: "ignore"
3350
- };
3351
- function forward(logger, level, message) {
3352
- if (!logger) return;
3353
- if (level === "info") logger.info(message);
3354
- else if (level === "error" && logger.error) logger.error(message);
3355
- else logger.warn(message);
3356
- }
3357
- /**
3358
- * Deploy a project's stage.
3359
- *
3360
- * ```ts
3361
- * import { deploy } from '@geekmidas/cli/deploy';
3362
- *
3363
- * const run = deploy({ cwd: '/srv/checkouts/shop', stage: 'production' });
3364
- * for await (const event of run) {
3365
- * if (event.type === 'app.deployed') console.log(event.app, event.url);
3366
- * }
3367
- * const result = await run.result;
3368
- * ```
3369
- *
3370
- * The run starts at once; iterating it is optional, and an iteration started
3371
- * late still sees every event from the first.
3372
- */
3373
- function deploy(input) {
3374
- const log = new EventLog();
3375
- const emit = (event) => {
3376
- log.push(event);
3377
- if (event.type === "log") forward(input.logger, event.level, event.message);
3378
- };
3379
- const ctx = {
3380
- emit,
3381
- credentials: input.credentials ?? storedCredentials({ home: input.home ?? gkmHome() }),
3382
- dryRun: input.dryRun ?? false,
3383
- home: input.home ?? gkmHome(),
3384
- ...input.signal ? { signal: input.signal } : {},
3385
- ...input.childOutput && input.childOutput !== "inherit" ? { stdio: CHILD_STDIO[input.childOutput] } : {}
3386
- };
3387
- const result = withOutput((level, message) => emit({
3388
- type: "log",
3389
- level,
3390
- message
3391
- }), async () => {
3392
- try {
3393
- input.signal?.throwIfAborted();
3394
- const deployed = await runDeploy(() => load(input), {
3395
- stage: input.stage,
3396
- ...input.tag ? { tag: input.tag } : {},
3397
- ...input.apps ? { apps: input.apps } : {}
3398
- }, ctx);
3399
- emit({
3400
- type: "deploy.finished",
3401
- result: deployed
3402
- });
3403
- return deployed;
3404
- } catch (error) {
3405
- emit({
3406
- type: "deploy.failed",
3407
- error: eventError(error)
3408
- });
3409
- throw error;
3410
- } finally {
3411
- log.close();
3412
- }
3413
- });
3414
- result.catch(() => {});
3415
- return {
3416
- result,
3417
- [Symbol.asyncIterator]: () => log.iterate()
3418
- };
3419
- }
3420
- /** The workspace at `input.cwd`, refusing a stage it does not deploy. */
3421
- async function load(input) {
3422
- const { workspace } = await loadWorkspaceConfig(resolve(input.cwd));
3423
- assertDeployedStage(workspace.stages, input.stage);
3424
- return workspace;
3425
- }
3426
- //#endregion
3427
- export { NoDeployableApps as a, RegistryAmbiguous as c, ProjectNotOwned as d, MissingCredential as f, MissingEnvVars as i, RegistryNotConfigured as l, storedCredentials as m, BackendDeployFailed as n, UnknownDeployApps as o, chainCredentials as p, DeployProviderUnsupported as r, terminalCredentials as s, deploy as t, RegistryNotFound as u };
2900
+ export { provisionDokploy as a, verifyDokploy as c, RegistryNotFound as d, ProjectNotOwned as f, planDokploy as i, RegistryAmbiguous as l, MissingEnvVars as n, releaseDokploy as o, dokployResult as r, validateDokploy as s, BackendDeployFailed as t, RegistryNotConfigured as u };
3428
2901
 
3429
- //# sourceMappingURL=deploy-D6Q09OkA.mjs.map
2902
+ //# sourceMappingURL=deploy-B7jvUORo.mjs.map