@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.
- package/CHANGELOG.md +18 -0
- package/dist/{CachedStateProvider-37pG1HBx.cjs → CachedStateProvider-3couMAQk.cjs} +1 -1
- package/dist/CachedStateProvider-C4QqvlPE.mjs +3 -0
- package/dist/{CachedStateProvider-C8A-cCm5.mjs → CachedStateProvider-CQr31ups.mjs} +1 -1
- package/dist/{CachedStateProvider-C8A-cCm5.mjs.map → CachedStateProvider-CQr31ups.mjs.map} +1 -1
- package/dist/{CachedStateProvider-CxsXOKkg.cjs → CachedStateProvider-Cyn17x3x.cjs} +1 -1
- package/dist/{CachedStateProvider-CxsXOKkg.cjs.map → CachedStateProvider-Cyn17x3x.cjs.map} +1 -1
- package/dist/{HostingerProvider-5KYmwoK2.cjs → HostingerProvider-C5oLa7N7.cjs} +1 -1
- package/dist/{HostingerProvider-5KYmwoK2.cjs.map → HostingerProvider-C5oLa7N7.cjs.map} +1 -1
- package/dist/{HostingerProvider-ANWchdiK.mjs → HostingerProvider-YvCg3Mus.mjs} +1 -1
- package/dist/{HostingerProvider-ANWchdiK.mjs.map → HostingerProvider-YvCg3Mus.mjs.map} +1 -1
- package/dist/{LocalStateProvider-Dp0KkRcw.mjs → LocalStateProvider-BciOhGR0.mjs} +1 -1
- package/dist/{LocalStateProvider-Dp0KkRcw.mjs.map → LocalStateProvider-BciOhGR0.mjs.map} +1 -1
- package/dist/{LocalStateProvider-CLifRC0Y.cjs → LocalStateProvider-DI6n11UM.cjs} +1 -1
- package/dist/{LocalStateProvider-CLifRC0Y.cjs.map → LocalStateProvider-DI6n11UM.cjs.map} +1 -1
- package/dist/{Route53Provider-QoPgcXxn.mjs → Route53Provider-CYlDOrYO.mjs} +1 -1
- package/dist/{Route53Provider-QoPgcXxn.mjs.map → Route53Provider-CYlDOrYO.mjs.map} +1 -1
- package/dist/{Route53Provider-owQQ4pn6.cjs → Route53Provider-DISZ6E8f.cjs} +1 -1
- package/dist/{Route53Provider-owQQ4pn6.cjs.map → Route53Provider-DISZ6E8f.cjs.map} +1 -1
- package/dist/{SSMStateProvider-CT8tjl9o.cjs → SSMStateProvider-BljH5efc.cjs} +1 -1
- package/dist/{SSMStateProvider-CT8tjl9o.cjs.map → SSMStateProvider-BljH5efc.cjs.map} +1 -1
- package/dist/{SSMStateProvider-CksOTB8M.mjs → SSMStateProvider-DXT1dIdI.mjs} +1 -1
- package/dist/{SSMStateProvider-CksOTB8M.mjs.map → SSMStateProvider-DXT1dIdI.mjs.map} +1 -1
- package/dist/{backup-provisioner-BEXoHTuC.mjs → backup-provisioner-CCUcj28C.mjs} +1 -1
- package/dist/{backup-provisioner-BEXoHTuC.mjs.map → backup-provisioner-CCUcj28C.mjs.map} +1 -1
- package/dist/{backup-provisioner-C4noe75O.cjs → backup-provisioner-CpirEvO1.cjs} +1 -1
- package/dist/{backup-provisioner-C4noe75O.cjs.map → backup-provisioner-CpirEvO1.cjs.map} +1 -1
- package/dist/{bundler-BG6P249p.cjs → bundler-CLOenWgi.cjs} +2 -2
- package/dist/{bundler-BG6P249p.cjs.map → bundler-CLOenWgi.cjs.map} +1 -1
- package/dist/{bundler-c6QvGUBM.mjs → bundler-E5VcXsPH.mjs} +2 -2
- package/dist/{bundler-c6QvGUBM.mjs.map → bundler-E5VcXsPH.mjs.map} +1 -1
- package/dist/client-generator-CUVVtAOo.mjs +23 -0
- package/dist/client-generator-CUVVtAOo.mjs.map +1 -0
- package/dist/client-generator-D-T4ypQo.cjs +35 -0
- package/dist/client-generator-D-T4ypQo.cjs.map +1 -0
- package/dist/{config-jsRYHOHU.mjs → config-B62g483e.mjs} +2 -2
- package/dist/{config-jsRYHOHU.mjs.map → config-B62g483e.mjs.map} +1 -1
- package/dist/{config-D3ORuiUs.cjs → config-Cuo8vFsp.cjs} +2 -2
- package/dist/{config-D3ORuiUs.cjs.map → config-Cuo8vFsp.cjs.map} +1 -1
- package/dist/config.cjs +2 -2
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +2 -2
- package/dist/config.mjs +2 -2
- package/dist/deploy/sniffer-worker.cjs +2 -0
- package/dist/deploy/sniffer-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-worker.mjs +2 -0
- package/dist/deploy/sniffer-worker.mjs.map +1 -1
- package/dist/dokploy-api-BPYkG-ZZ.cjs +3 -0
- package/dist/dokploy-api-BiSzWM4v.mjs +3 -0
- package/dist/{dokploy-api-Dvyq-LsM.cjs → dokploy-api-CqOIKHme.cjs} +1 -1
- package/dist/{dokploy-api-Dvyq-LsM.cjs.map → dokploy-api-CqOIKHme.cjs.map} +1 -1
- package/dist/{dokploy-api-BIT0683o.mjs → dokploy-api-sfZFlWuE.mjs} +1 -1
- package/dist/{dokploy-api-BIT0683o.mjs.map → dokploy-api-sfZFlWuE.mjs.map} +1 -1
- package/dist/{encryption-CipsS0KW.cjs → encryption-BVS7Vmzs.cjs} +1 -1
- package/dist/encryption-Bd_m4q3g.mjs +3 -0
- package/dist/{encryption-DSkIlEZ6.mjs → encryption-CO5Q4Bhf.mjs} +1 -1
- package/dist/{encryption-DSkIlEZ6.mjs.map → encryption-CO5Q4Bhf.mjs.map} +1 -1
- package/dist/{encryption-DgKS-Dv9.cjs → encryption-MfXAiFTm.cjs} +1 -1
- package/dist/{encryption-DgKS-Dv9.cjs.map → encryption-MfXAiFTm.cjs.map} +1 -1
- package/dist/{index-CY-ieuRp.d.mts → index-C-_rW4KF.d.mts} +3 -33
- package/dist/index-C-_rW4KF.d.mts.map +1 -0
- package/dist/{index-BkibYzso.d.cts → index-C3t5VL4R.d.cts} +2 -32
- package/dist/index-C3t5VL4R.d.cts.map +1 -0
- package/dist/index.cjs +102 -380
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +78 -356
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-CQCoLuzh.mjs → openapi-DHq5r17U.mjs} +7 -42
- package/dist/openapi-DHq5r17U.mjs.map +1 -0
- package/dist/{openapi-react-query-C4UdILaI.mjs → openapi-react-query-COpH7Mmz.mjs} +1 -1
- package/dist/{openapi-react-query-C4UdILaI.mjs.map → openapi-react-query-COpH7Mmz.mjs.map} +1 -1
- package/dist/{openapi-react-query-DYbBq-WJ.cjs → openapi-react-query-CxyQTTdF.cjs} +1 -1
- package/dist/{openapi-react-query-DYbBq-WJ.cjs.map → openapi-react-query-CxyQTTdF.cjs.map} +1 -1
- package/dist/openapi-react-query.cjs +1 -1
- package/dist/openapi-react-query.mjs +1 -1
- package/dist/{openapi-CBU4TEi-.cjs → openapi-w-_smBTO.cjs} +7 -54
- package/dist/openapi-w-_smBTO.cjs.map +1 -0
- package/dist/openapi.cjs +4 -3
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +4 -3
- package/dist/{reconcile-CZtzdrnc.cjs → reconcile-C8KIy4Uy.cjs} +1 -1
- package/dist/{reconcile-CZtzdrnc.cjs.map → reconcile-C8KIy4Uy.cjs.map} +1 -1
- package/dist/{reconcile-DAAKa0YR.mjs → reconcile-D423q2QW.mjs} +1 -1
- package/dist/{reconcile-DAAKa0YR.mjs.map → reconcile-D423q2QW.mjs.map} +1 -1
- package/dist/sniffer-BqSVVrWA.mjs +356 -0
- package/dist/sniffer-BqSVVrWA.mjs.map +1 -0
- package/dist/sniffer-CBhzByiY.cjs +386 -0
- package/dist/sniffer-CBhzByiY.cjs.map +1 -0
- package/dist/sniffer-Cpq_cbyz.mjs +4 -0
- package/dist/sniffer-eZ13G10M.cjs +4 -0
- package/dist/sync-B2CN_KS5.cjs +4 -0
- package/dist/{sync-DGXXSk2v.cjs → sync-BWY6yoUG.cjs} +1 -1
- package/dist/{sync-DGXXSk2v.cjs.map → sync-BWY6yoUG.cjs.map} +1 -1
- package/dist/{sync-D_NowTkZ.mjs → sync-Dc-QA4Mx.mjs} +1 -1
- package/dist/{sync-D_NowTkZ.mjs.map → sync-Dc-QA4Mx.mjs.map} +1 -1
- package/dist/{sync-COnAugP-.mjs → sync-fzT5WX_y.mjs} +1 -1
- package/dist/{types-OszPdw9m.d.mts → types-BqAbYt5a.d.mts} +1 -1
- package/dist/{types-OszPdw9m.d.mts.map → types-BqAbYt5a.d.mts.map} +1 -1
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-D4z4A4cq.mjs → workspace-Bi4X7Yzy.mjs} +1 -6
- package/dist/{workspace-D4z4A4cq.mjs.map → workspace-Bi4X7Yzy.mjs.map} +1 -1
- package/dist/{workspace-4SP3Gx4Y.cjs → workspace-CGYykWfn.cjs} +1 -6
- package/dist/{workspace-4SP3Gx4Y.cjs.map → workspace-CGYykWfn.cjs.map} +1 -1
- package/package.json +3 -3
- package/src/__tests__/openapi.spec.ts +0 -315
- package/src/build/__tests__/manifests.spec.ts +66 -0
- package/src/build/index.ts +54 -1
- package/src/deploy/__tests__/__fixtures__/env-parsers/optional-env-parser.ts +21 -0
- package/src/deploy/__tests__/sniffer.spec.ts +123 -0
- package/src/deploy/sniffer-worker.ts +2 -1
- package/src/deploy/sniffer.ts +86 -12
- package/src/docker/compose.ts +2 -0
- package/src/generators/EndpointGenerator.ts +1 -1
- package/src/index.ts +8 -0
- package/src/init/generators/monorepo.ts +15 -1
- package/src/init/generators/package.ts +2 -0
- package/src/init/index.ts +2 -4
- package/src/init/templates/index.ts +5 -0
- package/src/init/versions.ts +1 -1
- package/src/openapi.ts +1 -35
- package/src/types.ts +7 -0
- package/src/workspace/__tests__/client-generator.spec.ts +1 -485
- package/src/workspace/client-generator.ts +1 -145
- package/src/workspace/index.ts +0 -1
- package/src/workspace/schema.ts +0 -9
- package/src/workspace/types.ts +0 -29
- package/dist/CachedStateProvider-CC0DyO09.mjs +0 -3
- package/dist/dokploy-api-BOx71j6F.cjs +0 -3
- package/dist/dokploy-api-BZGk-lkD.mjs +0 -3
- package/dist/encryption-Db2zvGqM.mjs +0 -3
- package/dist/index-BkibYzso.d.cts.map +0 -1
- package/dist/index-CY-ieuRp.d.mts.map +0 -1
- package/dist/openapi-CBU4TEi-.cjs.map +0 -1
- package/dist/openapi-CQCoLuzh.mjs.map +0 -1
- package/dist/sync-D1Pa30oV.cjs +0 -4
package/src/deploy/sniffer.ts
CHANGED
|
@@ -60,7 +60,17 @@ export type { SniffResult } from '@geekmidas/envkit/sniffer';
|
|
|
60
60
|
*/
|
|
61
61
|
export interface SniffedEnvironment {
|
|
62
62
|
appName: string;
|
|
63
|
+
/**
|
|
64
|
+
* All required environment variable names.
|
|
65
|
+
* When `SniffAppOptions.markOptional` is true, optional variables are
|
|
66
|
+
* suffixed with `?` (e.g. `PORT?`).
|
|
67
|
+
*/
|
|
63
68
|
requiredEnvVars: string[];
|
|
69
|
+
/**
|
|
70
|
+
* Subset of variables that are optional (accessed via `.optional()` or
|
|
71
|
+
* `.default()`). Always populated regardless of `markOptional`.
|
|
72
|
+
*/
|
|
73
|
+
optionalEnvVars: string[];
|
|
64
74
|
}
|
|
65
75
|
|
|
66
76
|
/**
|
|
@@ -69,6 +79,12 @@ export interface SniffedEnvironment {
|
|
|
69
79
|
export interface SniffAppOptions {
|
|
70
80
|
/** Whether to log warnings for errors encountered during sniffing. Defaults to true. */
|
|
71
81
|
logWarnings?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* When true, optional variables (those with `.optional()` or `.default()`)
|
|
84
|
+
* are suffixed with `?` in `requiredEnvVars` (e.g. `PORT?`).
|
|
85
|
+
* Defaults to false.
|
|
86
|
+
*/
|
|
87
|
+
markOptional?: boolean;
|
|
72
88
|
}
|
|
73
89
|
|
|
74
90
|
/**
|
|
@@ -97,7 +113,7 @@ export async function sniffAppEnvironment(
|
|
|
97
113
|
workspacePath: string,
|
|
98
114
|
options: SniffAppOptions = {},
|
|
99
115
|
): Promise<SniffedEnvironment> {
|
|
100
|
-
const { logWarnings = true } = options;
|
|
116
|
+
const { logWarnings = true, markOptional = false } = options;
|
|
101
117
|
|
|
102
118
|
// 1. Frontend apps - handle dependencies and config sniffing
|
|
103
119
|
if (app.type === 'frontend') {
|
|
@@ -110,6 +126,7 @@ export async function sniffAppEnvironment(
|
|
|
110
126
|
// The file calls .parse() at module load, which triggers sniffer to capture vars
|
|
111
127
|
if (app.config) {
|
|
112
128
|
const sniffedVars: string[] = [];
|
|
129
|
+
const sniffedOptional: string[] = [];
|
|
113
130
|
|
|
114
131
|
// Collect config paths to sniff
|
|
115
132
|
const configPaths: string[] = [];
|
|
@@ -131,14 +148,20 @@ export async function sniffAppEnvironment(
|
|
|
131
148
|
}
|
|
132
149
|
|
|
133
150
|
sniffedVars.push(...result.envVars);
|
|
151
|
+
sniffedOptional.push(...result.optionalEnvVars);
|
|
134
152
|
}
|
|
135
153
|
|
|
154
|
+
const optionalEnvVars = [...new Set(sniffedOptional)];
|
|
136
155
|
// Combine: dependency vars + sniffed vars (deduplicated)
|
|
137
|
-
const allVars =
|
|
138
|
-
|
|
156
|
+
const allVars = applyMarkOptional(
|
|
157
|
+
[...new Set([...depVars, ...sniffedVars])],
|
|
158
|
+
optionalEnvVars,
|
|
159
|
+
markOptional,
|
|
160
|
+
);
|
|
161
|
+
return { appName, requiredEnvVars: allVars, optionalEnvVars };
|
|
139
162
|
}
|
|
140
163
|
|
|
141
|
-
return { appName, requiredEnvVars: depVars };
|
|
164
|
+
return { appName, requiredEnvVars: depVars, optionalEnvVars: [] };
|
|
142
165
|
}
|
|
143
166
|
|
|
144
167
|
// 2. Entry apps - import entry file in subprocess to trigger config.parse()
|
|
@@ -151,7 +174,15 @@ export async function sniffAppEnvironment(
|
|
|
151
174
|
);
|
|
152
175
|
}
|
|
153
176
|
|
|
154
|
-
return {
|
|
177
|
+
return {
|
|
178
|
+
appName,
|
|
179
|
+
requiredEnvVars: applyMarkOptional(
|
|
180
|
+
result.envVars,
|
|
181
|
+
result.optionalEnvVars,
|
|
182
|
+
markOptional,
|
|
183
|
+
),
|
|
184
|
+
optionalEnvVars: result.optionalEnvVars,
|
|
185
|
+
};
|
|
155
186
|
}
|
|
156
187
|
|
|
157
188
|
// 4. Route-based apps - load routes and call getEnvironment() on each construct
|
|
@@ -168,7 +199,15 @@ export async function sniffAppEnvironment(
|
|
|
168
199
|
);
|
|
169
200
|
}
|
|
170
201
|
|
|
171
|
-
return {
|
|
202
|
+
return {
|
|
203
|
+
appName,
|
|
204
|
+
requiredEnvVars: applyMarkOptional(
|
|
205
|
+
result.envVars,
|
|
206
|
+
result.optionalEnvVars,
|
|
207
|
+
markOptional,
|
|
208
|
+
),
|
|
209
|
+
optionalEnvVars: result.optionalEnvVars,
|
|
210
|
+
};
|
|
172
211
|
}
|
|
173
212
|
|
|
174
213
|
// 5. Apps with envParser but no routes - run sniffer to detect env var usage
|
|
@@ -189,11 +228,33 @@ export async function sniffAppEnvironment(
|
|
|
189
228
|
}
|
|
190
229
|
}
|
|
191
230
|
|
|
192
|
-
return {
|
|
231
|
+
return {
|
|
232
|
+
appName,
|
|
233
|
+
requiredEnvVars: applyMarkOptional(
|
|
234
|
+
result.envVars,
|
|
235
|
+
result.optionalEnvVars,
|
|
236
|
+
markOptional,
|
|
237
|
+
),
|
|
238
|
+
optionalEnvVars: result.optionalEnvVars,
|
|
239
|
+
};
|
|
193
240
|
}
|
|
194
241
|
|
|
195
|
-
//
|
|
196
|
-
return { appName, requiredEnvVars: [] };
|
|
242
|
+
// No env detection method available
|
|
243
|
+
return { appName, requiredEnvVars: [], optionalEnvVars: [] };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Apply the `?` suffix to optional variables in an env var list.
|
|
248
|
+
* Only modifies the list when `markOptional` is true and there are optional vars.
|
|
249
|
+
*/
|
|
250
|
+
function applyMarkOptional(
|
|
251
|
+
envVars: string[],
|
|
252
|
+
optionalEnvVars: string[],
|
|
253
|
+
markOptional: boolean,
|
|
254
|
+
): string[] {
|
|
255
|
+
if (!markOptional || optionalEnvVars.length === 0) return envVars;
|
|
256
|
+
const optionalSet = new Set(optionalEnvVars);
|
|
257
|
+
return envVars.map((v) => (optionalSet.has(v) ? `${v}?` : v));
|
|
197
258
|
}
|
|
198
259
|
|
|
199
260
|
/**
|
|
@@ -201,6 +262,7 @@ export async function sniffAppEnvironment(
|
|
|
201
262
|
*/
|
|
202
263
|
interface EntrySniffResult {
|
|
203
264
|
envVars: string[];
|
|
265
|
+
optionalEnvVars: string[];
|
|
204
266
|
error?: Error;
|
|
205
267
|
}
|
|
206
268
|
|
|
@@ -267,6 +329,7 @@ async function sniffEntryFile(
|
|
|
267
329
|
const result = JSON.parse(jsonMatch[0]);
|
|
268
330
|
resolvePromise({
|
|
269
331
|
envVars: result.envVars || [],
|
|
332
|
+
optionalEnvVars: result.optionalEnvVars || [],
|
|
270
333
|
error: result.error ? new Error(result.error) : undefined,
|
|
271
334
|
});
|
|
272
335
|
return;
|
|
@@ -278,6 +341,7 @@ async function sniffEntryFile(
|
|
|
278
341
|
// If we couldn't parse the output, return empty with error info
|
|
279
342
|
resolvePromise({
|
|
280
343
|
envVars: [],
|
|
344
|
+
optionalEnvVars: [],
|
|
281
345
|
error: new Error(
|
|
282
346
|
`Failed to sniff entry file (exit code ${code}): ${stderr || stdout || 'No output'}`,
|
|
283
347
|
),
|
|
@@ -287,6 +351,7 @@ async function sniffEntryFile(
|
|
|
287
351
|
child.on('error', (err) => {
|
|
288
352
|
resolvePromise({
|
|
289
353
|
envVars: [],
|
|
354
|
+
optionalEnvVars: [],
|
|
290
355
|
error: err,
|
|
291
356
|
});
|
|
292
357
|
});
|
|
@@ -320,7 +385,11 @@ async function sniffRouteFiles(
|
|
|
320
385
|
const routesArray = Array.isArray(routes) ? routes : [routes];
|
|
321
386
|
const pattern = routesArray[0];
|
|
322
387
|
if (!pattern) {
|
|
323
|
-
return {
|
|
388
|
+
return {
|
|
389
|
+
envVars: [],
|
|
390
|
+
optionalEnvVars: [],
|
|
391
|
+
error: new Error('No route patterns provided'),
|
|
392
|
+
};
|
|
324
393
|
}
|
|
325
394
|
|
|
326
395
|
return new Promise((resolvePromise) => {
|
|
@@ -364,6 +433,9 @@ async function sniffRouteFiles(
|
|
|
364
433
|
const result = JSON.parse(jsonMatch[0]);
|
|
365
434
|
resolvePromise({
|
|
366
435
|
envVars: result.envVars || [],
|
|
436
|
+
// Routes worker uses getEnvironment() which doesn't track
|
|
437
|
+
// optionality yet — populated when service register() is sniffed
|
|
438
|
+
optionalEnvVars: result.optionalEnvVars || [],
|
|
367
439
|
error: result.error ? new Error(result.error) : undefined,
|
|
368
440
|
});
|
|
369
441
|
return;
|
|
@@ -375,6 +447,7 @@ async function sniffRouteFiles(
|
|
|
375
447
|
// If we couldn't parse the output, return empty with error info
|
|
376
448
|
resolvePromise({
|
|
377
449
|
envVars: [],
|
|
450
|
+
optionalEnvVars: [],
|
|
378
451
|
error: new Error(
|
|
379
452
|
`Failed to sniff route files (exit code ${code}): ${stderr || stdout || 'No output'}`,
|
|
380
453
|
),
|
|
@@ -384,6 +457,7 @@ async function sniffRouteFiles(
|
|
|
384
457
|
child.on('error', (err) => {
|
|
385
458
|
resolvePromise({
|
|
386
459
|
envVars: [],
|
|
460
|
+
optionalEnvVars: [],
|
|
387
461
|
error: err,
|
|
388
462
|
});
|
|
389
463
|
});
|
|
@@ -410,7 +484,7 @@ async function sniffEnvParser(
|
|
|
410
484
|
// Parse the envParser path: './src/config/env#envParser' or './src/config/env'
|
|
411
485
|
const [modulePath, exportName = 'default'] = envParserPath.split('#');
|
|
412
486
|
if (!modulePath) {
|
|
413
|
-
return { envVars: [], unhandledRejections: [] };
|
|
487
|
+
return { envVars: [], optionalEnvVars: [], unhandledRejections: [] };
|
|
414
488
|
}
|
|
415
489
|
|
|
416
490
|
// Resolve the full path to the module
|
|
@@ -428,7 +502,7 @@ async function sniffEnvParser(
|
|
|
428
502
|
console.warn(
|
|
429
503
|
`[sniffer] Failed to import SnifferEnvironmentParser: ${message}`,
|
|
430
504
|
);
|
|
431
|
-
return { envVars: [], unhandledRejections: [] };
|
|
505
|
+
return { envVars: [], optionalEnvVars: [], unhandledRejections: [] };
|
|
432
506
|
}
|
|
433
507
|
|
|
434
508
|
const sniffer = new SnifferEnvironmentParser();
|
package/src/docker/compose.ts
CHANGED
|
@@ -280,6 +280,7 @@ services:
|
|
|
280
280
|
restart: unless-stopped
|
|
281
281
|
environment:
|
|
282
282
|
MP_SMTP_AUTH: \${SMTP_USER:-${imageName}}:\${SMTP_PASS:-${imageName}}
|
|
283
|
+
MP_SMTP_AUTH_ALLOW_INSECURE: true
|
|
283
284
|
ports:
|
|
284
285
|
- "\${MAILPIT_PORT:-8025}:8025" # Web UI / API
|
|
285
286
|
- "\${SMTP_PORT:-1025}:1025" # SMTP
|
|
@@ -505,6 +506,7 @@ services:
|
|
|
505
506
|
restart: unless-stopped
|
|
506
507
|
environment:
|
|
507
508
|
MP_SMTP_AUTH: \${SMTP_USER:-${workspace.name}}:\${SMTP_PASS:-${workspace.name}}
|
|
509
|
+
MP_SMTP_AUTH_ALLOW_INSECURE: true
|
|
508
510
|
ports:
|
|
509
511
|
- "\${MAILPIT_PORT:-8025}:8025" # Web UI / API
|
|
510
512
|
- "\${SMTP_PORT:-1025}:1025" # SMTP
|
|
@@ -305,7 +305,7 @@ import { ServiceDiscovery } from '@geekmidas/services';
|
|
|
305
305
|
import type { Hono } from 'hono';
|
|
306
306
|
${endpointImports}
|
|
307
307
|
|
|
308
|
-
const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any, any, any>[] = [
|
|
308
|
+
export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any, any, any>[] = [
|
|
309
309
|
${allExportNames.join(',\n ')}
|
|
310
310
|
];
|
|
311
311
|
|
package/src/index.ts
CHANGED
|
@@ -107,6 +107,10 @@ program
|
|
|
107
107
|
.option('--production', 'Build for production (no dev tools, bundled output)')
|
|
108
108
|
.option('--skip-bundle', 'Skip bundling step in production build')
|
|
109
109
|
.option('--stage <stage>', 'Inject encrypted secrets for deployment stage')
|
|
110
|
+
.option(
|
|
111
|
+
'--mark-optional',
|
|
112
|
+
'Suffix optional env vars with ? in manifest envVars field (e.g. PORT?)',
|
|
113
|
+
)
|
|
110
114
|
.action(
|
|
111
115
|
async (options: {
|
|
112
116
|
provider?: string;
|
|
@@ -115,6 +119,7 @@ program
|
|
|
115
119
|
production?: boolean;
|
|
116
120
|
skipBundle?: boolean;
|
|
117
121
|
stage?: string;
|
|
122
|
+
markOptional?: boolean;
|
|
118
123
|
}) => {
|
|
119
124
|
try {
|
|
120
125
|
const globalOptions = program.opts();
|
|
@@ -133,6 +138,7 @@ program
|
|
|
133
138
|
production: options.production || false,
|
|
134
139
|
skipBundle: options.skipBundle || false,
|
|
135
140
|
stage: options.stage,
|
|
141
|
+
markOptional: options.markOptional || false,
|
|
136
142
|
});
|
|
137
143
|
}
|
|
138
144
|
// Handle legacy providers option
|
|
@@ -146,6 +152,7 @@ program
|
|
|
146
152
|
production: options.production || false,
|
|
147
153
|
skipBundle: options.skipBundle || false,
|
|
148
154
|
stage: options.stage,
|
|
155
|
+
markOptional: options.markOptional || false,
|
|
149
156
|
});
|
|
150
157
|
}
|
|
151
158
|
// Default to config-driven build
|
|
@@ -155,6 +162,7 @@ program
|
|
|
155
162
|
production: options.production || false,
|
|
156
163
|
skipBundle: options.skipBundle || false,
|
|
157
164
|
stage: options.stage,
|
|
165
|
+
markOptional: options.markOptional || false,
|
|
158
166
|
});
|
|
159
167
|
}
|
|
160
168
|
} catch (error) {
|
|
@@ -389,7 +389,13 @@ export default defineWorkspace({
|
|
|
389
389
|
},`;
|
|
390
390
|
|
|
391
391
|
// Add services if any are selected
|
|
392
|
-
if (
|
|
392
|
+
if (
|
|
393
|
+
services.db ||
|
|
394
|
+
services.cache ||
|
|
395
|
+
services.mail ||
|
|
396
|
+
services.storage ||
|
|
397
|
+
services.events
|
|
398
|
+
) {
|
|
393
399
|
config += `
|
|
394
400
|
services: {`;
|
|
395
401
|
if (services.db) {
|
|
@@ -403,6 +409,14 @@ export default defineWorkspace({
|
|
|
403
409
|
if (services.mail) {
|
|
404
410
|
config += `
|
|
405
411
|
mail: true,`;
|
|
412
|
+
}
|
|
413
|
+
if (services.storage) {
|
|
414
|
+
config += `
|
|
415
|
+
storage: true,`;
|
|
416
|
+
}
|
|
417
|
+
if (services.events) {
|
|
418
|
+
config += `
|
|
419
|
+
events: '${services.events}',`;
|
|
406
420
|
}
|
|
407
421
|
config += `
|
|
408
422
|
},`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ENDPOINTS_OUTPUT_PATH,
|
|
2
3
|
type GeneratedFile,
|
|
3
4
|
OPENAPI_OUTPUT_PATH,
|
|
4
5
|
type TemplateConfig,
|
|
@@ -78,6 +79,7 @@ export function generatePackageJson(
|
|
|
78
79
|
type: 'module',
|
|
79
80
|
exports: {
|
|
80
81
|
'./client': OPENAPI_OUTPUT_PATH,
|
|
82
|
+
'./endpoints': ENDPOINTS_OUTPUT_PATH,
|
|
81
83
|
},
|
|
82
84
|
scripts,
|
|
83
85
|
dependencies: sortObject(dependencies),
|
package/src/init/index.ts
CHANGED
|
@@ -192,11 +192,9 @@ export async function initCommand(
|
|
|
192
192
|
? ['db', 'cache', 'mail', 'storage']
|
|
193
193
|
: answers.services || [];
|
|
194
194
|
|
|
195
|
-
// Determine events backend (default to pgboss for
|
|
195
|
+
// Determine events backend (default to pgboss for all templates with --yes)
|
|
196
196
|
const eventsBackend: EventsBackend | undefined = options.yes
|
|
197
|
-
?
|
|
198
|
-
? 'pgboss'
|
|
199
|
-
: undefined
|
|
197
|
+
? 'pgboss'
|
|
200
198
|
: answers.eventsBackend;
|
|
201
199
|
|
|
202
200
|
const services: ServicesSelection = {
|
|
@@ -8,6 +8,11 @@ import { workerTemplate } from './worker.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export const OPENAPI_OUTPUT_PATH = './.gkm/openapi.ts';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Endpoints output path (generated by gkm dev/build)
|
|
13
|
+
*/
|
|
14
|
+
export const ENDPOINTS_OUTPUT_PATH = './.gkm/server/endpoints.ts';
|
|
15
|
+
|
|
11
16
|
/**
|
|
12
17
|
* Logger implementation type
|
|
13
18
|
*/
|
package/src/init/versions.ts
CHANGED
|
@@ -32,7 +32,7 @@ export const GEEKMIDAS_VERSIONS = {
|
|
|
32
32
|
'@geekmidas/cache': '~1.1.0',
|
|
33
33
|
'@geekmidas/client': '~4.0.4',
|
|
34
34
|
'@geekmidas/cloud': '~1.0.0',
|
|
35
|
-
'@geekmidas/constructs': '~3.0.
|
|
35
|
+
'@geekmidas/constructs': '~3.0.7',
|
|
36
36
|
'@geekmidas/db': '~1.0.1',
|
|
37
37
|
'@geekmidas/emailkit': '~1.0.0',
|
|
38
38
|
'@geekmidas/envkit': '~1.0.4',
|
package/src/openapi.ts
CHANGED
|
@@ -115,7 +115,7 @@ export async function openapiCommand(
|
|
|
115
115
|
logger.log(`Found ${result.endpointCount} endpoints`);
|
|
116
116
|
}
|
|
117
117
|
} else {
|
|
118
|
-
// Workspace config - generate for each backend app
|
|
118
|
+
// Workspace config - generate for each backend app
|
|
119
119
|
const { workspace } = loadedConfig;
|
|
120
120
|
const workspaceRoot = options.cwd || process.cwd();
|
|
121
121
|
|
|
@@ -132,11 +132,6 @@ export async function openapiCommand(
|
|
|
132
132
|
return;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
// Find frontend apps with client config
|
|
136
|
-
const frontendApps = Object.entries(workspace.apps).filter(
|
|
137
|
-
([_, app]) => app.type === 'frontend' && app.client?.output,
|
|
138
|
-
);
|
|
139
|
-
|
|
140
135
|
// Generate OpenAPI for each backend app
|
|
141
136
|
for (const [appName, app] of backendApps) {
|
|
142
137
|
if (app.type !== 'backend' || !app.routes) continue;
|
|
@@ -164,35 +159,6 @@ export async function openapiCommand(
|
|
|
164
159
|
logger.log(
|
|
165
160
|
`📄 [${appName}] Generated OpenAPI (${result.endpointCount} endpoints)`,
|
|
166
161
|
);
|
|
167
|
-
|
|
168
|
-
// Copy to frontend apps that depend on this backend
|
|
169
|
-
for (const [frontendName, frontendApp] of frontendApps) {
|
|
170
|
-
if (frontendApp.type !== 'frontend') continue;
|
|
171
|
-
|
|
172
|
-
const dependsOnBackend =
|
|
173
|
-
!frontendApp.dependencies ||
|
|
174
|
-
frontendApp.dependencies.includes(appName);
|
|
175
|
-
|
|
176
|
-
if (dependsOnBackend && frontendApp.client?.output) {
|
|
177
|
-
const frontendPath = join(workspaceRoot, frontendApp.path);
|
|
178
|
-
const clientOutputPath = join(
|
|
179
|
-
frontendPath,
|
|
180
|
-
frontendApp.client.output,
|
|
181
|
-
'openapi.ts',
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
await mkdir(dirname(clientOutputPath), { recursive: true });
|
|
185
|
-
|
|
186
|
-
// Read the generated content and write to frontend
|
|
187
|
-
const { readFile } = await import('node:fs/promises');
|
|
188
|
-
const content = await readFile(result.outputPath, 'utf-8');
|
|
189
|
-
await writeFile(clientOutputPath, content);
|
|
190
|
-
|
|
191
|
-
logger.log(
|
|
192
|
-
` → [${frontendName}] ${frontendApp.client.output}/openapi.ts`,
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
162
|
}
|
|
197
163
|
}
|
|
198
164
|
}
|
package/src/types.ts
CHANGED
|
@@ -332,6 +332,13 @@ export interface BuildOptions {
|
|
|
332
332
|
skipBundle?: boolean;
|
|
333
333
|
/** Stage for secrets injection (e.g., 'production', 'staging') */
|
|
334
334
|
stage?: string;
|
|
335
|
+
/**
|
|
336
|
+
* When true, optional environment variables (those with `.optional()` or
|
|
337
|
+
* `.default()` in the envParser) are suffixed with `?` within each
|
|
338
|
+
* construct's `environment` array in the manifest (e.g. `PORT?`).
|
|
339
|
+
* Defaults to false.
|
|
340
|
+
*/
|
|
341
|
+
markOptional?: boolean;
|
|
335
342
|
}
|
|
336
343
|
|
|
337
344
|
/** Result from build command when secrets are injected */
|