@geekmidas/cli 1.10.29 → 1.10.31

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 (138) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/{CachedStateProvider-37pG1HBx.cjs → CachedStateProvider-3couMAQk.cjs} +1 -1
  3. package/dist/CachedStateProvider-C4QqvlPE.mjs +3 -0
  4. package/dist/{CachedStateProvider-C8A-cCm5.mjs → CachedStateProvider-CQr31ups.mjs} +1 -1
  5. package/dist/{CachedStateProvider-C8A-cCm5.mjs.map → CachedStateProvider-CQr31ups.mjs.map} +1 -1
  6. package/dist/{CachedStateProvider-CxsXOKkg.cjs → CachedStateProvider-Cyn17x3x.cjs} +1 -1
  7. package/dist/{CachedStateProvider-CxsXOKkg.cjs.map → CachedStateProvider-Cyn17x3x.cjs.map} +1 -1
  8. package/dist/{HostingerProvider-5KYmwoK2.cjs → HostingerProvider-C5oLa7N7.cjs} +1 -1
  9. package/dist/{HostingerProvider-5KYmwoK2.cjs.map → HostingerProvider-C5oLa7N7.cjs.map} +1 -1
  10. package/dist/{HostingerProvider-ANWchdiK.mjs → HostingerProvider-YvCg3Mus.mjs} +1 -1
  11. package/dist/{HostingerProvider-ANWchdiK.mjs.map → HostingerProvider-YvCg3Mus.mjs.map} +1 -1
  12. package/dist/{LocalStateProvider-Dp0KkRcw.mjs → LocalStateProvider-BciOhGR0.mjs} +1 -1
  13. package/dist/{LocalStateProvider-Dp0KkRcw.mjs.map → LocalStateProvider-BciOhGR0.mjs.map} +1 -1
  14. package/dist/{LocalStateProvider-CLifRC0Y.cjs → LocalStateProvider-DI6n11UM.cjs} +1 -1
  15. package/dist/{LocalStateProvider-CLifRC0Y.cjs.map → LocalStateProvider-DI6n11UM.cjs.map} +1 -1
  16. package/dist/{Route53Provider-QoPgcXxn.mjs → Route53Provider-CYlDOrYO.mjs} +1 -1
  17. package/dist/{Route53Provider-QoPgcXxn.mjs.map → Route53Provider-CYlDOrYO.mjs.map} +1 -1
  18. package/dist/{Route53Provider-owQQ4pn6.cjs → Route53Provider-DISZ6E8f.cjs} +1 -1
  19. package/dist/{Route53Provider-owQQ4pn6.cjs.map → Route53Provider-DISZ6E8f.cjs.map} +1 -1
  20. package/dist/{SSMStateProvider-CT8tjl9o.cjs → SSMStateProvider-BljH5efc.cjs} +1 -1
  21. package/dist/{SSMStateProvider-CT8tjl9o.cjs.map → SSMStateProvider-BljH5efc.cjs.map} +1 -1
  22. package/dist/{SSMStateProvider-CksOTB8M.mjs → SSMStateProvider-DXT1dIdI.mjs} +1 -1
  23. package/dist/{SSMStateProvider-CksOTB8M.mjs.map → SSMStateProvider-DXT1dIdI.mjs.map} +1 -1
  24. package/dist/{backup-provisioner-BEXoHTuC.mjs → backup-provisioner-CCUcj28C.mjs} +1 -1
  25. package/dist/{backup-provisioner-BEXoHTuC.mjs.map → backup-provisioner-CCUcj28C.mjs.map} +1 -1
  26. package/dist/{backup-provisioner-C4noe75O.cjs → backup-provisioner-CpirEvO1.cjs} +1 -1
  27. package/dist/{backup-provisioner-C4noe75O.cjs.map → backup-provisioner-CpirEvO1.cjs.map} +1 -1
  28. package/dist/{bundler-BG6P249p.cjs → bundler-CLOenWgi.cjs} +2 -2
  29. package/dist/{bundler-BG6P249p.cjs.map → bundler-CLOenWgi.cjs.map} +1 -1
  30. package/dist/{bundler-c6QvGUBM.mjs → bundler-E5VcXsPH.mjs} +2 -2
  31. package/dist/{bundler-c6QvGUBM.mjs.map → bundler-E5VcXsPH.mjs.map} +1 -1
  32. package/dist/client-generator-CUVVtAOo.mjs +23 -0
  33. package/dist/client-generator-CUVVtAOo.mjs.map +1 -0
  34. package/dist/client-generator-D-T4ypQo.cjs +35 -0
  35. package/dist/client-generator-D-T4ypQo.cjs.map +1 -0
  36. package/dist/{config-jsRYHOHU.mjs → config-B62g483e.mjs} +2 -2
  37. package/dist/{config-jsRYHOHU.mjs.map → config-B62g483e.mjs.map} +1 -1
  38. package/dist/{config-D3ORuiUs.cjs → config-Cuo8vFsp.cjs} +2 -2
  39. package/dist/{config-D3ORuiUs.cjs.map → config-Cuo8vFsp.cjs.map} +1 -1
  40. package/dist/config.cjs +2 -2
  41. package/dist/config.d.cts +1 -1
  42. package/dist/config.d.mts +2 -2
  43. package/dist/config.mjs +2 -2
  44. package/dist/deploy/sniffer-worker.cjs +2 -0
  45. package/dist/deploy/sniffer-worker.cjs.map +1 -1
  46. package/dist/deploy/sniffer-worker.mjs +2 -0
  47. package/dist/deploy/sniffer-worker.mjs.map +1 -1
  48. package/dist/dokploy-api-BPYkG-ZZ.cjs +3 -0
  49. package/dist/dokploy-api-BiSzWM4v.mjs +3 -0
  50. package/dist/{dokploy-api-Dvyq-LsM.cjs → dokploy-api-CqOIKHme.cjs} +1 -1
  51. package/dist/{dokploy-api-Dvyq-LsM.cjs.map → dokploy-api-CqOIKHme.cjs.map} +1 -1
  52. package/dist/{dokploy-api-BIT0683o.mjs → dokploy-api-sfZFlWuE.mjs} +1 -1
  53. package/dist/{dokploy-api-BIT0683o.mjs.map → dokploy-api-sfZFlWuE.mjs.map} +1 -1
  54. package/dist/{encryption-CipsS0KW.cjs → encryption-BVS7Vmzs.cjs} +1 -1
  55. package/dist/encryption-Bd_m4q3g.mjs +3 -0
  56. package/dist/{encryption-DSkIlEZ6.mjs → encryption-CO5Q4Bhf.mjs} +1 -1
  57. package/dist/{encryption-DSkIlEZ6.mjs.map → encryption-CO5Q4Bhf.mjs.map} +1 -1
  58. package/dist/{encryption-DgKS-Dv9.cjs → encryption-MfXAiFTm.cjs} +1 -1
  59. package/dist/{encryption-DgKS-Dv9.cjs.map → encryption-MfXAiFTm.cjs.map} +1 -1
  60. package/dist/{index-CY-ieuRp.d.mts → index-C-_rW4KF.d.mts} +3 -33
  61. package/dist/index-C-_rW4KF.d.mts.map +1 -0
  62. package/dist/{index-BkibYzso.d.cts → index-C3t5VL4R.d.cts} +2 -32
  63. package/dist/index-C3t5VL4R.d.cts.map +1 -0
  64. package/dist/index.cjs +102 -380
  65. package/dist/index.cjs.map +1 -1
  66. package/dist/index.mjs +78 -356
  67. package/dist/index.mjs.map +1 -1
  68. package/dist/{openapi-CQCoLuzh.mjs → openapi-DHq5r17U.mjs} +7 -42
  69. package/dist/openapi-DHq5r17U.mjs.map +1 -0
  70. package/dist/{openapi-react-query-C4UdILaI.mjs → openapi-react-query-COpH7Mmz.mjs} +1 -1
  71. package/dist/{openapi-react-query-C4UdILaI.mjs.map → openapi-react-query-COpH7Mmz.mjs.map} +1 -1
  72. package/dist/{openapi-react-query-DYbBq-WJ.cjs → openapi-react-query-CxyQTTdF.cjs} +1 -1
  73. package/dist/{openapi-react-query-DYbBq-WJ.cjs.map → openapi-react-query-CxyQTTdF.cjs.map} +1 -1
  74. package/dist/openapi-react-query.cjs +1 -1
  75. package/dist/openapi-react-query.mjs +1 -1
  76. package/dist/{openapi-CBU4TEi-.cjs → openapi-w-_smBTO.cjs} +7 -54
  77. package/dist/openapi-w-_smBTO.cjs.map +1 -0
  78. package/dist/openapi.cjs +4 -3
  79. package/dist/openapi.d.mts +1 -1
  80. package/dist/openapi.mjs +4 -3
  81. package/dist/{reconcile-CZtzdrnc.cjs → reconcile-C8KIy4Uy.cjs} +1 -1
  82. package/dist/{reconcile-CZtzdrnc.cjs.map → reconcile-C8KIy4Uy.cjs.map} +1 -1
  83. package/dist/{reconcile-DAAKa0YR.mjs → reconcile-D423q2QW.mjs} +1 -1
  84. package/dist/{reconcile-DAAKa0YR.mjs.map → reconcile-D423q2QW.mjs.map} +1 -1
  85. package/dist/sniffer-BqSVVrWA.mjs +356 -0
  86. package/dist/sniffer-BqSVVrWA.mjs.map +1 -0
  87. package/dist/sniffer-CBhzByiY.cjs +386 -0
  88. package/dist/sniffer-CBhzByiY.cjs.map +1 -0
  89. package/dist/sniffer-Cpq_cbyz.mjs +4 -0
  90. package/dist/sniffer-eZ13G10M.cjs +4 -0
  91. package/dist/sync-B2CN_KS5.cjs +4 -0
  92. package/dist/{sync-DGXXSk2v.cjs → sync-BWY6yoUG.cjs} +1 -1
  93. package/dist/{sync-DGXXSk2v.cjs.map → sync-BWY6yoUG.cjs.map} +1 -1
  94. package/dist/{sync-D_NowTkZ.mjs → sync-Dc-QA4Mx.mjs} +1 -1
  95. package/dist/{sync-D_NowTkZ.mjs.map → sync-Dc-QA4Mx.mjs.map} +1 -1
  96. package/dist/{sync-COnAugP-.mjs → sync-fzT5WX_y.mjs} +1 -1
  97. package/dist/{types-OszPdw9m.d.mts → types-BqAbYt5a.d.mts} +1 -1
  98. package/dist/{types-OszPdw9m.d.mts.map → types-BqAbYt5a.d.mts.map} +1 -1
  99. package/dist/workspace/index.cjs +1 -1
  100. package/dist/workspace/index.d.cts +2 -2
  101. package/dist/workspace/index.d.mts +3 -3
  102. package/dist/workspace/index.mjs +1 -1
  103. package/dist/{workspace-D4z4A4cq.mjs → workspace-Bi4X7Yzy.mjs} +1 -6
  104. package/dist/{workspace-D4z4A4cq.mjs.map → workspace-Bi4X7Yzy.mjs.map} +1 -1
  105. package/dist/{workspace-4SP3Gx4Y.cjs → workspace-CGYykWfn.cjs} +1 -6
  106. package/dist/{workspace-4SP3Gx4Y.cjs.map → workspace-CGYykWfn.cjs.map} +1 -1
  107. package/package.json +3 -3
  108. package/src/__tests__/openapi.spec.ts +0 -315
  109. package/src/build/__tests__/manifests.spec.ts +66 -0
  110. package/src/build/index.ts +54 -1
  111. package/src/deploy/__tests__/__fixtures__/env-parsers/optional-env-parser.ts +21 -0
  112. package/src/deploy/__tests__/sniffer.spec.ts +123 -0
  113. package/src/deploy/sniffer-worker.ts +2 -1
  114. package/src/deploy/sniffer.ts +86 -12
  115. package/src/docker/compose.ts +2 -0
  116. package/src/generators/EndpointGenerator.ts +1 -1
  117. package/src/index.ts +8 -0
  118. package/src/init/generators/monorepo.ts +15 -1
  119. package/src/init/generators/package.ts +2 -0
  120. package/src/init/index.ts +2 -4
  121. package/src/init/templates/index.ts +5 -0
  122. package/src/init/versions.ts +1 -1
  123. package/src/openapi.ts +1 -35
  124. package/src/types.ts +7 -0
  125. package/src/workspace/__tests__/client-generator.spec.ts +1 -485
  126. package/src/workspace/client-generator.ts +1 -145
  127. package/src/workspace/index.ts +0 -1
  128. package/src/workspace/schema.ts +0 -9
  129. package/src/workspace/types.ts +0 -29
  130. package/dist/CachedStateProvider-CC0DyO09.mjs +0 -3
  131. package/dist/dokploy-api-BOx71j6F.cjs +0 -3
  132. package/dist/dokploy-api-BZGk-lkD.mjs +0 -3
  133. package/dist/encryption-Db2zvGqM.mjs +0 -3
  134. package/dist/index-BkibYzso.d.cts.map +0 -1
  135. package/dist/index-CY-ieuRp.d.mts.map +0 -1
  136. package/dist/openapi-CBU4TEi-.cjs.map +0 -1
  137. package/dist/openapi-CQCoLuzh.mjs.map +0 -1
  138. package/dist/sync-D1Pa30oV.cjs +0 -4
@@ -0,0 +1,386 @@
1
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
+ const require_client_generator = require('./client-generator-D-T4ypQo.cjs');
3
+ const node_fs = require_chunk.__toESM(require("node:fs"));
4
+ const node_path = require_chunk.__toESM(require("node:path"));
5
+ const node_child_process = require_chunk.__toESM(require("node:child_process"));
6
+ const node_module = require_chunk.__toESM(require("node:module"));
7
+ const node_url = require_chunk.__toESM(require("node:url"));
8
+
9
+ //#region src/deploy/sniffer.ts
10
+ const __filename$1 = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
11
+ const __dirname$1 = (0, node_path.dirname)(__filename$1);
12
+ /**
13
+ * Resolve the tsx package path from the CLI package's dependencies.
14
+ * This ensures tsx is available regardless of whether the target project has it installed.
15
+ */
16
+ function resolveTsxPath() {
17
+ const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
18
+ return require$1.resolve("tsx");
19
+ }
20
+ /**
21
+ * Resolve the path to a sniffer helper file.
22
+ * Handles both dev (.ts with tsx) and production (.mjs from dist).
23
+ *
24
+ * In production: sniffer.ts is bundled into dist/index.mjs, but sniffer helper
25
+ * files are output to dist/deploy/ as standalone modules for subprocess loading.
26
+ *
27
+ * In development: All files are in src/deploy/ and loaded via tsx.
28
+ */
29
+ function resolveSnifferFile(baseName) {
30
+ const deployMjsPath = (0, node_path.resolve)(__dirname$1, "deploy", `${baseName}.mjs`);
31
+ if ((0, node_fs.existsSync)(deployMjsPath)) return deployMjsPath;
32
+ const mjsPath = (0, node_path.resolve)(__dirname$1, `${baseName}.mjs`);
33
+ if ((0, node_fs.existsSync)(mjsPath)) return mjsPath;
34
+ const tsPath = (0, node_path.resolve)(__dirname$1, `${baseName}.ts`);
35
+ if ((0, node_fs.existsSync)(tsPath)) return tsPath;
36
+ return tsPath;
37
+ }
38
+ /**
39
+ * Get required environment variables for an app.
40
+ *
41
+ * Detection strategy (in order):
42
+ * 1. Frontend apps: Returns empty (no server secrets)
43
+ * 2. Apps with `requiredEnv`: Uses explicit list from config
44
+ * 3. Entry apps: Imports entry file in subprocess to capture config.parse() calls
45
+ * 4. Route-based apps: Loads route files and calls getEnvironment() on each construct
46
+ * 5. Apps with `envParser` (no routes): Runs SnifferEnvironmentParser to detect usage
47
+ * 6. Apps with neither: Returns empty
48
+ *
49
+ * This function handles "fire and forget" async operations gracefully,
50
+ * capturing errors and unhandled rejections without failing the build.
51
+ *
52
+ * @param app - The normalized app configuration
53
+ * @param appName - The name of the app
54
+ * @param workspacePath - Absolute path to the workspace root
55
+ * @param options - Optional configuration for sniffing behavior
56
+ * @returns The sniffed environment with required variables
57
+ */
58
+ async function sniffAppEnvironment(app, appName, workspacePath, options = {}) {
59
+ const { logWarnings = true, markOptional = false } = options;
60
+ if (app.type === "frontend") {
61
+ const depVars = (app.dependencies ?? []).map((dep) => `NEXT_PUBLIC_${dep.toUpperCase()}_URL`);
62
+ if (app.config) {
63
+ const sniffedVars = [];
64
+ const sniffedOptional = [];
65
+ const configPaths = [];
66
+ if (app.config.client) configPaths.push(app.config.client);
67
+ if (app.config.server) configPaths.push(app.config.server);
68
+ for (const configPath of configPaths) {
69
+ const result = await sniffEntryFile(configPath, app.path, workspacePath);
70
+ if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Config file "${configPath}" threw error during sniffing (env vars still captured): ${result.error.message}`);
71
+ sniffedVars.push(...result.envVars);
72
+ sniffedOptional.push(...result.optionalEnvVars);
73
+ }
74
+ const optionalEnvVars = [...new Set(sniffedOptional)];
75
+ const allVars = applyMarkOptional([...new Set([...depVars, ...sniffedVars])], optionalEnvVars, markOptional);
76
+ return {
77
+ appName,
78
+ requiredEnvVars: allVars,
79
+ optionalEnvVars
80
+ };
81
+ }
82
+ return {
83
+ appName,
84
+ requiredEnvVars: depVars,
85
+ optionalEnvVars: []
86
+ };
87
+ }
88
+ if (app.entry) {
89
+ const result = await sniffEntryFile(app.entry, app.path, workspacePath);
90
+ if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Entry file threw error during sniffing (env vars still captured): ${result.error.message}`);
91
+ return {
92
+ appName,
93
+ requiredEnvVars: applyMarkOptional(result.envVars, result.optionalEnvVars, markOptional),
94
+ optionalEnvVars: result.optionalEnvVars
95
+ };
96
+ }
97
+ if (app.routes) {
98
+ const result = await sniffRouteFiles(require_client_generator.normalizeRoutes(app.routes), app.path, workspacePath);
99
+ if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Route sniffing threw error (env vars still captured): ${result.error.message}`);
100
+ return {
101
+ appName,
102
+ requiredEnvVars: applyMarkOptional(result.envVars, result.optionalEnvVars, markOptional),
103
+ optionalEnvVars: result.optionalEnvVars
104
+ };
105
+ }
106
+ if (app.envParser) {
107
+ const result = await sniffEnvParser(app.envParser, app.path, workspacePath);
108
+ if (logWarnings) {
109
+ if (result.error) console.warn(`[sniffer] ${appName}: envParser threw error during sniffing (env vars still captured): ${result.error.message}`);
110
+ if (result.unhandledRejections.length > 0) console.warn(`[sniffer] ${appName}: Fire-and-forget rejections during sniffing (suppressed): ${result.unhandledRejections.map((e) => e.message).join(", ")}`);
111
+ }
112
+ return {
113
+ appName,
114
+ requiredEnvVars: applyMarkOptional(result.envVars, result.optionalEnvVars, markOptional),
115
+ optionalEnvVars: result.optionalEnvVars
116
+ };
117
+ }
118
+ return {
119
+ appName,
120
+ requiredEnvVars: [],
121
+ optionalEnvVars: []
122
+ };
123
+ }
124
+ /**
125
+ * Apply the `?` suffix to optional variables in an env var list.
126
+ * Only modifies the list when `markOptional` is true and there are optional vars.
127
+ */
128
+ function applyMarkOptional(envVars, optionalEnvVars, markOptional) {
129
+ if (!markOptional || optionalEnvVars.length === 0) return envVars;
130
+ const optionalSet = new Set(optionalEnvVars);
131
+ return envVars.map((v) => optionalSet.has(v) ? `${v}?` : v);
132
+ }
133
+ /**
134
+ * Sniff an entry file by importing it in a subprocess.
135
+ *
136
+ * Entry apps call `config.parse()` at module load time. To capture which
137
+ * env vars are accessed, we:
138
+ * 1. Spawn a subprocess with a module loader hook
139
+ * 2. The loader intercepts `@geekmidas/envkit` and replaces EnvironmentParser
140
+ * with SnifferEnvironmentParser
141
+ * 3. Import the entry file (triggers config.parse())
142
+ * 4. Capture and return the accessed env var names
143
+ *
144
+ * This approach provides process isolation - each app is sniffed in its own
145
+ * subprocess, preventing module cache pollution.
146
+ *
147
+ * @param entryPath - Relative path to the entry file (e.g., './src/index.ts')
148
+ * @param appPath - The app's path relative to workspace (e.g., 'apps/auth')
149
+ * @param workspacePath - Absolute path to workspace root
150
+ * @returns EntrySniffResult with env vars and optional error
151
+ */
152
+ async function sniffEntryFile(entryPath, appPath, workspacePath) {
153
+ const fullEntryPath = (0, node_path.resolve)(workspacePath, appPath, entryPath);
154
+ const loaderPath = resolveSnifferFile("sniffer-loader");
155
+ const workerPath = resolveSnifferFile("sniffer-worker");
156
+ return new Promise((resolvePromise) => {
157
+ const child = (0, node_child_process.spawn)("node", [
158
+ "--import",
159
+ loaderPath,
160
+ workerPath,
161
+ fullEntryPath
162
+ ], {
163
+ cwd: (0, node_path.resolve)(workspacePath, appPath),
164
+ stdio: [
165
+ "ignore",
166
+ "pipe",
167
+ "pipe"
168
+ ],
169
+ env: {
170
+ ...process.env,
171
+ NODE_OPTIONS: "--import=tsx"
172
+ }
173
+ });
174
+ let stdout = "";
175
+ let stderr = "";
176
+ child.stdout.on("data", (data) => {
177
+ stdout += data.toString();
178
+ });
179
+ child.stderr.on("data", (data) => {
180
+ stderr += data.toString();
181
+ });
182
+ child.on("close", (code) => {
183
+ try {
184
+ const jsonMatch = stdout.match(/\{[^{}]*"envVars"[^{}]*\}[^{]*$/);
185
+ if (jsonMatch) {
186
+ const result = JSON.parse(jsonMatch[0]);
187
+ resolvePromise({
188
+ envVars: result.envVars || [],
189
+ optionalEnvVars: result.optionalEnvVars || [],
190
+ error: result.error ? new Error(result.error) : void 0
191
+ });
192
+ return;
193
+ }
194
+ } catch {}
195
+ resolvePromise({
196
+ envVars: [],
197
+ optionalEnvVars: [],
198
+ error: new Error(`Failed to sniff entry file (exit code ${code}): ${stderr || stdout || "No output"}`)
199
+ });
200
+ });
201
+ child.on("error", (err) => {
202
+ resolvePromise({
203
+ envVars: [],
204
+ optionalEnvVars: [],
205
+ error: err
206
+ });
207
+ });
208
+ });
209
+ }
210
+ /**
211
+ * Sniff route files by loading constructs and calling getEnvironment().
212
+ *
213
+ * Route-based apps have endpoints, functions, crons, and subscribers that
214
+ * use services. Each service's register() method accesses environment variables.
215
+ *
216
+ * This runs in a subprocess with tsx loader to properly handle TypeScript
217
+ * compilation and path alias resolution (e.g., `src/...` imports).
218
+ *
219
+ * @param routes - Glob pattern(s) for route files
220
+ * @param appPath - The app's path relative to workspace (e.g., 'apps/api')
221
+ * @param workspacePath - Absolute path to workspace root
222
+ * @returns EntrySniffResult with env vars and optional error
223
+ */
224
+ async function sniffRouteFiles(routes, appPath, workspacePath) {
225
+ const fullAppPath = (0, node_path.resolve)(workspacePath, appPath);
226
+ const workerPath = resolveSnifferFile("sniffer-routes-worker");
227
+ const tsxPath = resolveTsxPath();
228
+ const routesArray = Array.isArray(routes) ? routes : [routes];
229
+ const pattern = routesArray[0];
230
+ if (!pattern) return {
231
+ envVars: [],
232
+ optionalEnvVars: [],
233
+ error: new Error("No route patterns provided")
234
+ };
235
+ return new Promise((resolvePromise) => {
236
+ const child = (0, node_child_process.spawn)("node", [
237
+ "--import",
238
+ tsxPath,
239
+ workerPath,
240
+ fullAppPath,
241
+ pattern
242
+ ], {
243
+ cwd: fullAppPath,
244
+ stdio: [
245
+ "ignore",
246
+ "pipe",
247
+ "pipe"
248
+ ],
249
+ env: { ...process.env }
250
+ });
251
+ let stdout = "";
252
+ let stderr = "";
253
+ child.stdout.on("data", (data) => {
254
+ stdout += data.toString();
255
+ });
256
+ child.stderr.on("data", (data) => {
257
+ stderr += data.toString();
258
+ });
259
+ child.on("close", (code) => {
260
+ if (stderr) stderr.split("\n").filter((line) => line.trim()).forEach((line) => console.warn(line));
261
+ try {
262
+ const jsonMatch = stdout.match(/\{[^{}]*"envVars"[^{}]*\}[^{]*$/);
263
+ if (jsonMatch) {
264
+ const result = JSON.parse(jsonMatch[0]);
265
+ resolvePromise({
266
+ envVars: result.envVars || [],
267
+ optionalEnvVars: result.optionalEnvVars || [],
268
+ error: result.error ? new Error(result.error) : void 0
269
+ });
270
+ return;
271
+ }
272
+ } catch {}
273
+ resolvePromise({
274
+ envVars: [],
275
+ optionalEnvVars: [],
276
+ error: new Error(`Failed to sniff route files (exit code ${code}): ${stderr || stdout || "No output"}`)
277
+ });
278
+ });
279
+ child.on("error", (err) => {
280
+ resolvePromise({
281
+ envVars: [],
282
+ optionalEnvVars: [],
283
+ error: err
284
+ });
285
+ });
286
+ });
287
+ }
288
+ /**
289
+ * Run the SnifferEnvironmentParser on an envParser module to detect
290
+ * which environment variables it accesses.
291
+ *
292
+ * This function handles "fire and forget" async operations by using
293
+ * the shared sniffWithFireAndForget utility from @geekmidas/envkit.
294
+ *
295
+ * @param envParserPath - The envParser config (e.g., './src/config/env#envParser')
296
+ * @param appPath - The app's path relative to workspace
297
+ * @param workspacePath - Absolute path to workspace root
298
+ * @returns SniffResult with env vars and any errors encountered
299
+ */
300
+ async function sniffEnvParser(envParserPath, appPath, workspacePath) {
301
+ const [modulePath, exportName = "default"] = envParserPath.split("#");
302
+ if (!modulePath) return {
303
+ envVars: [],
304
+ optionalEnvVars: [],
305
+ unhandledRejections: []
306
+ };
307
+ const fullPath = (0, node_path.resolve)(workspacePath, appPath, modulePath);
308
+ let SnifferEnvironmentParser;
309
+ let sniffWithFireAndForget;
310
+ try {
311
+ const envkitModule = await import("@geekmidas/envkit/sniffer");
312
+ SnifferEnvironmentParser = envkitModule.SnifferEnvironmentParser;
313
+ sniffWithFireAndForget = envkitModule.sniffWithFireAndForget;
314
+ } catch (error) {
315
+ const message = error instanceof Error ? error.message : String(error);
316
+ console.warn(`[sniffer] Failed to import SnifferEnvironmentParser: ${message}`);
317
+ return {
318
+ envVars: [],
319
+ optionalEnvVars: [],
320
+ unhandledRejections: []
321
+ };
322
+ }
323
+ const sniffer = new SnifferEnvironmentParser();
324
+ return sniffWithFireAndForget(sniffer, async () => {
325
+ const moduleUrl = (0, node_url.pathToFileURL)(fullPath).href;
326
+ const module$1 = await import(moduleUrl);
327
+ const envParser = module$1[exportName];
328
+ if (typeof envParser !== "function") {
329
+ console.warn(`[sniffer] Export "${exportName}" from "${modulePath}" is not a function`);
330
+ return;
331
+ }
332
+ const result = envParser(sniffer);
333
+ if (result && typeof result.parse === "function") try {
334
+ result.parse();
335
+ } catch {}
336
+ });
337
+ }
338
+ /**
339
+ * Sniff environment requirements for multiple apps.
340
+ *
341
+ * @param apps - Map of app name to app config
342
+ * @param workspacePath - Absolute path to workspace root
343
+ * @param options - Optional configuration for sniffing behavior
344
+ * @returns Map of app name to sniffed environment
345
+ */
346
+ async function sniffAllApps(apps, workspacePath, options = {}) {
347
+ const results = /* @__PURE__ */ new Map();
348
+ for (const [appName, app] of Object.entries(apps)) {
349
+ const sniffed = await sniffAppEnvironment(app, appName, workspacePath, options);
350
+ results.set(appName, sniffed);
351
+ }
352
+ return results;
353
+ }
354
+
355
+ //#endregion
356
+ Object.defineProperty(exports, 'sniffAllApps', {
357
+ enumerable: true,
358
+ get: function () {
359
+ return sniffAllApps;
360
+ }
361
+ });
362
+ Object.defineProperty(exports, 'sniffAppEnvironment', {
363
+ enumerable: true,
364
+ get: function () {
365
+ return sniffAppEnvironment;
366
+ }
367
+ });
368
+ Object.defineProperty(exports, 'sniffEntryFile', {
369
+ enumerable: true,
370
+ get: function () {
371
+ return sniffEntryFile;
372
+ }
373
+ });
374
+ Object.defineProperty(exports, 'sniffEnvParser', {
375
+ enumerable: true,
376
+ get: function () {
377
+ return sniffEnvParser;
378
+ }
379
+ });
380
+ Object.defineProperty(exports, 'sniffRouteFiles', {
381
+ enumerable: true,
382
+ get: function () {
383
+ return sniffRouteFiles;
384
+ }
385
+ });
386
+ //# sourceMappingURL=sniffer-CBhzByiY.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sniffer-CBhzByiY.cjs","names":["__filename","__dirname","require","baseName: string","app: NormalizedAppConfig","appName: string","workspacePath: string","options: SniffAppOptions","sniffedVars: string[]","sniffedOptional: string[]","configPaths: string[]","envVars: string[]","optionalEnvVars: string[]","markOptional: boolean","entryPath: string","appPath: string","routes: string | string[]","envParserPath: string","SnifferEnvironmentParser: any","sniffWithFireAndForget: any","module","apps: Record<string, NormalizedAppConfig>"],"sources":["../src/deploy/sniffer.ts"],"sourcesContent":["import { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport type { SniffResult } from '@geekmidas/envkit/sniffer';\nimport { normalizeRoutes } from '../workspace/client-generator.js';\nimport type { NormalizedAppConfig } from '../workspace/types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Resolve the tsx package path from the CLI package's dependencies.\n * This ensures tsx is available regardless of whether the target project has it installed.\n */\nfunction resolveTsxPath(): string {\n\tconst require = createRequire(import.meta.url);\n\treturn require.resolve('tsx');\n}\n\n/**\n * Resolve the path to a sniffer helper file.\n * Handles both dev (.ts with tsx) and production (.mjs from dist).\n *\n * In production: sniffer.ts is bundled into dist/index.mjs, but sniffer helper\n * files are output to dist/deploy/ as standalone modules for subprocess loading.\n *\n * In development: All files are in src/deploy/ and loaded via tsx.\n */\nfunction resolveSnifferFile(baseName: string): string {\n\t// Try deploy/ subdirectory first (production: bundled code is at dist/index.mjs,\n\t// but sniffer files are at dist/deploy/)\n\tconst deployMjsPath = resolve(__dirname, 'deploy', `${baseName}.mjs`);\n\tif (existsSync(deployMjsPath)) {\n\t\treturn deployMjsPath;\n\t}\n\n\t// Try same directory .mjs (production: if running from dist/deploy/ directly)\n\tconst mjsPath = resolve(__dirname, `${baseName}.mjs`);\n\tif (existsSync(mjsPath)) {\n\t\treturn mjsPath;\n\t}\n\n\t// Try same directory .ts (development with tsx: all files in src/deploy/)\n\tconst tsPath = resolve(__dirname, `${baseName}.ts`);\n\tif (existsSync(tsPath)) {\n\t\treturn tsPath;\n\t}\n\n\t// Fallback to .ts (will error if neither exists)\n\treturn tsPath;\n}\n\n// Re-export SniffResult for consumers\nexport type { SniffResult } from '@geekmidas/envkit/sniffer';\n\n/**\n * Result of sniffing an app's environment requirements.\n */\nexport interface SniffedEnvironment {\n\tappName: string;\n\t/**\n\t * All required environment variable names.\n\t * When `SniffAppOptions.markOptional` is true, optional variables are\n\t * suffixed with `?` (e.g. `PORT?`).\n\t */\n\trequiredEnvVars: string[];\n\t/**\n\t * Subset of variables that are optional (accessed via `.optional()` or\n\t * `.default()`). Always populated regardless of `markOptional`.\n\t */\n\toptionalEnvVars: string[];\n}\n\n/**\n * Options for sniffing an app's environment.\n */\nexport interface SniffAppOptions {\n\t/** Whether to log warnings for errors encountered during sniffing. Defaults to true. */\n\tlogWarnings?: boolean;\n\t/**\n\t * When true, optional variables (those with `.optional()` or `.default()`)\n\t * are suffixed with `?` in `requiredEnvVars` (e.g. `PORT?`).\n\t * Defaults to false.\n\t */\n\tmarkOptional?: boolean;\n}\n\n/**\n * Get required environment variables for an app.\n *\n * Detection strategy (in order):\n * 1. Frontend apps: Returns empty (no server secrets)\n * 2. Apps with `requiredEnv`: Uses explicit list from config\n * 3. Entry apps: Imports entry file in subprocess to capture config.parse() calls\n * 4. Route-based apps: Loads route files and calls getEnvironment() on each construct\n * 5. Apps with `envParser` (no routes): Runs SnifferEnvironmentParser to detect usage\n * 6. Apps with neither: Returns empty\n *\n * This function handles \"fire and forget\" async operations gracefully,\n * capturing errors and unhandled rejections without failing the build.\n *\n * @param app - The normalized app configuration\n * @param appName - The name of the app\n * @param workspacePath - Absolute path to the workspace root\n * @param options - Optional configuration for sniffing behavior\n * @returns The sniffed environment with required variables\n */\nexport async function sniffAppEnvironment(\n\tapp: NormalizedAppConfig,\n\tappName: string,\n\tworkspacePath: string,\n\toptions: SniffAppOptions = {},\n): Promise<SniffedEnvironment> {\n\tconst { logWarnings = true, markOptional = false } = options;\n\n\t// 1. Frontend apps - handle dependencies and config sniffing\n\tif (app.type === 'frontend') {\n\t\t// Auto-generate NEXT_PUBLIC_{DEP}_URL from dependencies\n\t\tconst depVars = (app.dependencies ?? []).map(\n\t\t\t(dep) => `NEXT_PUBLIC_${dep.toUpperCase()}_URL`,\n\t\t);\n\n\t\t// If config specified, sniff by importing the file(s)\n\t\t// The file calls .parse() at module load, which triggers sniffer to capture vars\n\t\tif (app.config) {\n\t\t\tconst sniffedVars: string[] = [];\n\t\t\tconst sniffedOptional: string[] = [];\n\n\t\t\t// Collect config paths to sniff\n\t\t\tconst configPaths: string[] = [];\n\t\t\tif (app.config.client) configPaths.push(app.config.client);\n\t\t\tif (app.config.server) configPaths.push(app.config.server);\n\n\t\t\t// Sniff each config file\n\t\t\tfor (const configPath of configPaths) {\n\t\t\t\tconst result = await sniffEntryFile(\n\t\t\t\t\tconfigPath,\n\t\t\t\t\tapp.path,\n\t\t\t\t\tworkspacePath,\n\t\t\t\t);\n\n\t\t\t\tif (logWarnings && result.error) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[sniffer] ${appName}: Config file \"${configPath}\" threw error during sniffing (env vars still captured): ${result.error.message}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tsniffedVars.push(...result.envVars);\n\t\t\t\tsniffedOptional.push(...result.optionalEnvVars);\n\t\t\t}\n\n\t\t\tconst optionalEnvVars = [...new Set(sniffedOptional)];\n\t\t\t// Combine: dependency vars + sniffed vars (deduplicated)\n\t\t\tconst allVars = applyMarkOptional(\n\t\t\t\t[...new Set([...depVars, ...sniffedVars])],\n\t\t\t\toptionalEnvVars,\n\t\t\t\tmarkOptional,\n\t\t\t);\n\t\t\treturn { appName, requiredEnvVars: allVars, optionalEnvVars };\n\t\t}\n\n\t\treturn { appName, requiredEnvVars: depVars, optionalEnvVars: [] };\n\t}\n\n\t// 2. Entry apps - import entry file in subprocess to trigger config.parse()\n\tif (app.entry) {\n\t\tconst result = await sniffEntryFile(app.entry, app.path, workspacePath);\n\n\t\tif (logWarnings && result.error) {\n\t\t\tconsole.warn(\n\t\t\t\t`[sniffer] ${appName}: Entry file threw error during sniffing (env vars still captured): ${result.error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tappName,\n\t\t\trequiredEnvVars: applyMarkOptional(\n\t\t\t\tresult.envVars,\n\t\t\t\tresult.optionalEnvVars,\n\t\t\t\tmarkOptional,\n\t\t\t),\n\t\t\toptionalEnvVars: result.optionalEnvVars,\n\t\t};\n\t}\n\n\t// 4. Route-based apps - load routes and call getEnvironment() on each construct\n\tif (app.routes) {\n\t\tconst result = await sniffRouteFiles(\n\t\t\tnormalizeRoutes(app.routes),\n\t\t\tapp.path,\n\t\t\tworkspacePath,\n\t\t);\n\n\t\tif (logWarnings && result.error) {\n\t\t\tconsole.warn(\n\t\t\t\t`[sniffer] ${appName}: Route sniffing threw error (env vars still captured): ${result.error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tappName,\n\t\t\trequiredEnvVars: applyMarkOptional(\n\t\t\t\tresult.envVars,\n\t\t\t\tresult.optionalEnvVars,\n\t\t\t\tmarkOptional,\n\t\t\t),\n\t\t\toptionalEnvVars: result.optionalEnvVars,\n\t\t};\n\t}\n\n\t// 5. Apps with envParser but no routes - run sniffer to detect env var usage\n\tif (app.envParser) {\n\t\tconst result = await sniffEnvParser(app.envParser, app.path, workspacePath);\n\n\t\t// Log any issues for debugging\n\t\tif (logWarnings) {\n\t\t\tif (result.error) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[sniffer] ${appName}: envParser threw error during sniffing (env vars still captured): ${result.error.message}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.unhandledRejections.length > 0) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[sniffer] ${appName}: Fire-and-forget rejections during sniffing (suppressed): ${result.unhandledRejections.map((e) => e.message).join(', ')}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tappName,\n\t\t\trequiredEnvVars: applyMarkOptional(\n\t\t\t\tresult.envVars,\n\t\t\t\tresult.optionalEnvVars,\n\t\t\t\tmarkOptional,\n\t\t\t),\n\t\t\toptionalEnvVars: result.optionalEnvVars,\n\t\t};\n\t}\n\n\t// No env detection method available\n\treturn { appName, requiredEnvVars: [], optionalEnvVars: [] };\n}\n\n/**\n * Apply the `?` suffix to optional variables in an env var list.\n * Only modifies the list when `markOptional` is true and there are optional vars.\n */\nfunction applyMarkOptional(\n\tenvVars: string[],\n\toptionalEnvVars: string[],\n\tmarkOptional: boolean,\n): string[] {\n\tif (!markOptional || optionalEnvVars.length === 0) return envVars;\n\tconst optionalSet = new Set(optionalEnvVars);\n\treturn envVars.map((v) => (optionalSet.has(v) ? `${v}?` : v));\n}\n\n/**\n * Result from sniffing an entry file.\n */\ninterface EntrySniffResult {\n\tenvVars: string[];\n\toptionalEnvVars: string[];\n\terror?: Error;\n}\n\n/**\n * Sniff an entry file by importing it in a subprocess.\n *\n * Entry apps call `config.parse()` at module load time. To capture which\n * env vars are accessed, we:\n * 1. Spawn a subprocess with a module loader hook\n * 2. The loader intercepts `@geekmidas/envkit` and replaces EnvironmentParser\n * with SnifferEnvironmentParser\n * 3. Import the entry file (triggers config.parse())\n * 4. Capture and return the accessed env var names\n *\n * This approach provides process isolation - each app is sniffed in its own\n * subprocess, preventing module cache pollution.\n *\n * @param entryPath - Relative path to the entry file (e.g., './src/index.ts')\n * @param appPath - The app's path relative to workspace (e.g., 'apps/auth')\n * @param workspacePath - Absolute path to workspace root\n * @returns EntrySniffResult with env vars and optional error\n */\nasync function sniffEntryFile(\n\tentryPath: string,\n\tappPath: string,\n\tworkspacePath: string,\n): Promise<EntrySniffResult> {\n\tconst fullEntryPath = resolve(workspacePath, appPath, entryPath);\n\tconst loaderPath = resolveSnifferFile('sniffer-loader');\n\tconst workerPath = resolveSnifferFile('sniffer-worker');\n\n\treturn new Promise((resolvePromise) => {\n\t\tconst child = spawn(\n\t\t\t'node',\n\t\t\t['--import', loaderPath, workerPath, fullEntryPath],\n\t\t\t{\n\t\t\t\tcwd: resolve(workspacePath, appPath),\n\t\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\t\tenv: {\n\t\t\t\t\t...process.env,\n\t\t\t\t\t// Ensure tsx is available for TypeScript entry files\n\t\t\t\t\tNODE_OPTIONS: '--import=tsx',\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tlet stdout = '';\n\t\tlet stderr = '';\n\n\t\tchild.stdout.on('data', (data) => {\n\t\t\tstdout += data.toString();\n\t\t});\n\n\t\tchild.stderr.on('data', (data) => {\n\t\t\tstderr += data.toString();\n\t\t});\n\n\t\tchild.on('close', (code) => {\n\t\t\t// Try to parse the JSON output from the worker\n\t\t\ttry {\n\t\t\t\t// Find the last JSON object in stdout (worker may emit other output)\n\t\t\t\tconst jsonMatch = stdout.match(/\\{[^{}]*\"envVars\"[^{}]*\\}[^{]*$/);\n\t\t\t\tif (jsonMatch) {\n\t\t\t\t\tconst result = JSON.parse(jsonMatch[0]);\n\t\t\t\t\tresolvePromise({\n\t\t\t\t\t\tenvVars: result.envVars || [],\n\t\t\t\t\t\toptionalEnvVars: result.optionalEnvVars || [],\n\t\t\t\t\t\terror: result.error ? new Error(result.error) : undefined,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// JSON parse failed\n\t\t\t}\n\n\t\t\t// If we couldn't parse the output, return empty with error info\n\t\t\tresolvePromise({\n\t\t\t\tenvVars: [],\n\t\t\t\toptionalEnvVars: [],\n\t\t\t\terror: new Error(\n\t\t\t\t\t`Failed to sniff entry file (exit code ${code}): ${stderr || stdout || 'No output'}`,\n\t\t\t\t),\n\t\t\t});\n\t\t});\n\n\t\tchild.on('error', (err) => {\n\t\t\tresolvePromise({\n\t\t\t\tenvVars: [],\n\t\t\t\toptionalEnvVars: [],\n\t\t\t\terror: err,\n\t\t\t});\n\t\t});\n\t});\n}\n\n/**\n * Sniff route files by loading constructs and calling getEnvironment().\n *\n * Route-based apps have endpoints, functions, crons, and subscribers that\n * use services. Each service's register() method accesses environment variables.\n *\n * This runs in a subprocess with tsx loader to properly handle TypeScript\n * compilation and path alias resolution (e.g., `src/...` imports).\n *\n * @param routes - Glob pattern(s) for route files\n * @param appPath - The app's path relative to workspace (e.g., 'apps/api')\n * @param workspacePath - Absolute path to workspace root\n * @returns EntrySniffResult with env vars and optional error\n */\nasync function sniffRouteFiles(\n\troutes: string | string[],\n\tappPath: string,\n\tworkspacePath: string,\n): Promise<EntrySniffResult> {\n\tconst fullAppPath = resolve(workspacePath, appPath);\n\tconst workerPath = resolveSnifferFile('sniffer-routes-worker');\n\tconst tsxPath = resolveTsxPath();\n\n\t// Convert array of patterns to first pattern (worker handles glob internally)\n\tconst routesArray = Array.isArray(routes) ? routes : [routes];\n\tconst pattern = routesArray[0];\n\tif (!pattern) {\n\t\treturn {\n\t\t\tenvVars: [],\n\t\t\toptionalEnvVars: [],\n\t\t\terror: new Error('No route patterns provided'),\n\t\t};\n\t}\n\n\treturn new Promise((resolvePromise) => {\n\t\tconst child = spawn(\n\t\t\t'node',\n\t\t\t['--import', tsxPath, workerPath, fullAppPath, pattern],\n\t\t\t{\n\t\t\t\tcwd: fullAppPath,\n\t\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\t\tenv: {\n\t\t\t\t\t...process.env,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tlet stdout = '';\n\t\tlet stderr = '';\n\n\t\tchild.stdout.on('data', (data) => {\n\t\t\tstdout += data.toString();\n\t\t});\n\n\t\tchild.stderr.on('data', (data) => {\n\t\t\tstderr += data.toString();\n\t\t});\n\n\t\tchild.on('close', (code) => {\n\t\t\t// Log any stderr output (import errors, etc.)\n\t\t\tif (stderr) {\n\t\t\t\tstderr\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.filter((line) => line.trim())\n\t\t\t\t\t.forEach((line) => console.warn(line));\n\t\t\t}\n\n\t\t\t// Try to parse the JSON output from the worker\n\t\t\ttry {\n\t\t\t\t// Find the last JSON object in stdout (worker may emit other output)\n\t\t\t\tconst jsonMatch = stdout.match(/\\{[^{}]*\"envVars\"[^{}]*\\}[^{]*$/);\n\t\t\t\tif (jsonMatch) {\n\t\t\t\t\tconst result = JSON.parse(jsonMatch[0]);\n\t\t\t\t\tresolvePromise({\n\t\t\t\t\t\tenvVars: result.envVars || [],\n\t\t\t\t\t\t// Routes worker uses getEnvironment() which doesn't track\n\t\t\t\t\t\t// optionality yet — populated when service register() is sniffed\n\t\t\t\t\t\toptionalEnvVars: result.optionalEnvVars || [],\n\t\t\t\t\t\terror: result.error ? new Error(result.error) : undefined,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// JSON parse failed\n\t\t\t}\n\n\t\t\t// If we couldn't parse the output, return empty with error info\n\t\t\tresolvePromise({\n\t\t\t\tenvVars: [],\n\t\t\t\toptionalEnvVars: [],\n\t\t\t\terror: new Error(\n\t\t\t\t\t`Failed to sniff route files (exit code ${code}): ${stderr || stdout || 'No output'}`,\n\t\t\t\t),\n\t\t\t});\n\t\t});\n\n\t\tchild.on('error', (err) => {\n\t\t\tresolvePromise({\n\t\t\t\tenvVars: [],\n\t\t\t\toptionalEnvVars: [],\n\t\t\t\terror: err,\n\t\t\t});\n\t\t});\n\t});\n}\n\n/**\n * Run the SnifferEnvironmentParser on an envParser module to detect\n * which environment variables it accesses.\n *\n * This function handles \"fire and forget\" async operations by using\n * the shared sniffWithFireAndForget utility from @geekmidas/envkit.\n *\n * @param envParserPath - The envParser config (e.g., './src/config/env#envParser')\n * @param appPath - The app's path relative to workspace\n * @param workspacePath - Absolute path to workspace root\n * @returns SniffResult with env vars and any errors encountered\n */\nasync function sniffEnvParser(\n\tenvParserPath: string,\n\tappPath: string,\n\tworkspacePath: string,\n): Promise<SniffResult> {\n\t// Parse the envParser path: './src/config/env#envParser' or './src/config/env'\n\tconst [modulePath, exportName = 'default'] = envParserPath.split('#');\n\tif (!modulePath) {\n\t\treturn { envVars: [], optionalEnvVars: [], unhandledRejections: [] };\n\t}\n\n\t// Resolve the full path to the module\n\tconst fullPath = resolve(workspacePath, appPath, modulePath);\n\n\t// Dynamically import the sniffer utilities\n\tlet SnifferEnvironmentParser: any;\n\tlet sniffWithFireAndForget: any;\n\ttry {\n\t\tconst envkitModule = await import('@geekmidas/envkit/sniffer');\n\t\tSnifferEnvironmentParser = envkitModule.SnifferEnvironmentParser;\n\t\tsniffWithFireAndForget = envkitModule.sniffWithFireAndForget;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(\n\t\t\t`[sniffer] Failed to import SnifferEnvironmentParser: ${message}`,\n\t\t);\n\t\treturn { envVars: [], optionalEnvVars: [], unhandledRejections: [] };\n\t}\n\n\tconst sniffer = new SnifferEnvironmentParser();\n\n\treturn sniffWithFireAndForget(sniffer, async () => {\n\t\t// Import the envParser module\n\t\tconst moduleUrl = pathToFileURL(fullPath).href;\n\t\tconst module = await import(moduleUrl);\n\n\t\t// Get the envParser function\n\t\tconst envParser = module[exportName];\n\t\tif (typeof envParser !== 'function') {\n\t\t\tconsole.warn(\n\t\t\t\t`[sniffer] Export \"${exportName}\" from \"${modulePath}\" is not a function`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// The envParser function typically creates and configures an EnvironmentParser.\n\t\t// We pass our sniffer which implements the same interface.\n\t\tconst result = envParser(sniffer);\n\n\t\t// If the result is a ConfigParser, call parse() to trigger env var access\n\t\tif (result && typeof result.parse === 'function') {\n\t\t\ttry {\n\t\t\t\tresult.parse();\n\t\t\t} catch {\n\t\t\t\t// Parsing may fail due to mock values, that's expected\n\t\t\t}\n\t\t}\n\t});\n}\n\n/**\n * Sniff environment requirements for multiple apps.\n *\n * @param apps - Map of app name to app config\n * @param workspacePath - Absolute path to workspace root\n * @param options - Optional configuration for sniffing behavior\n * @returns Map of app name to sniffed environment\n */\nexport async function sniffAllApps(\n\tapps: Record<string, NormalizedAppConfig>,\n\tworkspacePath: string,\n\toptions: SniffAppOptions = {},\n): Promise<Map<string, SniffedEnvironment>> {\n\tconst results = new Map<string, SniffedEnvironment>();\n\n\tfor (const [appName, app] of Object.entries(apps)) {\n\t\tconst sniffed = await sniffAppEnvironment(\n\t\t\tapp,\n\t\t\tappName,\n\t\t\tworkspacePath,\n\t\t\toptions,\n\t\t);\n\t\tresults.set(appName, sniffed);\n\t}\n\n\treturn results;\n}\n\n// Export for testing\nexport {\n\tsniffEnvParser as _sniffEnvParser,\n\tsniffEntryFile as _sniffEntryFile,\n\tsniffRouteFiles as _sniffRouteFiles,\n};\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import "./client-generator-CUVVtAOo.mjs";
2
+ import { sniffAllApps, sniffAppEnvironment, sniffEntryFile, sniffEnvParser, sniffRouteFiles } from "./sniffer-BqSVVrWA.mjs";
3
+
4
+ export { sniffEnvParser as _sniffEnvParser };
@@ -0,0 +1,4 @@
1
+ require('./client-generator-D-T4ypQo.cjs');
2
+ const require_sniffer = require('./sniffer-CBhzByiY.cjs');
3
+
4
+ exports._sniffEnvParser = require_sniffer.sniffEnvParser;
@@ -0,0 +1,4 @@
1
+ const require_sync = require('./sync-BWY6yoUG.cjs');
2
+
3
+ exports.pullSecrets = require_sync.pullSecrets;
4
+ exports.pushSecrets = require_sync.pushSecrets;
@@ -90,4 +90,4 @@ Object.defineProperty(exports, 'pushSecrets', {
90
90
  return pushSecrets;
91
91
  }
92
92
  });
93
- //# sourceMappingURL=sync-DGXXSk2v.cjs.map
93
+ //# sourceMappingURL=sync-BWY6yoUG.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync-DGXXSk2v.cjs","names":["workspaceName: string","stage: string","config: SSMStateConfig","clientConfig: SSMClientConfig","SSMClient","workspace: NormalizedWorkspace","PutParameterCommand","GetParameterCommand","ParameterNotFound"],"sources":["../src/secrets/sync.ts"],"sourcesContent":["/**\n * Secrets Sync via AWS SSM Parameter Store\n *\n * Stores and retrieves encrypted StageSecrets as SecureString parameters.\n * Reuses the SSM infrastructure from the state provider.\n *\n * Parameter naming: /gkm/{workspaceName}/{stage}/secrets\n */\n\nimport {\n\tGetParameterCommand,\n\tParameterNotFound,\n\tPutParameterCommand,\n\tSSMClient,\n\ttype SSMClientConfig,\n} from '@aws-sdk/client-ssm';\nimport type { SSMStateConfig } from '../deploy/StateProvider.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport type { StageSecrets } from './types.js';\n\n/**\n * Get the SSM parameter name for secrets.\n */\nfunction getSecretsParameterName(workspaceName: string, stage: string): string {\n\treturn `/gkm/${workspaceName}/${stage}/secrets`;\n}\n\n/**\n * Create an SSM client from workspace state config.\n */\nfunction createSSMClient(config: SSMStateConfig): SSMClient {\n\tconst clientConfig: SSMClientConfig = {\n\t\tregion: config.region,\n\t};\n\n\tif (config.profile) {\n\t\tconst { fromIni } = require('@aws-sdk/credential-providers');\n\t\tclientConfig.credentials = fromIni({ profile: config.profile });\n\t}\n\n\treturn new SSMClient(clientConfig);\n}\n\n/**\n * Push secrets to SSM Parameter Store.\n *\n * Stores the full StageSecrets object as a SecureString parameter.\n */\nexport async function pushSecrets(\n\tstage: string,\n\tworkspace: NormalizedWorkspace,\n): Promise<void> {\n\tconst config = workspace.state;\n\tif (!config || config.provider !== 'ssm') {\n\t\tthrow new Error(\n\t\t\t'SSM state provider not configured. Add state: { provider: \"ssm\", region: \"...\" } to gkm.config.ts.',\n\t\t);\n\t}\n\n\tif (!workspace.name) {\n\t\tthrow new Error(\n\t\t\t'Workspace name is required for SSM secrets sync. Set \"name\" in gkm.config.ts.',\n\t\t);\n\t}\n\n\tconst client = createSSMClient(config as SSMStateConfig);\n\tconst parameterName = getSecretsParameterName(workspace.name, stage);\n\n\tconst { readStageSecrets } = await import('./storage.js');\n\tconst secrets = await readStageSecrets(stage, workspace.root);\n\n\tif (!secrets) {\n\t\tthrow new Error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t}\n\n\tawait client.send(\n\t\tnew PutParameterCommand({\n\t\t\tName: parameterName,\n\t\t\tValue: JSON.stringify(secrets),\n\t\t\tType: 'SecureString',\n\t\t\tOverwrite: true,\n\t\t\tDescription: `GKM secrets for ${workspace.name}/${stage}`,\n\t\t}),\n\t);\n}\n\n/**\n * Pull secrets from SSM Parameter Store.\n *\n * @returns StageSecrets or null if no secrets are stored remotely\n */\nexport async function pullSecrets(\n\tstage: string,\n\tworkspace: NormalizedWorkspace,\n): Promise<StageSecrets | null> {\n\tconst config = workspace.state;\n\tif (!config || config.provider !== 'ssm') {\n\t\treturn null;\n\t}\n\n\tif (!workspace.name) {\n\t\treturn null;\n\t}\n\n\tconst client = createSSMClient(config as SSMStateConfig);\n\tconst parameterName = getSecretsParameterName(workspace.name, stage);\n\n\ttry {\n\t\tconst response = await client.send(\n\t\t\tnew GetParameterCommand({\n\t\t\t\tName: parameterName,\n\t\t\t\tWithDecryption: true,\n\t\t\t}),\n\t\t);\n\n\t\tif (!response.Parameter?.Value) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn JSON.parse(response.Parameter.Value) as StageSecrets;\n\t} catch (error) {\n\t\tif (error instanceof ParameterNotFound) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Check if SSM is configured for the workspace.\n */\nexport function isSSMConfigured(workspace: NormalizedWorkspace): boolean {\n\treturn !!workspace.state && workspace.state.provider === 'ssm';\n}\n"],"mappings":";;;;;;;AAuBA,SAAS,wBAAwBA,eAAuBC,OAAuB;AAC9E,SAAQ,OAAO,cAAc,GAAG,MAAM;AACtC;;;;AAKD,SAAS,gBAAgBC,QAAmC;CAC3D,MAAMC,eAAgC,EACrC,QAAQ,OAAO,OACf;AAED,KAAI,OAAO,SAAS;EACnB,MAAM,EAAE,SAAS,GAAG,QAAQ,gCAAgC;AAC5D,eAAa,cAAc,QAAQ,EAAE,SAAS,OAAO,QAAS,EAAC;CAC/D;AAED,QAAO,IAAIC,+BAAU;AACrB;;;;;;AAOD,eAAsB,YACrBH,OACAI,WACgB;CAChB,MAAM,SAAS,UAAU;AACzB,MAAK,UAAU,OAAO,aAAa,MAClC,OAAM,IAAI,MACT;AAIF,MAAK,UAAU,KACd,OAAM,IAAI,MACT;CAIF,MAAM,SAAS,gBAAgB,OAAyB;CACxD,MAAM,gBAAgB,wBAAwB,UAAU,MAAM,MAAM;CAEpE,MAAM,EAAE,kBAAkB,GAAG,2CAAM;CACnC,MAAM,UAAU,MAAM,iBAAiB,OAAO,UAAU,KAAK;AAE7D,MAAK,QACJ,OAAM,IAAI,OACR,8BAA8B,MAAM,mCAAmC,MAAM;AAIhF,OAAM,OAAO,KACZ,IAAIC,yCAAoB;EACvB,MAAM;EACN,OAAO,KAAK,UAAU,QAAQ;EAC9B,MAAM;EACN,WAAW;EACX,cAAc,kBAAkB,UAAU,KAAK,GAAG,MAAM;CACxD,GACD;AACD;;;;;;AAOD,eAAsB,YACrBL,OACAI,WAC+B;CAC/B,MAAM,SAAS,UAAU;AACzB,MAAK,UAAU,OAAO,aAAa,MAClC,QAAO;AAGR,MAAK,UAAU,KACd,QAAO;CAGR,MAAM,SAAS,gBAAgB,OAAyB;CACxD,MAAM,gBAAgB,wBAAwB,UAAU,MAAM,MAAM;AAEpE,KAAI;EACH,MAAM,WAAW,MAAM,OAAO,KAC7B,IAAIE,yCAAoB;GACvB,MAAM;GACN,gBAAgB;EAChB,GACD;AAED,OAAK,SAAS,WAAW,MACxB,QAAO;AAGR,SAAO,KAAK,MAAM,SAAS,UAAU,MAAM;CAC3C,SAAQ,OAAO;AACf,MAAI,iBAAiBC,uCACpB,QAAO;AAER,QAAM;CACN;AACD;;;;AAKD,SAAgB,gBAAgBH,WAAyC;AACxE,UAAS,UAAU,SAAS,UAAU,MAAM,aAAa;AACzD"}
1
+ {"version":3,"file":"sync-BWY6yoUG.cjs","names":["workspaceName: string","stage: string","config: SSMStateConfig","clientConfig: SSMClientConfig","SSMClient","workspace: NormalizedWorkspace","PutParameterCommand","GetParameterCommand","ParameterNotFound"],"sources":["../src/secrets/sync.ts"],"sourcesContent":["/**\n * Secrets Sync via AWS SSM Parameter Store\n *\n * Stores and retrieves encrypted StageSecrets as SecureString parameters.\n * Reuses the SSM infrastructure from the state provider.\n *\n * Parameter naming: /gkm/{workspaceName}/{stage}/secrets\n */\n\nimport {\n\tGetParameterCommand,\n\tParameterNotFound,\n\tPutParameterCommand,\n\tSSMClient,\n\ttype SSMClientConfig,\n} from '@aws-sdk/client-ssm';\nimport type { SSMStateConfig } from '../deploy/StateProvider.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport type { StageSecrets } from './types.js';\n\n/**\n * Get the SSM parameter name for secrets.\n */\nfunction getSecretsParameterName(workspaceName: string, stage: string): string {\n\treturn `/gkm/${workspaceName}/${stage}/secrets`;\n}\n\n/**\n * Create an SSM client from workspace state config.\n */\nfunction createSSMClient(config: SSMStateConfig): SSMClient {\n\tconst clientConfig: SSMClientConfig = {\n\t\tregion: config.region,\n\t};\n\n\tif (config.profile) {\n\t\tconst { fromIni } = require('@aws-sdk/credential-providers');\n\t\tclientConfig.credentials = fromIni({ profile: config.profile });\n\t}\n\n\treturn new SSMClient(clientConfig);\n}\n\n/**\n * Push secrets to SSM Parameter Store.\n *\n * Stores the full StageSecrets object as a SecureString parameter.\n */\nexport async function pushSecrets(\n\tstage: string,\n\tworkspace: NormalizedWorkspace,\n): Promise<void> {\n\tconst config = workspace.state;\n\tif (!config || config.provider !== 'ssm') {\n\t\tthrow new Error(\n\t\t\t'SSM state provider not configured. Add state: { provider: \"ssm\", region: \"...\" } to gkm.config.ts.',\n\t\t);\n\t}\n\n\tif (!workspace.name) {\n\t\tthrow new Error(\n\t\t\t'Workspace name is required for SSM secrets sync. Set \"name\" in gkm.config.ts.',\n\t\t);\n\t}\n\n\tconst client = createSSMClient(config as SSMStateConfig);\n\tconst parameterName = getSecretsParameterName(workspace.name, stage);\n\n\tconst { readStageSecrets } = await import('./storage.js');\n\tconst secrets = await readStageSecrets(stage, workspace.root);\n\n\tif (!secrets) {\n\t\tthrow new Error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t}\n\n\tawait client.send(\n\t\tnew PutParameterCommand({\n\t\t\tName: parameterName,\n\t\t\tValue: JSON.stringify(secrets),\n\t\t\tType: 'SecureString',\n\t\t\tOverwrite: true,\n\t\t\tDescription: `GKM secrets for ${workspace.name}/${stage}`,\n\t\t}),\n\t);\n}\n\n/**\n * Pull secrets from SSM Parameter Store.\n *\n * @returns StageSecrets or null if no secrets are stored remotely\n */\nexport async function pullSecrets(\n\tstage: string,\n\tworkspace: NormalizedWorkspace,\n): Promise<StageSecrets | null> {\n\tconst config = workspace.state;\n\tif (!config || config.provider !== 'ssm') {\n\t\treturn null;\n\t}\n\n\tif (!workspace.name) {\n\t\treturn null;\n\t}\n\n\tconst client = createSSMClient(config as SSMStateConfig);\n\tconst parameterName = getSecretsParameterName(workspace.name, stage);\n\n\ttry {\n\t\tconst response = await client.send(\n\t\t\tnew GetParameterCommand({\n\t\t\t\tName: parameterName,\n\t\t\t\tWithDecryption: true,\n\t\t\t}),\n\t\t);\n\n\t\tif (!response.Parameter?.Value) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn JSON.parse(response.Parameter.Value) as StageSecrets;\n\t} catch (error) {\n\t\tif (error instanceof ParameterNotFound) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Check if SSM is configured for the workspace.\n */\nexport function isSSMConfigured(workspace: NormalizedWorkspace): boolean {\n\treturn !!workspace.state && workspace.state.provider === 'ssm';\n}\n"],"mappings":";;;;;;;AAuBA,SAAS,wBAAwBA,eAAuBC,OAAuB;AAC9E,SAAQ,OAAO,cAAc,GAAG,MAAM;AACtC;;;;AAKD,SAAS,gBAAgBC,QAAmC;CAC3D,MAAMC,eAAgC,EACrC,QAAQ,OAAO,OACf;AAED,KAAI,OAAO,SAAS;EACnB,MAAM,EAAE,SAAS,GAAG,QAAQ,gCAAgC;AAC5D,eAAa,cAAc,QAAQ,EAAE,SAAS,OAAO,QAAS,EAAC;CAC/D;AAED,QAAO,IAAIC,+BAAU;AACrB;;;;;;AAOD,eAAsB,YACrBH,OACAI,WACgB;CAChB,MAAM,SAAS,UAAU;AACzB,MAAK,UAAU,OAAO,aAAa,MAClC,OAAM,IAAI,MACT;AAIF,MAAK,UAAU,KACd,OAAM,IAAI,MACT;CAIF,MAAM,SAAS,gBAAgB,OAAyB;CACxD,MAAM,gBAAgB,wBAAwB,UAAU,MAAM,MAAM;CAEpE,MAAM,EAAE,kBAAkB,GAAG,2CAAM;CACnC,MAAM,UAAU,MAAM,iBAAiB,OAAO,UAAU,KAAK;AAE7D,MAAK,QACJ,OAAM,IAAI,OACR,8BAA8B,MAAM,mCAAmC,MAAM;AAIhF,OAAM,OAAO,KACZ,IAAIC,yCAAoB;EACvB,MAAM;EACN,OAAO,KAAK,UAAU,QAAQ;EAC9B,MAAM;EACN,WAAW;EACX,cAAc,kBAAkB,UAAU,KAAK,GAAG,MAAM;CACxD,GACD;AACD;;;;;;AAOD,eAAsB,YACrBL,OACAI,WAC+B;CAC/B,MAAM,SAAS,UAAU;AACzB,MAAK,UAAU,OAAO,aAAa,MAClC,QAAO;AAGR,MAAK,UAAU,KACd,QAAO;CAGR,MAAM,SAAS,gBAAgB,OAAyB;CACxD,MAAM,gBAAgB,wBAAwB,UAAU,MAAM,MAAM;AAEpE,KAAI;EACH,MAAM,WAAW,MAAM,OAAO,KAC7B,IAAIE,yCAAoB;GACvB,MAAM;GACN,gBAAgB;EAChB,GACD;AAED,OAAK,SAAS,WAAW,MACxB,QAAO;AAGR,SAAO,KAAK,MAAM,SAAS,UAAU,MAAM;CAC3C,SAAQ,OAAO;AACf,MAAI,iBAAiBC,uCACpB,QAAO;AAER,QAAM;CACN;AACD;;;;AAKD,SAAgB,gBAAgBH,WAAyC;AACxE,UAAS,UAAU,SAAS,UAAU,MAAM,aAAa;AACzD"}
@@ -73,4 +73,4 @@ function isSSMConfigured(workspace) {
73
73
 
74
74
  //#endregion
75
75
  export { isSSMConfigured, pullSecrets, pushSecrets };
76
- //# sourceMappingURL=sync-D_NowTkZ.mjs.map
76
+ //# sourceMappingURL=sync-Dc-QA4Mx.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync-D_NowTkZ.mjs","names":["workspaceName: string","stage: string","config: SSMStateConfig","clientConfig: SSMClientConfig","workspace: NormalizedWorkspace"],"sources":["../src/secrets/sync.ts"],"sourcesContent":["/**\n * Secrets Sync via AWS SSM Parameter Store\n *\n * Stores and retrieves encrypted StageSecrets as SecureString parameters.\n * Reuses the SSM infrastructure from the state provider.\n *\n * Parameter naming: /gkm/{workspaceName}/{stage}/secrets\n */\n\nimport {\n\tGetParameterCommand,\n\tParameterNotFound,\n\tPutParameterCommand,\n\tSSMClient,\n\ttype SSMClientConfig,\n} from '@aws-sdk/client-ssm';\nimport type { SSMStateConfig } from '../deploy/StateProvider.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport type { StageSecrets } from './types.js';\n\n/**\n * Get the SSM parameter name for secrets.\n */\nfunction getSecretsParameterName(workspaceName: string, stage: string): string {\n\treturn `/gkm/${workspaceName}/${stage}/secrets`;\n}\n\n/**\n * Create an SSM client from workspace state config.\n */\nfunction createSSMClient(config: SSMStateConfig): SSMClient {\n\tconst clientConfig: SSMClientConfig = {\n\t\tregion: config.region,\n\t};\n\n\tif (config.profile) {\n\t\tconst { fromIni } = require('@aws-sdk/credential-providers');\n\t\tclientConfig.credentials = fromIni({ profile: config.profile });\n\t}\n\n\treturn new SSMClient(clientConfig);\n}\n\n/**\n * Push secrets to SSM Parameter Store.\n *\n * Stores the full StageSecrets object as a SecureString parameter.\n */\nexport async function pushSecrets(\n\tstage: string,\n\tworkspace: NormalizedWorkspace,\n): Promise<void> {\n\tconst config = workspace.state;\n\tif (!config || config.provider !== 'ssm') {\n\t\tthrow new Error(\n\t\t\t'SSM state provider not configured. Add state: { provider: \"ssm\", region: \"...\" } to gkm.config.ts.',\n\t\t);\n\t}\n\n\tif (!workspace.name) {\n\t\tthrow new Error(\n\t\t\t'Workspace name is required for SSM secrets sync. Set \"name\" in gkm.config.ts.',\n\t\t);\n\t}\n\n\tconst client = createSSMClient(config as SSMStateConfig);\n\tconst parameterName = getSecretsParameterName(workspace.name, stage);\n\n\tconst { readStageSecrets } = await import('./storage.js');\n\tconst secrets = await readStageSecrets(stage, workspace.root);\n\n\tif (!secrets) {\n\t\tthrow new Error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t}\n\n\tawait client.send(\n\t\tnew PutParameterCommand({\n\t\t\tName: parameterName,\n\t\t\tValue: JSON.stringify(secrets),\n\t\t\tType: 'SecureString',\n\t\t\tOverwrite: true,\n\t\t\tDescription: `GKM secrets for ${workspace.name}/${stage}`,\n\t\t}),\n\t);\n}\n\n/**\n * Pull secrets from SSM Parameter Store.\n *\n * @returns StageSecrets or null if no secrets are stored remotely\n */\nexport async function pullSecrets(\n\tstage: string,\n\tworkspace: NormalizedWorkspace,\n): Promise<StageSecrets | null> {\n\tconst config = workspace.state;\n\tif (!config || config.provider !== 'ssm') {\n\t\treturn null;\n\t}\n\n\tif (!workspace.name) {\n\t\treturn null;\n\t}\n\n\tconst client = createSSMClient(config as SSMStateConfig);\n\tconst parameterName = getSecretsParameterName(workspace.name, stage);\n\n\ttry {\n\t\tconst response = await client.send(\n\t\t\tnew GetParameterCommand({\n\t\t\t\tName: parameterName,\n\t\t\t\tWithDecryption: true,\n\t\t\t}),\n\t\t);\n\n\t\tif (!response.Parameter?.Value) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn JSON.parse(response.Parameter.Value) as StageSecrets;\n\t} catch (error) {\n\t\tif (error instanceof ParameterNotFound) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Check if SSM is configured for the workspace.\n */\nexport function isSSMConfigured(workspace: NormalizedWorkspace): boolean {\n\treturn !!workspace.state && workspace.state.provider === 'ssm';\n}\n"],"mappings":";;;;;;;AAuBA,SAAS,wBAAwBA,eAAuBC,OAAuB;AAC9E,SAAQ,OAAO,cAAc,GAAG,MAAM;AACtC;;;;AAKD,SAAS,gBAAgBC,QAAmC;CAC3D,MAAMC,eAAgC,EACrC,QAAQ,OAAO,OACf;AAED,KAAI,OAAO,SAAS;EACnB,MAAM,EAAE,SAAS,GAAG,UAAQ,gCAAgC;AAC5D,eAAa,cAAc,QAAQ,EAAE,SAAS,OAAO,QAAS,EAAC;CAC/D;AAED,QAAO,IAAI,UAAU;AACrB;;;;;;AAOD,eAAsB,YACrBF,OACAG,WACgB;CAChB,MAAM,SAAS,UAAU;AACzB,MAAK,UAAU,OAAO,aAAa,MAClC,OAAM,IAAI,MACT;AAIF,MAAK,UAAU,KACd,OAAM,IAAI,MACT;CAIF,MAAM,SAAS,gBAAgB,OAAyB;CACxD,MAAM,gBAAgB,wBAAwB,UAAU,MAAM,MAAM;CAEpE,MAAM,EAAE,kBAAkB,GAAG,MAAM,OAAO;CAC1C,MAAM,UAAU,MAAM,iBAAiB,OAAO,UAAU,KAAK;AAE7D,MAAK,QACJ,OAAM,IAAI,OACR,8BAA8B,MAAM,mCAAmC,MAAM;AAIhF,OAAM,OAAO,KACZ,IAAI,oBAAoB;EACvB,MAAM;EACN,OAAO,KAAK,UAAU,QAAQ;EAC9B,MAAM;EACN,WAAW;EACX,cAAc,kBAAkB,UAAU,KAAK,GAAG,MAAM;CACxD,GACD;AACD;;;;;;AAOD,eAAsB,YACrBH,OACAG,WAC+B;CAC/B,MAAM,SAAS,UAAU;AACzB,MAAK,UAAU,OAAO,aAAa,MAClC,QAAO;AAGR,MAAK,UAAU,KACd,QAAO;CAGR,MAAM,SAAS,gBAAgB,OAAyB;CACxD,MAAM,gBAAgB,wBAAwB,UAAU,MAAM,MAAM;AAEpE,KAAI;EACH,MAAM,WAAW,MAAM,OAAO,KAC7B,IAAI,oBAAoB;GACvB,MAAM;GACN,gBAAgB;EAChB,GACD;AAED,OAAK,SAAS,WAAW,MACxB,QAAO;AAGR,SAAO,KAAK,MAAM,SAAS,UAAU,MAAM;CAC3C,SAAQ,OAAO;AACf,MAAI,iBAAiB,kBACpB,QAAO;AAER,QAAM;CACN;AACD;;;;AAKD,SAAgB,gBAAgBA,WAAyC;AACxE,UAAS,UAAU,SAAS,UAAU,MAAM,aAAa;AACzD"}
1
+ {"version":3,"file":"sync-Dc-QA4Mx.mjs","names":["workspaceName: string","stage: string","config: SSMStateConfig","clientConfig: SSMClientConfig","workspace: NormalizedWorkspace"],"sources":["../src/secrets/sync.ts"],"sourcesContent":["/**\n * Secrets Sync via AWS SSM Parameter Store\n *\n * Stores and retrieves encrypted StageSecrets as SecureString parameters.\n * Reuses the SSM infrastructure from the state provider.\n *\n * Parameter naming: /gkm/{workspaceName}/{stage}/secrets\n */\n\nimport {\n\tGetParameterCommand,\n\tParameterNotFound,\n\tPutParameterCommand,\n\tSSMClient,\n\ttype SSMClientConfig,\n} from '@aws-sdk/client-ssm';\nimport type { SSMStateConfig } from '../deploy/StateProvider.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport type { StageSecrets } from './types.js';\n\n/**\n * Get the SSM parameter name for secrets.\n */\nfunction getSecretsParameterName(workspaceName: string, stage: string): string {\n\treturn `/gkm/${workspaceName}/${stage}/secrets`;\n}\n\n/**\n * Create an SSM client from workspace state config.\n */\nfunction createSSMClient(config: SSMStateConfig): SSMClient {\n\tconst clientConfig: SSMClientConfig = {\n\t\tregion: config.region,\n\t};\n\n\tif (config.profile) {\n\t\tconst { fromIni } = require('@aws-sdk/credential-providers');\n\t\tclientConfig.credentials = fromIni({ profile: config.profile });\n\t}\n\n\treturn new SSMClient(clientConfig);\n}\n\n/**\n * Push secrets to SSM Parameter Store.\n *\n * Stores the full StageSecrets object as a SecureString parameter.\n */\nexport async function pushSecrets(\n\tstage: string,\n\tworkspace: NormalizedWorkspace,\n): Promise<void> {\n\tconst config = workspace.state;\n\tif (!config || config.provider !== 'ssm') {\n\t\tthrow new Error(\n\t\t\t'SSM state provider not configured. Add state: { provider: \"ssm\", region: \"...\" } to gkm.config.ts.',\n\t\t);\n\t}\n\n\tif (!workspace.name) {\n\t\tthrow new Error(\n\t\t\t'Workspace name is required for SSM secrets sync. Set \"name\" in gkm.config.ts.',\n\t\t);\n\t}\n\n\tconst client = createSSMClient(config as SSMStateConfig);\n\tconst parameterName = getSecretsParameterName(workspace.name, stage);\n\n\tconst { readStageSecrets } = await import('./storage.js');\n\tconst secrets = await readStageSecrets(stage, workspace.root);\n\n\tif (!secrets) {\n\t\tthrow new Error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t}\n\n\tawait client.send(\n\t\tnew PutParameterCommand({\n\t\t\tName: parameterName,\n\t\t\tValue: JSON.stringify(secrets),\n\t\t\tType: 'SecureString',\n\t\t\tOverwrite: true,\n\t\t\tDescription: `GKM secrets for ${workspace.name}/${stage}`,\n\t\t}),\n\t);\n}\n\n/**\n * Pull secrets from SSM Parameter Store.\n *\n * @returns StageSecrets or null if no secrets are stored remotely\n */\nexport async function pullSecrets(\n\tstage: string,\n\tworkspace: NormalizedWorkspace,\n): Promise<StageSecrets | null> {\n\tconst config = workspace.state;\n\tif (!config || config.provider !== 'ssm') {\n\t\treturn null;\n\t}\n\n\tif (!workspace.name) {\n\t\treturn null;\n\t}\n\n\tconst client = createSSMClient(config as SSMStateConfig);\n\tconst parameterName = getSecretsParameterName(workspace.name, stage);\n\n\ttry {\n\t\tconst response = await client.send(\n\t\t\tnew GetParameterCommand({\n\t\t\t\tName: parameterName,\n\t\t\t\tWithDecryption: true,\n\t\t\t}),\n\t\t);\n\n\t\tif (!response.Parameter?.Value) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn JSON.parse(response.Parameter.Value) as StageSecrets;\n\t} catch (error) {\n\t\tif (error instanceof ParameterNotFound) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Check if SSM is configured for the workspace.\n */\nexport function isSSMConfigured(workspace: NormalizedWorkspace): boolean {\n\treturn !!workspace.state && workspace.state.provider === 'ssm';\n}\n"],"mappings":";;;;;;;AAuBA,SAAS,wBAAwBA,eAAuBC,OAAuB;AAC9E,SAAQ,OAAO,cAAc,GAAG,MAAM;AACtC;;;;AAKD,SAAS,gBAAgBC,QAAmC;CAC3D,MAAMC,eAAgC,EACrC,QAAQ,OAAO,OACf;AAED,KAAI,OAAO,SAAS;EACnB,MAAM,EAAE,SAAS,GAAG,UAAQ,gCAAgC;AAC5D,eAAa,cAAc,QAAQ,EAAE,SAAS,OAAO,QAAS,EAAC;CAC/D;AAED,QAAO,IAAI,UAAU;AACrB;;;;;;AAOD,eAAsB,YACrBF,OACAG,WACgB;CAChB,MAAM,SAAS,UAAU;AACzB,MAAK,UAAU,OAAO,aAAa,MAClC,OAAM,IAAI,MACT;AAIF,MAAK,UAAU,KACd,OAAM,IAAI,MACT;CAIF,MAAM,SAAS,gBAAgB,OAAyB;CACxD,MAAM,gBAAgB,wBAAwB,UAAU,MAAM,MAAM;CAEpE,MAAM,EAAE,kBAAkB,GAAG,MAAM,OAAO;CAC1C,MAAM,UAAU,MAAM,iBAAiB,OAAO,UAAU,KAAK;AAE7D,MAAK,QACJ,OAAM,IAAI,OACR,8BAA8B,MAAM,mCAAmC,MAAM;AAIhF,OAAM,OAAO,KACZ,IAAI,oBAAoB;EACvB,MAAM;EACN,OAAO,KAAK,UAAU,QAAQ;EAC9B,MAAM;EACN,WAAW;EACX,cAAc,kBAAkB,UAAU,KAAK,GAAG,MAAM;CACxD,GACD;AACD;;;;;;AAOD,eAAsB,YACrBH,OACAG,WAC+B;CAC/B,MAAM,SAAS,UAAU;AACzB,MAAK,UAAU,OAAO,aAAa,MAClC,QAAO;AAGR,MAAK,UAAU,KACd,QAAO;CAGR,MAAM,SAAS,gBAAgB,OAAyB;CACxD,MAAM,gBAAgB,wBAAwB,UAAU,MAAM,MAAM;AAEpE,KAAI;EACH,MAAM,WAAW,MAAM,OAAO,KAC7B,IAAI,oBAAoB;GACvB,MAAM;GACN,gBAAgB;EAChB,GACD;AAED,OAAK,SAAS,WAAW,MACxB,QAAO;AAGR,SAAO,KAAK,MAAM,SAAS,UAAU,MAAM;CAC3C,SAAQ,OAAO;AACf,MAAI,iBAAiB,kBACpB,QAAO;AAER,QAAM;CACN;AACD;;;;AAKD,SAAgB,gBAAgBA,WAAyC;AACxE,UAAS,UAAU,SAAS,UAAU,MAAM,aAAa;AACzD"}
@@ -1,3 +1,3 @@
1
- import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-D_NowTkZ.mjs";
1
+ import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-Dc-QA4Mx.mjs";
2
2
 
3
3
  export { pullSecrets, pushSecrets };
@@ -275,4 +275,4 @@ interface GkmConfig {
275
275
  }
276
276
  //#endregion
277
277
  export { EventsBackend, GkmConfig, HooksConfig, OpenApiConfig, ProvidersConfig, Routes, Runtime, StudioConfig, TelescopeConfig };
278
- //# sourceMappingURL=types-OszPdw9m.d.mts.map
278
+ //# sourceMappingURL=types-BqAbYt5a.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-OszPdw9m.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;AAYY,UALK,iBAAA,CAKwB;EAaxB,KAAA,EAAA,MAAA,GAAA,MAAc,EAAA;EAKd,SAAA,EAAA,CAAA,QAAA,EAAoB,MAAA,EAAA,GAAQ,MAAA;AAI7C;AAIiB,KA1BL,MAAA,GA0BK,MAAgB,GAAA,MAAA,EAAA,GA1BQ,iBA0BR;AAkDrB,UA/DK,cAAA,CA+DQ;EAGb,OAAA,CAAA,EAAA,OAAA;EASA,SAAA,CAAA,EAAA,MAAA;;AACL,UAvEU,mBAAA,SAA4B,cAuEtC,CAAA;AAA6C,UAnEnC,eAAA,SAAwB,cAmEW,CAAA,CAGpD;AAA6B,UAlEZ,gBAAA,CAkEY;EAAA;EAwBK,OAAG,CAAA,EAAA,OAAA;EAAkB;EAItC,MAAA,CAAA,EAAA,OAAa;EAAA;EAAA,MAIhB,CAAA,EAAA,OAAA;EAAgB;EAJsB,WAAA,CAAA,EAAA,MAAA;EAOxC;EAEK,gBAAA,CAAA,EAAe,OAAA;EAiBf;EASA,QAAA,CAAA,EAAA,MAAa,EAAA;EAWb;EA6BA,WAAA,CAAA,EAAA,SAAA,GAAqB,SAAA;EAarB;EAAe,OAAA,CAAA,EAAA,OAAA;EAAA;;;;;;AAaU;EAGzB,iBAAS,CAAA,EAAA,OAAA;;;AAEb,UA5KI,aAAA,CA4KJ;EAAM;;;;EAeC,KAQY,CAAA,EAAA,MAAA;EAAe;;;;EA2DzB,OAAA,CAAA,EAAA,MAAA;;;;;;;;;;;KAxOV,aAAA;;KAGA,kBAAA;;KASA,qBAAA,WACL,gCAAgC;UAGtB,YAAA;;;;;;;;;;;;;;;;;;;;;;;;eAwBJ,wBAAwB;;;UAIpB,YAAA,SAAqB;;;;eAIxB;;KAGF,OAAA;UAEK,eAAA;;;;;;;;;;;;;;;;UAiBA,YAAA;;;;;;;;UASA,aAAA;;;;;;;;;;UAWA,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA6BA,qBAAA;;;;;;;;;;;;UAaA,eAAA;;;qBAGC;qBACA;;;4BAGO;wBACJ;;;qBAGD;;sBAEC;;UAGJ,SAAA;UACR;cACI;UACJ;gBACM;;;cAGF;;;;;;;;;;UAUJ;;;;;;;;iCAQuB;;;;;;;;;;8BAUH;;;;;;;;;;;;;;;;;;;sBAmBR;;YAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BD"}
1
+ {"version":3,"file":"types-BqAbYt5a.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;AAYY,UALK,iBAAA,CAKwB;EAaxB,KAAA,EAAA,MAAA,GAAA,MAAc,EAAA;EAKd,SAAA,EAAA,CAAA,QAAA,EAAoB,MAAA,EAAA,GAAQ,MAAA;AAI7C;AAIiB,KA1BL,MAAA,GA0BK,MAAgB,GAAA,MAAA,EAAA,GA1BQ,iBA0BR;AAkDrB,UA/DK,cAAA,CA+DQ;EAGb,OAAA,CAAA,EAAA,OAAA;EASA,SAAA,CAAA,EAAA,MAAA;;AACL,UAvEU,mBAAA,SAA4B,cAuEtC,CAAA;AAA6C,UAnEnC,eAAA,SAAwB,cAmEW,CAAA,CAGpD;AAA6B,UAlEZ,gBAAA,CAkEY;EAAA;EAwBK,OAAG,CAAA,EAAA,OAAA;EAAkB;EAItC,MAAA,CAAA,EAAA,OAAa;EAAA;EAAA,MAIhB,CAAA,EAAA,OAAA;EAAgB;EAJsB,WAAA,CAAA,EAAA,MAAA;EAOxC;EAEK,gBAAA,CAAA,EAAe,OAAA;EAiBf;EASA,QAAA,CAAA,EAAA,MAAa,EAAA;EAWb;EA6BA,WAAA,CAAA,EAAA,SAAA,GAAqB,SAAA;EAarB;EAAe,OAAA,CAAA,EAAA,OAAA;EAAA;;;;;;AAaU;EAGzB,iBAAS,CAAA,EAAA,OAAA;;;AAEb,UA5KI,aAAA,CA4KJ;EAAM;;;;EAeC,KAQY,CAAA,EAAA,MAAA;EAAe;;;;EA2DzB,OAAA,CAAA,EAAA,MAAA;;;;;;;;;;;KAxOV,aAAA;;KAGA,kBAAA;;KASA,qBAAA,WACL,gCAAgC;UAGtB,YAAA;;;;;;;;;;;;;;;;;;;;;;;;eAwBJ,wBAAwB;;;UAIpB,YAAA,SAAqB;;;;eAIxB;;KAGF,OAAA;UAEK,eAAA;;;;;;;;;;;;;;;;UAiBA,YAAA;;;;;;;;UASA,aAAA;;;;;;;;;;UAWA,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA6BA,qBAAA;;;;;;;;;;;;UAaA,eAAA;;;qBAGC;qBACA;;;4BAGO;wBACJ;;;qBAGD;;sBAEC;;UAGJ,SAAA;UACR;cACI;UACJ;gBACM;;;cAGF;;;;;;;;;;UAUJ;;;;;;;;iCAQuB;;;;;;;;;;8BAUH;;;;;;;;;;;;;;;;;;;sBAmBR;;YAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BD"}
@@ -1,4 +1,4 @@
1
- const require_workspace = require('../workspace-4SP3Gx4Y.cjs');
1
+ const require_workspace = require('../workspace-CGYykWfn.cjs');
2
2
 
3
3
  exports.PHASE_2_DEPLOY_TARGETS = require_workspace.PHASE_2_DEPLOY_TARGETS;
4
4
  exports.SUPPORTED_DEPLOY_TARGETS = require_workspace.SUPPORTED_DEPLOY_TARGETS;
@@ -1,3 +1,3 @@
1
1
  import "../types-DdHfUbxk.cjs";
2
- import { AppConfig, AppConfigInput, AppInput, AppsRecord, BackendFramework, ClientConfig, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, FrontendFramework, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace } from "../index-BkibYzso.cjs";
3
- export { AppConfig, AppConfigInput, AppInput, AppsRecord, BackendFramework, ClientConfig, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, FrontendFramework, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace };
2
+ import { AppConfig, AppConfigInput, AppInput, AppsRecord, BackendFramework, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, FrontendFramework, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace } from "../index-C3t5VL4R.cjs";
3
+ export { AppConfig, AppConfigInput, AppInput, AppsRecord, BackendFramework, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, FrontendFramework, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace };
@@ -1,3 +1,3 @@
1
- import "../types-OszPdw9m.mjs";
2
- import { AppConfig, AppConfigInput, AppInput, AppsRecord, BackendFramework, ClientConfig, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, FrontendFramework, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace } from "../index-CY-ieuRp.mjs";
3
- export { AppConfig, AppConfigInput, AppInput, AppsRecord, BackendFramework, ClientConfig, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, FrontendFramework, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace };
1
+ import "../types-BqAbYt5a.mjs";
2
+ import { AppConfig, AppConfigInput, AppInput, AppsRecord, BackendFramework, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, FrontendFramework, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace } from "../index-C-_rW4KF.mjs";
3
+ export { AppConfig, AppConfigInput, AppInput, AppsRecord, BackendFramework, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, FrontendFramework, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace };
@@ -1,3 +1,3 @@
1
- import { PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, WorkspaceConfigSchema, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace } from "../workspace-D4z4A4cq.mjs";
1
+ import { PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, WorkspaceConfigSchema, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace } from "../workspace-Bi4X7Yzy.mjs";
2
2
 
3
3
  export { PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, WorkspaceConfigSchema, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace };
@@ -3401,10 +3401,6 @@ const OpenApiConfigSchema = object({
3401
3401
  */
3402
3402
  const HooksConfigSchema = object({ server: string().optional() });
3403
3403
  /**
3404
- * Client generation configuration schema.
3405
- */
3406
- const ClientConfigSchema = object({ output: string().optional() });
3407
- /**
3408
3404
  * Auth provider schema.
3409
3405
  * Currently only 'better-auth' is supported.
3410
3406
  */
@@ -3768,7 +3764,6 @@ const AppConfigSchema = object({
3768
3764
  env: union([string(), array(string())]).optional(),
3769
3765
  entry: string().optional(),
3770
3766
  framework: FrameworkSchema.optional(),
3771
- client: ClientConfigSchema.optional(),
3772
3767
  config: object({
3773
3768
  client: string().optional(),
3774
3769
  server: string().optional()
@@ -4176,4 +4171,4 @@ function getEndpointForStage(dokployConfig, stage) {
4176
4171
 
4177
4172
  //#endregion
4178
4173
  export { PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, WorkspaceConfigSchema, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, getEndpointForStage, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace };
4179
- //# sourceMappingURL=workspace-D4z4A4cq.mjs.map
4174
+ //# sourceMappingURL=workspace-Bi4X7Yzy.mjs.map