@geekmidas/cli 10.0.0-alpha.2 → 10.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -48
- package/bin/adjacent-tsconfig.mjs +59 -0
- package/bin/gkm.mjs +7 -1
- package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-BY26bWwB.mjs} +20 -21
- package/dist/HostingerProvider-BY26bWwB.mjs.map +1 -0
- package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
- package/dist/HostingerProvider-BZFGYYVA.cjs.map +1 -0
- package/dist/{LocalStateProvider-Db9SEjyH.cjs → LocalStateProvider-7HR6SS2t.cjs} +11 -6
- package/dist/LocalStateProvider-7HR6SS2t.cjs.map +1 -0
- package/dist/{LocalStateProvider-Bn6tS-oL.mjs → LocalStateProvider-D7QyJoLM.mjs} +10 -4
- package/dist/LocalStateProvider-D7QyJoLM.mjs.map +1 -0
- package/dist/{Route53Provider-RdpUDJQk.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
- package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
- package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
- package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
- package/dist/{SSMStateProvider-BRt2py-A.mjs → SSMStateProvider-B0Hu1MKZ.mjs} +13 -4
- package/dist/SSMStateProvider-B0Hu1MKZ.mjs.map +1 -0
- package/dist/{SSMStateProvider-DyX8s9HI.cjs → SSMStateProvider-VrQ-yeqd.cjs} +17 -9
- package/dist/SSMStateProvider-VrQ-yeqd.cjs.map +1 -0
- package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
- package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
- package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
- package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
- package/dist/{bundler-BY1OmV1e.cjs → bundler-mjqGAvu1.cjs} +10 -28
- package/dist/bundler-mjqGAvu1.cjs.map +1 -0
- package/dist/{bundler-Be8Zg4Wd.mjs → bundler-mwH7WOb1.mjs} +9 -26
- package/dist/bundler-mwH7WOb1.mjs.map +1 -0
- package/dist/{config-BholeD-0.cjs → config-DSXI480r.cjs} +80 -148
- package/dist/config-DSXI480r.cjs.map +1 -0
- package/dist/{config-CzWnfcXM.mjs → config-DdKkoUE1.mjs} +33 -88
- package/dist/config-DdKkoUE1.mjs.map +1 -0
- package/dist/config.cjs +4 -5
- package/dist/config.d.cts +14 -17
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +14 -17
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -5
- package/dist/{credentials-DQmbRnr1.cjs → credentials-BfmmB4WD.cjs} +1508 -1243
- package/dist/credentials-BfmmB4WD.cjs.map +1 -0
- package/dist/{credentials-BZcp3CGx.mjs → credentials-CD8ftUS6.mjs} +1374 -1114
- package/dist/credentials-CD8ftUS6.mjs.map +1 -0
- package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
- package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
- package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
- package/dist/deploy/sniffer-hooks.cjs +13 -7
- package/dist/deploy/sniffer-hooks.cjs.map +1 -1
- package/dist/deploy/sniffer-hooks.d.cts +1 -2
- package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
- package/dist/deploy/sniffer-hooks.d.mts +1 -2
- package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
- package/dist/deploy/sniffer-hooks.mjs +9 -2
- package/dist/deploy/sniffer-hooks.mjs.map +1 -1
- package/dist/deploy/sniffer-loader.cjs +16 -7
- package/dist/deploy/sniffer-loader.cjs.map +1 -1
- package/dist/deploy/sniffer-loader.d.cts +1 -1
- package/dist/deploy/sniffer-loader.d.mts +1 -1
- package/dist/deploy/sniffer-loader.mjs +13 -2
- package/dist/deploy/sniffer-loader.mjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.cjs +11 -11
- package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
- package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
- package/dist/deploy/sniffer-routes-worker.mjs +2 -2
- package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
- package/dist/deploy/sniffer-worker.cjs +15 -6
- package/dist/deploy/sniffer-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-worker.d.cts +1 -3
- package/dist/deploy/sniffer-worker.d.cts.map +1 -1
- package/dist/deploy/sniffer-worker.d.mts +1 -3
- package/dist/deploy/sniffer-worker.d.mts.map +1 -1
- package/dist/deploy/sniffer-worker.mjs +15 -4
- package/dist/deploy/sniffer-worker.mjs.map +1 -1
- package/dist/{discover-DTmFeloL.cjs → discover-BERGFg8v.cjs} +81 -64
- package/dist/discover-BERGFg8v.cjs.map +1 -0
- package/dist/{discover-CAlFgYec.mjs → discover-CK-n3w6b.mjs} +35 -20
- package/dist/discover-CK-n3w6b.mjs.map +1 -0
- package/dist/{emit-CbcRolsa.cjs → emit-BdoPFjZf.cjs} +53 -36
- package/dist/emit-BdoPFjZf.cjs.map +1 -0
- package/dist/{emit-CiZS_5Ub.mjs → emit-Bzq7JsMP.mjs} +24 -6
- package/dist/emit-Bzq7JsMP.mjs.map +1 -0
- package/dist/{generator-VE2JrFlY.mjs → generator-LfZU7NlU.mjs} +8 -14
- package/dist/generator-LfZU7NlU.mjs.map +1 -0
- package/dist/{generator-CNzBw7g5.cjs → generator-Wdfp0jCS.cjs} +38 -45
- package/dist/generator-Wdfp0jCS.cjs.map +1 -0
- package/dist/github-Bho-C6Zg.cjs +216 -0
- package/dist/github-Bho-C6Zg.cjs.map +1 -0
- package/dist/github-De-yMwVt.mjs +216 -0
- package/dist/github-De-yMwVt.mjs.map +1 -0
- package/dist/{index-CHB4tSzX.d.cts → index-B4H4XF7A.d.mts} +4 -13
- package/dist/index-B4H4XF7A.d.mts.map +1 -0
- package/dist/{index-BThUzEIp.d.mts → index-RCUizGxL.d.cts} +4 -13
- package/dist/index-RCUizGxL.d.cts.map +1 -0
- package/dist/index.cjs +5108 -3381
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +5025 -3315
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-c9bpieI5.cjs → openapi-B8bu_OXN.cjs} +228 -188
- package/dist/openapi-B8bu_OXN.cjs.map +1 -0
- package/dist/{openapi-CY9xFkTH.mjs → openapi-DfjbhrsM.mjs} +172 -143
- package/dist/openapi-DfjbhrsM.mjs.map +1 -0
- package/dist/openapi.cjs +5 -6
- package/dist/openapi.d.cts +47 -14
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +47 -14
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +2 -6
- package/dist/reconcile/public.cjs +4 -4
- package/dist/reconcile/public.d.cts +8 -26
- package/dist/reconcile/public.d.cts.map +1 -1
- package/dist/reconcile/public.d.mts +8 -26
- package/dist/reconcile/public.d.mts.map +1 -1
- package/dist/reconcile/public.mjs +3 -4
- package/dist/{fullstack-secrets-D1o9-G5l.mjs → reconcile-gb1lz1Dk.mjs} +43 -17
- package/dist/reconcile-gb1lz1Dk.mjs.map +1 -0
- package/dist/{fullstack-secrets-C-GGohke.cjs → reconcile-hx_vBvux.cjs} +63 -38
- package/dist/reconcile-hx_vBvux.cjs.map +1 -0
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
- package/dist/ssm-BKN1Cg4z.mjs +60 -0
- package/dist/ssm-BKN1Cg4z.mjs.map +1 -0
- package/dist/ssm-FxeSAt35.cjs +60 -0
- package/dist/ssm-FxeSAt35.cjs.map +1 -0
- package/dist/{storage-BJmzYxt8.cjs → storage-DgypfSD6.cjs} +65 -77
- package/dist/storage-DgypfSD6.cjs.map +1 -0
- package/dist/{storage-Bi24WfoW.mjs → storage-TP0x118M.mjs} +22 -15
- package/dist/storage-TP0x118M.mjs.map +1 -0
- package/dist/transfer-CXoyQZbB.cjs +151 -0
- package/dist/transfer-CXoyQZbB.cjs.map +1 -0
- package/dist/transfer-Gsxfy6m-.mjs +122 -0
- package/dist/transfer-Gsxfy6m-.mjs.map +1 -0
- package/dist/types-7R81hu0i.d.mts +6302 -0
- package/dist/types-7R81hu0i.d.mts.map +1 -0
- package/dist/types-N7c2O2m7.d.cts +6303 -0
- package/dist/types-N7c2O2m7.d.cts.map +1 -0
- package/dist/workspace/index.cjs +3 -3
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -3
- package/dist/workspace-Bu3xNCej.mjs +6563 -0
- package/dist/workspace-Bu3xNCej.mjs.map +1 -0
- package/dist/workspace-CRD9YinV.cjs +6741 -0
- package/dist/workspace-CRD9YinV.cjs.map +1 -0
- package/package.json +33 -43
- package/dist/CachedStateProvider-BLo7zv7S.cjs +0 -3
- package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
- package/dist/CachedStateProvider-CqPdW7CB.cjs +0 -60
- package/dist/CachedStateProvider-CqPdW7CB.cjs.map +0 -1
- package/dist/CachedStateProvider-DTniehMP.mjs +0 -54
- package/dist/CachedStateProvider-DTniehMP.mjs.map +0 -1
- package/dist/HostingerProvider-Cft7lEYr.mjs.map +0 -1
- package/dist/HostingerProvider-h3EbEp-Z.cjs.map +0 -1
- package/dist/LocalStateProvider-Bn6tS-oL.mjs.map +0 -1
- package/dist/LocalStateProvider-Db9SEjyH.cjs.map +0 -1
- package/dist/Route53Provider-RdpUDJQk.mjs.map +0 -1
- package/dist/Route53Provider-di2fMM5N.cjs.map +0 -1
- package/dist/SSMStateProvider-BRt2py-A.mjs.map +0 -1
- package/dist/SSMStateProvider-DyX8s9HI.cjs.map +0 -1
- package/dist/backup-provisioner-Bgj5Vi_L.mjs.map +0 -1
- package/dist/backup-provisioner-BrsHwYG0.cjs.map +0 -1
- package/dist/bundler-BY1OmV1e.cjs.map +0 -1
- package/dist/bundler-Be8Zg4Wd.mjs.map +0 -1
- package/dist/chunk-Duj1WY3L.mjs +0 -7
- package/dist/config-BholeD-0.cjs.map +0 -1
- package/dist/config-CzWnfcXM.mjs.map +0 -1
- package/dist/credentials-B5zRHdAl.mjs +0 -141
- package/dist/credentials-B5zRHdAl.mjs.map +0 -1
- package/dist/credentials-BZcp3CGx.mjs.map +0 -1
- package/dist/credentials-BapzjyV5.cjs +0 -195
- package/dist/credentials-BapzjyV5.cjs.map +0 -1
- package/dist/credentials-DQmbRnr1.cjs.map +0 -1
- package/dist/discover-CAlFgYec.mjs.map +0 -1
- package/dist/discover-DTmFeloL.cjs.map +0 -1
- package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
- package/dist/dokploy-api-BsVH0y_s.cjs +0 -718
- package/dist/dokploy-api-BsVH0y_s.cjs.map +0 -1
- package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
- package/dist/dokploy-api-aTFPz7_4.mjs +0 -706
- package/dist/dokploy-api-aTFPz7_4.mjs.map +0 -1
- package/dist/emit-CbcRolsa.cjs.map +0 -1
- package/dist/emit-CiZS_5Ub.mjs.map +0 -1
- package/dist/encryption-C6jaU0hE.cjs +0 -54
- package/dist/encryption-C6jaU0hE.cjs.map +0 -1
- package/dist/encryption-CHzzeR8a.cjs +0 -4
- package/dist/encryption-CQUncu7v.mjs +0 -3
- package/dist/encryption-D-abyhZx.mjs +0 -42
- package/dist/encryption-D-abyhZx.mjs.map +0 -1
- package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
- package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
- package/dist/generator-CNzBw7g5.cjs.map +0 -1
- package/dist/generator-VE2JrFlY.mjs.map +0 -1
- package/dist/index-BThUzEIp.d.mts.map +0 -1
- package/dist/index-CHB4tSzX.d.cts.map +0 -1
- package/dist/openapi-CY9xFkTH.mjs.map +0 -1
- package/dist/openapi-c9bpieI5.cjs.map +0 -1
- package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
- package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
- package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
- package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
- package/dist/openapi-react-query.cjs +0 -4
- package/dist/openapi-react-query.d.cts +0 -11
- package/dist/openapi-react-query.d.cts.map +0 -1
- package/dist/openapi-react-query.d.mts +0 -11
- package/dist/openapi-react-query.d.mts.map +0 -1
- package/dist/openapi-react-query.mjs +0 -4
- package/dist/reconcile-CFs8C_1a.mjs +0 -37
- package/dist/reconcile-CFs8C_1a.mjs.map +0 -1
- package/dist/reconcile-D0pimNiy.cjs +0 -37
- package/dist/reconcile-D0pimNiy.cjs.map +0 -1
- package/dist/setup-Bc73t0ve.mjs +0 -443
- package/dist/setup-Bc73t0ve.mjs.map +0 -1
- package/dist/setup-C48C9hto.cjs +0 -473
- package/dist/setup-C48C9hto.cjs.map +0 -1
- package/dist/setup-DCuudnCl.mjs +0 -11
- package/dist/setup-fG_ivuxO.cjs +0 -11
- package/dist/storage-BJmzYxt8.cjs.map +0 -1
- package/dist/storage-BM9hGpgv.cjs +0 -7
- package/dist/storage-Bi24WfoW.mjs.map +0 -1
- package/dist/storage-CYlGwWTj.mjs +0 -3
- package/dist/sync-CmEuNZsB.mjs +0 -76
- package/dist/sync-CmEuNZsB.mjs.map +0 -1
- package/dist/sync-D306yOWu.cjs +0 -4
- package/dist/sync-SizaChmC.cjs +0 -93
- package/dist/sync-SizaChmC.cjs.map +0 -1
- package/dist/sync-hOqAWHR6.mjs +0 -3
- package/dist/types-C-arnQ1r.d.mts +0 -2184
- package/dist/types-C-arnQ1r.d.mts.map +0 -1
- package/dist/types-abJQuk7m.d.cts +0 -2184
- package/dist/types-abJQuk7m.d.cts.map +0 -1
- package/dist/workspace-7FqprxuJ.mjs +0 -4323
- package/dist/workspace-7FqprxuJ.mjs.map +0 -1
- package/dist/workspace-BO_KWohI.cjs +0 -9
- package/dist/workspace-DK4WWJIn.mjs +0 -8
- package/dist/workspace-XvqO9jIv.cjs +0 -4472
- package/dist/workspace-XvqO9jIv.cjs.map +0 -1
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
const require_discover = require("./discover-BERGFg8v.cjs");
|
|
2
|
+
const require_config = require("./config-DSXI480r.cjs");
|
|
3
|
+
let node_fs_promises = require("node:fs/promises");
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
let node_child_process = require("node:child_process");
|
|
6
|
+
let _geekmidas_manifest = require("@geekmidas/manifest");
|
|
7
|
+
let _geekmidas_constructs_endpoints = require("@geekmidas/constructs/endpoints");
|
|
8
|
+
let node_url = require("node:url");
|
|
9
|
+
let _geekmidas_schema_conversion = require("@geekmidas/schema/conversion");
|
|
11
10
|
//#region src/build/endpoint-analyzer.ts
|
|
12
11
|
/**
|
|
13
12
|
* Analyze an endpoint to extract its features
|
|
@@ -84,7 +83,6 @@ function summarizeAnalysis(analyses) {
|
|
|
84
83
|
byFeature
|
|
85
84
|
};
|
|
86
85
|
}
|
|
87
|
-
|
|
88
86
|
//#endregion
|
|
89
87
|
//#region src/build/handler-templates.ts
|
|
90
88
|
/**
|
|
@@ -106,8 +104,7 @@ function generateMinimalHandler(analysis) {
|
|
|
106
104
|
const { exportName, features } = analysis;
|
|
107
105
|
const method = analysis.method.toLowerCase();
|
|
108
106
|
const validators = generateValidators(exportName, features);
|
|
109
|
-
|
|
110
|
-
if (!hasValidators && !features.hasOutputValidation) return `
|
|
107
|
+
if (!(validators.length > 0) && !features.hasOutputValidation) return `
|
|
111
108
|
// Minimal handler: ${analysis.route} (${analysis.method})
|
|
112
109
|
app.${method}('${analysis.route}', async (c) => {
|
|
113
110
|
const result = await ${exportName}.handler(
|
|
@@ -255,10 +252,10 @@ function generateValidatorsFile(analyses) {
|
|
|
255
252
|
const needsQuery = analyses.some((a) => a.features.hasQueryValidation);
|
|
256
253
|
const needsParams = analyses.some((a) => a.features.hasParamValidation);
|
|
257
254
|
if (!needsBody && !needsQuery && !needsParams) return `// No validators needed for this build\nexport {};\n`;
|
|
258
|
-
const exports
|
|
255
|
+
const exports = [];
|
|
259
256
|
const factories = [];
|
|
260
257
|
if (needsBody) {
|
|
261
|
-
exports
|
|
258
|
+
exports.push("validateBody");
|
|
262
259
|
factories.push(`
|
|
263
260
|
export const validateBody = (endpoint: any) =>
|
|
264
261
|
validator('json', async (value, c) => {
|
|
@@ -269,7 +266,7 @@ export const validateBody = (endpoint: any) =>
|
|
|
269
266
|
});`);
|
|
270
267
|
}
|
|
271
268
|
if (needsQuery) {
|
|
272
|
-
exports
|
|
269
|
+
exports.push("validateQuery");
|
|
273
270
|
factories.push(`
|
|
274
271
|
export const validateQuery = (endpoint: any) =>
|
|
275
272
|
validator('query', async (_, c) => {
|
|
@@ -281,7 +278,7 @@ export const validateQuery = (endpoint: any) =>
|
|
|
281
278
|
});`);
|
|
282
279
|
}
|
|
283
280
|
if (needsParams) {
|
|
284
|
-
exports
|
|
281
|
+
exports.push("validateParams");
|
|
285
282
|
factories.push(`
|
|
286
283
|
export const validateParams = (endpoint: any) =>
|
|
287
284
|
validator('param', async (params, c) => {
|
|
@@ -305,8 +302,7 @@ ${factories.join("\n")}
|
|
|
305
302
|
*/
|
|
306
303
|
function generateMinimalEndpointFile(analysis, endpointImport) {
|
|
307
304
|
const { exportName, features } = analysis;
|
|
308
|
-
const
|
|
309
|
-
const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
305
|
+
const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
310
306
|
const handler = generateMinimalHandler(analysis);
|
|
311
307
|
return `/**
|
|
312
308
|
* Minimal endpoint: ${analysis.route} (${analysis.method})
|
|
@@ -331,8 +327,7 @@ ${handler}
|
|
|
331
327
|
*/
|
|
332
328
|
function generateStandardEndpointFile(analysis, endpointImport) {
|
|
333
329
|
const { exportName, features } = analysis;
|
|
334
|
-
const
|
|
335
|
-
const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
330
|
+
const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
336
331
|
const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
|
|
337
332
|
const handler = generateStandardHandler(analysis);
|
|
338
333
|
return `/**
|
|
@@ -424,7 +419,7 @@ export function setupFullEndpoints(
|
|
|
424
419
|
}
|
|
425
420
|
const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
|
|
426
421
|
if (tier === "minimal") {
|
|
427
|
-
const calls
|
|
422
|
+
const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
|
|
428
423
|
return `/**
|
|
429
424
|
* Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
|
|
430
425
|
* Near-raw-Hono performance
|
|
@@ -437,12 +432,12 @@ export function setupMinimalEndpoints(
|
|
|
437
432
|
app: Hono,
|
|
438
433
|
logger: Logger,
|
|
439
434
|
): void {
|
|
440
|
-
${calls
|
|
435
|
+
${calls}
|
|
441
436
|
}
|
|
442
437
|
`;
|
|
443
438
|
}
|
|
444
439
|
if (tier === "standard") {
|
|
445
|
-
const calls
|
|
440
|
+
const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
|
|
446
441
|
return `/**
|
|
447
442
|
* Standard-tier endpoint index (${tierEndpoints.length} endpoints)
|
|
448
443
|
* Auth and/or services enabled
|
|
@@ -457,7 +452,7 @@ export function setupStandardEndpoints(
|
|
|
457
452
|
serviceDiscovery: ServiceDiscovery<any, any>,
|
|
458
453
|
logger: Logger,
|
|
459
454
|
): void {
|
|
460
|
-
${calls
|
|
455
|
+
${calls}
|
|
461
456
|
}
|
|
462
457
|
`;
|
|
463
458
|
}
|
|
@@ -527,9 +522,7 @@ function generateEndpointFilesNested(analyses, endpointImports) {
|
|
|
527
522
|
case "standard":
|
|
528
523
|
files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
|
|
529
524
|
break;
|
|
530
|
-
case "full":
|
|
531
|
-
files[fileName] = generateFullEndpointFile(analysis, endpointImport);
|
|
532
|
-
break;
|
|
525
|
+
case "full": files[fileName] = generateFullEndpointFile(analysis, endpointImport);
|
|
533
526
|
}
|
|
534
527
|
}
|
|
535
528
|
return files;
|
|
@@ -586,7 +579,6 @@ export async function setupEndpoints(
|
|
|
586
579
|
}
|
|
587
580
|
`;
|
|
588
581
|
}
|
|
589
|
-
|
|
590
582
|
//#endregion
|
|
591
583
|
//#region src/generators/EndpointGenerator.ts
|
|
592
584
|
/**
|
|
@@ -603,24 +595,21 @@ export async function setupEndpoints(
|
|
|
603
595
|
*
|
|
604
596
|
* Falls back to the configured paths for an app that declares no surface.
|
|
605
597
|
*/
|
|
606
|
-
function runtimeFor(context, fromDir) {
|
|
607
|
-
const module
|
|
608
|
-
if (module
|
|
609
|
-
const specifier = importSpecifier(fromDir, module
|
|
598
|
+
function runtimeFor(context, fromDir, owner) {
|
|
599
|
+
const module = owner ? context.owners?.[owner] ?? context.surface?.module : context.surface?.module;
|
|
600
|
+
if (module) {
|
|
601
|
+
const specifier = importSpecifier(fromDir, module.specifier);
|
|
610
602
|
return {
|
|
611
|
-
imports: `import { ${module
|
|
603
|
+
imports: `import { ${module.exportName} as __surface } from '${specifier}';`,
|
|
612
604
|
bindings: [
|
|
613
|
-
"// What this
|
|
614
|
-
"// the entry imports the
|
|
605
|
+
"// What this construct was declared with. Objects, not module paths:",
|
|
606
|
+
"// the entry imports the owner, so there is nothing to print.",
|
|
615
607
|
"const envParser = __surface.envParser;",
|
|
616
608
|
"const logger = __surface.logger;"
|
|
617
609
|
].join("\n")
|
|
618
610
|
};
|
|
619
611
|
}
|
|
620
|
-
|
|
621
|
-
imports: [`import ${context.envParserImportPattern} from '${importSpecifier(fromDir, context.envParserPath)}';`, `import ${context.loggerImportPattern} from '${importSpecifier(fromDir, context.loggerPath)}';`].join("\n"),
|
|
622
|
-
bindings: ""
|
|
623
|
-
};
|
|
612
|
+
throw new Error(`No owner to take a logger and an environment parser from${owner ? ` for "${owner}"` : ""}. Build it from a \`RestApi\` or a \`Worker\`.`);
|
|
624
613
|
}
|
|
625
614
|
/** A relative specifier ESM will accept: always prefixed, never bare. */
|
|
626
615
|
function importSpecifier(fromDir, target) {
|
|
@@ -679,7 +668,7 @@ function corsFor(surface) {
|
|
|
679
668
|
}
|
|
680
669
|
var EndpointGenerator = class extends require_discover.ConstructGenerator {
|
|
681
670
|
isConstruct(value) {
|
|
682
|
-
return
|
|
671
|
+
return _geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
|
|
683
672
|
}
|
|
684
673
|
async build(context, constructs, outputDir, options) {
|
|
685
674
|
const provider = options?.provider || "aws-apigatewayv2";
|
|
@@ -735,8 +724,7 @@ var EndpointGenerator = class extends require_discover.ConstructGenerator {
|
|
|
735
724
|
async generateHandlerFile(outputDir, sourceFile, exportName, provider, _endpoint, context) {
|
|
736
725
|
const handlerFileName = `${exportName}.ts`;
|
|
737
726
|
const handlerPath = (0, node_path.join)(outputDir, handlerFileName);
|
|
738
|
-
const
|
|
739
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
727
|
+
const importPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile).replace(/\.ts$/, ".js");
|
|
740
728
|
let content;
|
|
741
729
|
switch (provider) {
|
|
742
730
|
case "aws-apigatewayv1":
|
|
@@ -754,16 +742,14 @@ var EndpointGenerator = class extends require_discover.ConstructGenerator {
|
|
|
754
742
|
return handlerPath;
|
|
755
743
|
}
|
|
756
744
|
async generateEndpointsFile(outputDir, endpoints, context) {
|
|
757
|
-
const
|
|
758
|
-
const endpointsPath = (0, node_path.join)(outputDir, endpointsFileName);
|
|
745
|
+
const endpointsPath = (0, node_path.join)(outputDir, "endpoints.ts");
|
|
759
746
|
const importsByFile = /* @__PURE__ */ new Map();
|
|
760
747
|
for (const { path, key } of endpoints) {
|
|
761
|
-
const
|
|
762
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
748
|
+
const importPath = (0, node_path.relative)((0, node_path.dirname)(endpointsPath), path.relative).replace(/\.ts$/, ".js");
|
|
763
749
|
if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
|
|
764
750
|
importsByFile.get(importPath)?.push(key);
|
|
765
751
|
}
|
|
766
|
-
const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports
|
|
752
|
+
const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports]) => `import { ${exports.join(", ")} } from '${importPath}';`).join("\n");
|
|
767
753
|
const allExportNames = endpoints.map(({ key }) => key);
|
|
768
754
|
if (context.production?.enabled && context.production.optimizedHandlers) return this.generateOptimizedEndpointsFile(endpointsPath, endpoints, endpointImports, allExportNames);
|
|
769
755
|
const content = `import type { EnvironmentParser } from '@geekmidas/envkit';
|
|
@@ -825,11 +811,9 @@ export async function setupEndpoints(
|
|
|
825
811
|
const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
|
|
826
812
|
const endpointImports = endpoints.map(({ key, path }) => {
|
|
827
813
|
const tierDir = (0, node_path.join)(endpointsDir, "standard");
|
|
828
|
-
const relativePath = (0, node_path.relative)(tierDir, path.relative);
|
|
829
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
830
814
|
return {
|
|
831
815
|
exportName: key,
|
|
832
|
-
importPath
|
|
816
|
+
importPath: (0, node_path.relative)(tierDir, path.relative).replace(/\.ts$/, ".js")
|
|
833
817
|
};
|
|
834
818
|
});
|
|
835
819
|
const summary = summarizeAnalysis(analyses);
|
|
@@ -851,8 +835,7 @@ export async function setupEndpoints(
|
|
|
851
835
|
}
|
|
852
836
|
async generateAppFile(outputDir, context) {
|
|
853
837
|
if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
|
|
854
|
-
const
|
|
855
|
-
const appPath = (0, node_path.join)(outputDir, appFileName);
|
|
838
|
+
const appPath = (0, node_path.join)(outputDir, "app.ts");
|
|
856
839
|
const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
|
|
857
840
|
const telescopeEnabled = context.telescope?.enabled;
|
|
858
841
|
const telescopeWebSocketEnabled = context.telescope?.websocket;
|
|
@@ -862,32 +845,35 @@ export async function setupEndpoints(
|
|
|
862
845
|
const studioFromDatabase = !usesExternalStudio && !!context.studio?.database;
|
|
863
846
|
const telescopeFromSurface = !!context.surface?.module && !usesExternalTelescope;
|
|
864
847
|
let telescopeImports = "";
|
|
865
|
-
if (telescopeEnabled)
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
848
|
+
if (telescopeEnabled) {
|
|
849
|
+
if (telescopeFromSurface) telescopeImports = "import { createMiddleware, createUI } from '@geekmidas/telescope/hono';";
|
|
850
|
+
else if (usesExternalTelescope) {
|
|
851
|
+
const relativeTelescopePath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.telescope?.telescopePath);
|
|
852
|
+
telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
|
|
869
853
|
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
870
|
-
|
|
854
|
+
} else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
|
|
871
855
|
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
856
|
+
}
|
|
872
857
|
let studioImports = "";
|
|
873
|
-
if (studioEnabled)
|
|
874
|
-
|
|
875
|
-
|
|
858
|
+
if (studioEnabled) {
|
|
859
|
+
if (usesExternalStudio) {
|
|
860
|
+
const relativeStudioPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.studio?.studioPath);
|
|
861
|
+
studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
|
|
876
862
|
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
863
|
+
} else if (studioFromDatabase) {
|
|
864
|
+
const dbSpecifier = importSpecifier((0, node_path.dirname)(appPath), context.studio.database.specifier);
|
|
865
|
+
studioImports = `import { snifferContext } from '@geekmidas/constructs';
|
|
880
866
|
import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
|
|
881
867
|
import { ${context.studio.database.exportName} as __studioDb } from '${dbSpecifier}';
|
|
882
868
|
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
883
|
-
|
|
869
|
+
} else studioImports = "";
|
|
870
|
+
}
|
|
884
871
|
const cors = corsFor(context.surface);
|
|
885
872
|
let hooksImports = "";
|
|
886
873
|
let beforeSetupCall = "";
|
|
887
874
|
let afterSetupCall = "";
|
|
888
875
|
if (context.hooks?.serverHooksPath) {
|
|
889
|
-
|
|
890
|
-
hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
|
|
876
|
+
hooksImports = `import * as serverHooks from '${(0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath)}';`;
|
|
891
877
|
beforeSetupCall = `
|
|
892
878
|
// Call beforeSetup hook if defined
|
|
893
879
|
if (typeof serverHooks.beforeSetup === 'function') {
|
|
@@ -933,7 +919,8 @@ import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
|
933
919
|
}
|
|
934
920
|
` : "";
|
|
935
921
|
let telescopeSetup = "";
|
|
936
|
-
if (telescopeEnabled)
|
|
922
|
+
if (telescopeEnabled) {
|
|
923
|
+
if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
|
|
937
924
|
${telescopeWebSocketSetupCode}
|
|
938
925
|
// Add telescope middleware (before endpoints to capture all requests)
|
|
939
926
|
honoApp.use('*', createMiddleware(telescope));
|
|
@@ -942,7 +929,7 @@ ${telescopeWebSocketSetupCode}
|
|
|
942
929
|
const telescopeUI = createUI(telescope);
|
|
943
930
|
honoApp.route('${context.telescope?.path}', telescopeUI);
|
|
944
931
|
`;
|
|
945
|
-
|
|
932
|
+
else telescopeSetup = `
|
|
946
933
|
// Setup Telescope for debugging/monitoring
|
|
947
934
|
const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
|
|
948
935
|
const telescope = new Telescope({
|
|
@@ -960,6 +947,7 @@ ${telescopeWebSocketSetupCode}
|
|
|
960
947
|
const telescopeUI = createUI(telescope);
|
|
961
948
|
honoApp.route('${context.telescope?.path}', telescopeUI);
|
|
962
949
|
`;
|
|
950
|
+
}
|
|
963
951
|
let studioSetup = "";
|
|
964
952
|
if (studioEnabled && studioFromDatabase) studioSetup = `
|
|
965
953
|
// Studio, built from the declared database. The client comes from the
|
|
@@ -993,6 +981,7 @@ import type { Hono as HonoType } from 'hono';
|
|
|
993
981
|
import { setupEndpoints } from './endpoints.js';
|
|
994
982
|
import { setupSubscribers } from './subscribers.js';
|
|
995
983
|
import { setupQueues } from './queues.js';
|
|
984
|
+
import { setupCrons } from './crons.js';
|
|
996
985
|
${runtime.imports}
|
|
997
986
|
${telescopeImports}
|
|
998
987
|
${studioImports}
|
|
@@ -1080,6 +1069,12 @@ ${afterSetupCall}
|
|
|
1080
1069
|
logger.error({ error }, 'Failed to start queue workers');
|
|
1081
1070
|
});
|
|
1082
1071
|
|
|
1072
|
+
// Schedule this app's crons. Caught like the others: a scheduler that
|
|
1073
|
+
// cannot start is not a reason for the HTTP server not to.
|
|
1074
|
+
await setupCrons(envParser, logger).catch((error) => {
|
|
1075
|
+
logger.error({ error }, 'Failed to schedule crons');
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1083
1078
|
logger.info({ port }, 'Starting server');
|
|
1084
1079
|
|
|
1085
1080
|
// Start HTTP server using provided serve function
|
|
@@ -1148,10 +1143,8 @@ export const handler = ${exportName};
|
|
|
1148
1143
|
* No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
|
|
1149
1144
|
*/
|
|
1150
1145
|
async generateProductionAppFile(outputDir, context) {
|
|
1151
|
-
const
|
|
1152
|
-
const
|
|
1153
|
-
const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.loggerPath);
|
|
1154
|
-
const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.envParserPath);
|
|
1146
|
+
const appPath = (0, node_path.join)(outputDir, "app.ts");
|
|
1147
|
+
const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
|
|
1155
1148
|
const production = context.production;
|
|
1156
1149
|
const healthCheckPath = production.healthCheck;
|
|
1157
1150
|
const enableGracefulShutdown = production.gracefulShutdown;
|
|
@@ -1162,8 +1155,7 @@ export const handler = ${exportName};
|
|
|
1162
1155
|
let beforeSetupCall = "";
|
|
1163
1156
|
let afterSetupCall = "";
|
|
1164
1157
|
if (context.hooks?.serverHooksPath) {
|
|
1165
|
-
|
|
1166
|
-
hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
|
|
1158
|
+
hooksImports = `import * as serverHooks from '${(0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath)}';`;
|
|
1167
1159
|
beforeSetupCall = `
|
|
1168
1160
|
// Call beforeSetup hook if defined
|
|
1169
1161
|
if (typeof serverHooks.beforeSetup === 'function') {
|
|
@@ -1187,9 +1179,16 @@ export const handler = ${exportName};
|
|
|
1187
1179
|
await setupQueues(envParser, logger).catch((error) => {
|
|
1188
1180
|
logger.error({ error }, 'Failed to start queue workers');
|
|
1189
1181
|
});
|
|
1182
|
+
|
|
1183
|
+
// Schedule this app's crons. Caught like the others: a scheduler that
|
|
1184
|
+
// cannot start is not a reason for the HTTP server not to.
|
|
1185
|
+
await setupCrons(envParser, logger).catch((error) => {
|
|
1186
|
+
logger.error({ error }, 'Failed to schedule crons');
|
|
1187
|
+
});
|
|
1190
1188
|
` : "";
|
|
1191
1189
|
const subscriberImport = includeSubscribers ? `import { setupSubscribers } from './subscribers.js';
|
|
1192
|
-
import { setupQueues } from './queues.js'
|
|
1190
|
+
import { setupQueues } from './queues.js';
|
|
1191
|
+
import { setupCrons } from './crons.js';` : "";
|
|
1193
1192
|
const gracefulShutdownCode = enableGracefulShutdown ? `
|
|
1194
1193
|
// Graceful shutdown handling
|
|
1195
1194
|
let isShuttingDown = false;
|
|
@@ -1205,7 +1204,6 @@ import { setupQueues } from './queues.js';` : "";
|
|
|
1205
1204
|
process.on('SIGTERM', shutdown);
|
|
1206
1205
|
process.on('SIGINT', shutdown);
|
|
1207
1206
|
` : "";
|
|
1208
|
-
const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
|
|
1209
1207
|
const content = `/**
|
|
1210
1208
|
* Generated production server application
|
|
1211
1209
|
*
|
|
@@ -1217,10 +1215,10 @@ import { setupQueues } from './queues.js';` : "";
|
|
|
1217
1215
|
*/
|
|
1218
1216
|
import { Hono } from 'hono';
|
|
1219
1217
|
import type { Hono as HonoType } from 'hono';
|
|
1220
|
-
import { setupEndpoints } from '${
|
|
1218
|
+
import { setupEndpoints } from '${production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js"}';
|
|
1221
1219
|
${subscriberImport}
|
|
1222
|
-
|
|
1223
|
-
|
|
1220
|
+
${runtime.imports}
|
|
1221
|
+
${runtime.bindings}
|
|
1224
1222
|
${hooksImports}
|
|
1225
1223
|
${cors.imports}
|
|
1226
1224
|
${context.storageDrivers?.imports ?? ""}
|
|
@@ -1284,7 +1282,7 @@ export default createApp;
|
|
|
1284
1282
|
*/
|
|
1285
1283
|
async generateProductionServerEntry(outputDir) {
|
|
1286
1284
|
const serverPath = (0, node_path.join)(outputDir, "server.ts");
|
|
1287
|
-
|
|
1285
|
+
await (0, node_fs_promises.writeFile)(serverPath, `#!/usr/bin/env node
|
|
1288
1286
|
/**
|
|
1289
1287
|
* Production server entry point
|
|
1290
1288
|
* Generated by 'gkm build --provider server --production'
|
|
@@ -1300,11 +1298,9 @@ await start({
|
|
|
1300
1298
|
port,
|
|
1301
1299
|
serve: (app, port) => { serve({ fetch: app.fetch, port }); },
|
|
1302
1300
|
});
|
|
1303
|
-
|
|
1304
|
-
await (0, node_fs_promises.writeFile)(serverPath, content);
|
|
1301
|
+
`);
|
|
1305
1302
|
}
|
|
1306
1303
|
};
|
|
1307
|
-
|
|
1308
1304
|
//#endregion
|
|
1309
1305
|
//#region src/generators/OpenApiTsGenerator.ts
|
|
1310
1306
|
/**
|
|
@@ -1455,11 +1451,11 @@ var OpenApiTsGenerator = class {
|
|
|
1455
1451
|
}
|
|
1456
1452
|
}
|
|
1457
1453
|
}
|
|
1458
|
-
const registrySchemas = await (0,
|
|
1454
|
+
const registrySchemas = await (0, _geekmidas_schema_conversion.getRegisteredZodJsonSchemas)();
|
|
1459
1455
|
for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
|
|
1460
1456
|
const defName = this.pascalCase(rawName);
|
|
1461
1457
|
if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
|
|
1462
|
-
const { id: _id, $defs: _defs
|
|
1458
|
+
const { id: _id, $defs: _defs, ...rest } = rawSchema;
|
|
1463
1459
|
collectedDefs.set(defName, rest);
|
|
1464
1460
|
}
|
|
1465
1461
|
for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
|
|
@@ -1475,7 +1471,7 @@ var OpenApiTsGenerator = class {
|
|
|
1475
1471
|
*/
|
|
1476
1472
|
async getSchemaName(schema, defaultName) {
|
|
1477
1473
|
try {
|
|
1478
|
-
const metadata = await (0,
|
|
1474
|
+
const metadata = await (0, _geekmidas_schema_conversion.getSchemaMetadata)(schema);
|
|
1479
1475
|
if (metadata?.id) return this.pascalCase(metadata.id);
|
|
1480
1476
|
} catch {}
|
|
1481
1477
|
return defaultName;
|
|
@@ -1495,27 +1491,29 @@ var OpenApiTsGenerator = class {
|
|
|
1495
1491
|
async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
|
|
1496
1492
|
try {
|
|
1497
1493
|
const vendor = schema["~standard"]?.vendor;
|
|
1498
|
-
if (!vendor || !(vendor in
|
|
1499
|
-
const toJsonSchema =
|
|
1494
|
+
if (!vendor || !(vendor in _geekmidas_schema_conversion.StandardSchemaJsonSchema)) return unknownType(name);
|
|
1495
|
+
const toJsonSchema = _geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
|
|
1500
1496
|
const jsonSchema = await toJsonSchema(schema);
|
|
1501
|
-
if (!jsonSchema) return
|
|
1497
|
+
if (!jsonSchema) return unknownType(name);
|
|
1502
1498
|
if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
|
|
1503
1499
|
for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
|
|
1504
|
-
const { id
|
|
1500
|
+
const { id, ...schemaWithoutId } = defSchema;
|
|
1505
1501
|
collectedDefs.set(defName, schemaWithoutId);
|
|
1506
1502
|
}
|
|
1507
1503
|
}
|
|
1508
|
-
const { $defs
|
|
1504
|
+
const { $defs, ...schemaWithoutDefs } = jsonSchema;
|
|
1505
|
+
const ref = schemaWithoutDefs.$ref;
|
|
1506
|
+
if (ref && Object.keys(schemaWithoutDefs).every((k) => k === "$ref" || k === "$schema")) {
|
|
1507
|
+
const target = ref.split("/").pop();
|
|
1508
|
+
return target === name ? null : `export type ${name} = ${target};`;
|
|
1509
|
+
}
|
|
1509
1510
|
return this.jsonSchemaToInterface(schemaWithoutDefs, name);
|
|
1510
1511
|
} catch {
|
|
1511
|
-
return
|
|
1512
|
+
return unknownType(name);
|
|
1512
1513
|
}
|
|
1513
1514
|
}
|
|
1514
1515
|
jsonSchemaToInterface(schema, name) {
|
|
1515
|
-
if (schema.type !== "object" || !schema.properties) {
|
|
1516
|
-
const typeStr = this.jsonSchemaTypeToTs(schema);
|
|
1517
|
-
return `export type ${name} = ${typeStr};`;
|
|
1518
|
-
}
|
|
1516
|
+
if (schema.type !== "object" || !schema.properties) return `export type ${name} = ${this.jsonSchemaTypeToTs(schema)};`;
|
|
1519
1517
|
const props = [];
|
|
1520
1518
|
const required = new Set(schema.required || []);
|
|
1521
1519
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
@@ -1528,13 +1526,15 @@ var OpenApiTsGenerator = class {
|
|
|
1528
1526
|
}
|
|
1529
1527
|
jsonSchemaTypeToTs(schema) {
|
|
1530
1528
|
if (!schema) return "unknown";
|
|
1531
|
-
if (schema.$ref)
|
|
1532
|
-
|
|
1533
|
-
return refName;
|
|
1534
|
-
}
|
|
1529
|
+
if (schema.$ref) return schema.$ref.split("/").pop() || "unknown";
|
|
1530
|
+
if (schema.const !== void 0) return typeof schema.const === "string" ? `'${schema.const}'` : String(schema.const);
|
|
1535
1531
|
if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
1536
1532
|
if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
1537
1533
|
if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
|
|
1534
|
+
if (Array.isArray(schema.type)) return schema.type.map((type) => this.jsonSchemaTypeToTs({
|
|
1535
|
+
...schema,
|
|
1536
|
+
type
|
|
1537
|
+
})).join(" | ");
|
|
1538
1538
|
switch (schema.type) {
|
|
1539
1539
|
case "string":
|
|
1540
1540
|
if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
|
|
@@ -1558,10 +1558,7 @@ var OpenApiTsGenerator = class {
|
|
|
1558
1558
|
}
|
|
1559
1559
|
return `{ ${props.join("; ")} }`;
|
|
1560
1560
|
}
|
|
1561
|
-
if (schema.additionalProperties) {
|
|
1562
|
-
const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
|
|
1563
|
-
return `Record<string, ${valueType}>`;
|
|
1564
|
-
}
|
|
1561
|
+
if (schema.additionalProperties) return `Record<string, ${this.jsonSchemaTypeToTs(schema.additionalProperties)}>`;
|
|
1565
1562
|
return "Record<string, unknown>";
|
|
1566
1563
|
default: return "unknown";
|
|
1567
1564
|
}
|
|
@@ -1582,10 +1579,7 @@ var OpenApiTsGenerator = class {
|
|
|
1582
1579
|
}
|
|
1583
1580
|
const firstWithParams = infos.find((i) => i.input?.params);
|
|
1584
1581
|
let paramsEntry = "";
|
|
1585
|
-
if (firstWithParams?.input?.params) {
|
|
1586
|
-
const paramsName = await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`);
|
|
1587
|
-
paramsEntry = `\n parameters: {\n path: ${paramsName};\n };`;
|
|
1588
|
-
}
|
|
1582
|
+
if (firstWithParams?.input?.params) paramsEntry = `\n parameters: {\n path: ${await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`)};\n };`;
|
|
1589
1583
|
pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
|
|
1590
1584
|
}
|
|
1591
1585
|
return `export interface paths {\n${pathEntries.join("\n")}\n}`;
|
|
@@ -1624,8 +1618,7 @@ var OpenApiTsGenerator = class {
|
|
|
1624
1618
|
return acc;
|
|
1625
1619
|
}, {});
|
|
1626
1620
|
const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
|
|
1627
|
-
const
|
|
1628
|
-
const createApiSection = hasSecuritySchemes ? `
|
|
1621
|
+
const createApiSection = schemeNames.length > 0 ? `
|
|
1629
1622
|
// ============================================================
|
|
1630
1623
|
// API Client Factory
|
|
1631
1624
|
// ============================================================
|
|
@@ -1802,20 +1795,14 @@ ${createApiSection}
|
|
|
1802
1795
|
`;
|
|
1803
1796
|
}
|
|
1804
1797
|
};
|
|
1805
|
-
|
|
1806
|
-
//#endregion
|
|
1807
|
-
//#region src/workspace/client-generator.ts
|
|
1808
1798
|
/**
|
|
1809
|
-
*
|
|
1810
|
-
*
|
|
1811
|
-
*
|
|
1799
|
+
* The declaration for a schema that cannot be converted — a vendor with no
|
|
1800
|
+
* converter, or one that fails. The paths interface names it either way, so
|
|
1801
|
+
* leaving it undeclared made the generated client fail to compile.
|
|
1812
1802
|
*/
|
|
1813
|
-
function
|
|
1814
|
-
|
|
1815
|
-
if (require_discover.isPartitionedRoutes(routes)) return Array.isArray(routes.paths) ? routes.paths : [routes.paths];
|
|
1816
|
-
return Array.isArray(routes) ? routes : [routes];
|
|
1803
|
+
function unknownType(name) {
|
|
1804
|
+
return `export type ${name} = unknown;`;
|
|
1817
1805
|
}
|
|
1818
|
-
|
|
1819
1806
|
//#endregion
|
|
1820
1807
|
//#region src/openapi.ts
|
|
1821
1808
|
/**
|
|
@@ -1823,6 +1810,16 @@ function normalizeRoutes(routes) {
|
|
|
1823
1810
|
*/
|
|
1824
1811
|
const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
|
|
1825
1812
|
/**
|
|
1813
|
+
* Where a surface's generated client lands.
|
|
1814
|
+
*
|
|
1815
|
+
* Named from the surface, so `new RestApi('Webhooks')` writes
|
|
1816
|
+
* `.gkm/openapi/webhooks.ts` — the same kebab form that gives it its container
|
|
1817
|
+
* name and its `WEBHOOKS_URL`.
|
|
1818
|
+
*/
|
|
1819
|
+
function openApiPathFor(surfaceId) {
|
|
1820
|
+
return `./.gkm/openapi/${(0, _geekmidas_manifest.kebabCase)(surfaceId)}.ts`;
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1826
1823
|
* Resolve OpenAPI config from GkmConfig
|
|
1827
1824
|
*/
|
|
1828
1825
|
function resolveOpenApiConfig(config) {
|
|
@@ -1841,33 +1838,65 @@ function resolveOpenApiConfig(config) {
|
|
|
1841
1838
|
};
|
|
1842
1839
|
}
|
|
1843
1840
|
/**
|
|
1844
|
-
*
|
|
1845
|
-
*
|
|
1841
|
+
* Load endpoints from a glob, then generate.
|
|
1842
|
+
*
|
|
1843
|
+
* For the callers that have no endpoints in hand — `gkm openapi`, and `gkm dev`
|
|
1844
|
+
* regenerating on reload. The glob is the app's derived one — the conventional
|
|
1845
|
+
* directories under it — not a `routes` field anybody wrote.
|
|
1846
1846
|
*/
|
|
1847
|
-
async function
|
|
1847
|
+
async function generateOpenApiFrom(routes, options = {}) {
|
|
1848
|
+
return generateOpenApi((await new EndpointGenerator().load(routes, void 0, options.bustCache)).map(({ construct }) => construct), options);
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Generate an OpenAPI spec for each surface these endpoints name.
|
|
1852
|
+
*
|
|
1853
|
+
* Takes the endpoints, not a glob to find them with. The build has already
|
|
1854
|
+
* loaded every one of them to generate handlers, so globbing again was a second
|
|
1855
|
+
* discovery pass over the same files — and the reason this function needed a
|
|
1856
|
+
* `routes` to be told where to look, which is how a retired config field stayed
|
|
1857
|
+
* load-bearing.
|
|
1858
|
+
*
|
|
1859
|
+
* @returns What was written, or null if disabled or there were none
|
|
1860
|
+
*/
|
|
1861
|
+
async function generateOpenApi(endpoints, options = {}) {
|
|
1848
1862
|
const logger = options.silent ? { log: () => {} } : console;
|
|
1849
|
-
const openApiConfig = resolveOpenApiConfig(
|
|
1863
|
+
const openApiConfig = resolveOpenApiConfig({ openapi: options.openapi });
|
|
1850
1864
|
if (!openApiConfig.enabled) return null;
|
|
1851
|
-
|
|
1852
|
-
const loadedEndpoints = await endpointGenerator.load(config.routes, void 0, options.bustCache);
|
|
1853
|
-
if (loadedEndpoints.length === 0) {
|
|
1865
|
+
if (endpoints.length === 0) {
|
|
1854
1866
|
logger.log("No valid endpoints found for OpenAPI generation");
|
|
1855
1867
|
return null;
|
|
1856
1868
|
}
|
|
1857
|
-
const
|
|
1858
|
-
const
|
|
1859
|
-
|
|
1869
|
+
const bySurface = /* @__PURE__ */ new Map();
|
|
1870
|
+
for (const endpoint of endpoints) {
|
|
1871
|
+
const owner = endpoint.owner ?? endpoint.surface?.id;
|
|
1872
|
+
if (!owner) continue;
|
|
1873
|
+
const existing = bySurface.get(owner);
|
|
1874
|
+
if (existing) existing.push(endpoint);
|
|
1875
|
+
else bySurface.set(owner, [endpoint]);
|
|
1876
|
+
}
|
|
1877
|
+
if (bySurface.size === 0) {
|
|
1878
|
+
logger.log("No endpoints named a surface, so no OpenAPI was generated");
|
|
1879
|
+
return null;
|
|
1880
|
+
}
|
|
1860
1881
|
const tsGenerator = new OpenApiTsGenerator();
|
|
1861
|
-
const
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1882
|
+
const written = [];
|
|
1883
|
+
for (const [surfaceId, surfaceEndpoints] of bySurface) {
|
|
1884
|
+
const relative = openApiPathFor(surfaceId);
|
|
1885
|
+
const outputPath = (0, node_path.join)(process.cwd(), relative);
|
|
1886
|
+
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
|
|
1887
|
+
const tsContent = await tsGenerator.generate(surfaceEndpoints, {
|
|
1888
|
+
title: openApiConfig.title ?? surfaceId,
|
|
1889
|
+
version: openApiConfig.version,
|
|
1890
|
+
description: openApiConfig.description
|
|
1891
|
+
});
|
|
1892
|
+
await (0, node_fs_promises.writeFile)(outputPath, tsContent);
|
|
1893
|
+
written.push(relative);
|
|
1894
|
+
logger.log(`📄 OpenAPI client generated: ${relative} (${surfaceEndpoints.length} endpoints)`);
|
|
1895
|
+
}
|
|
1868
1896
|
return {
|
|
1869
|
-
outputPath,
|
|
1870
|
-
|
|
1897
|
+
outputPath: (0, node_path.join)(process.cwd(), written[0]),
|
|
1898
|
+
outputPaths: written.map((r) => (0, node_path.join)(process.cwd(), r)),
|
|
1899
|
+
endpointCount: endpoints.length
|
|
1871
1900
|
};
|
|
1872
1901
|
}
|
|
1873
1902
|
async function openapiCommand(options = {}) {
|
|
@@ -1877,12 +1906,12 @@ async function openapiCommand(options = {}) {
|
|
|
1877
1906
|
if (loadedConfig.type === "single") {
|
|
1878
1907
|
const config = loadedConfig.raw;
|
|
1879
1908
|
if (!config.openapi) config.openapi = { enabled: true };
|
|
1880
|
-
const result = await
|
|
1909
|
+
const result = await generateOpenApiFrom(config.constructs, { openapi: config.openapi });
|
|
1881
1910
|
if (result) logger.log(`Found ${result.endpointCount} endpoints`);
|
|
1882
1911
|
} else {
|
|
1883
1912
|
const { workspace } = loadedConfig;
|
|
1884
1913
|
const workspaceRoot = workspace.root;
|
|
1885
|
-
const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend" && app.
|
|
1914
|
+
const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend" && app.openapi !== false && (typeof app.openapi !== "object" || app.openapi.enabled !== false));
|
|
1886
1915
|
if (backendApps.length === 0) {
|
|
1887
1916
|
logger.log("No backend apps with OpenAPI enabled found");
|
|
1888
1917
|
return;
|
|
@@ -1896,8 +1925,12 @@ async function openapiCommand(options = {}) {
|
|
|
1896
1925
|
return;
|
|
1897
1926
|
}
|
|
1898
1927
|
for (const [appName, app] of backendApps) {
|
|
1899
|
-
if (app.type !== "backend" || !app.routes) continue;
|
|
1900
1928
|
const appPath = (0, node_path.join)(workspaceRoot, app.path);
|
|
1929
|
+
if ((0, node_path.resolve)(appPath) === (0, node_path.resolve)(workspaceRoot)) {
|
|
1930
|
+
const result = await generateOpenApiForApp(workspaceRoot, appName, app, false);
|
|
1931
|
+
if (result) logger.log(`Found ${result.endpointCount} endpoints`);
|
|
1932
|
+
continue;
|
|
1933
|
+
}
|
|
1901
1934
|
await runOpenApiInSubprocess(appPath, appName);
|
|
1902
1935
|
}
|
|
1903
1936
|
}
|
|
@@ -1910,18 +1943,13 @@ async function openapiCommand(options = {}) {
|
|
|
1910
1943
|
* Runs in-process. The caller is responsible for ensuring `process.cwd()`
|
|
1911
1944
|
* is the app's directory so tsx loads the app's tsconfig path aliases.
|
|
1912
1945
|
*/
|
|
1913
|
-
async function generateOpenApiForApp(workspaceRoot, _appName, app) {
|
|
1914
|
-
if (app.type !== "backend"
|
|
1946
|
+
async function generateOpenApiForApp(workspaceRoot, _appName, app, silent = true) {
|
|
1947
|
+
if (app.type !== "backend") return null;
|
|
1915
1948
|
const appPath = (0, node_path.join)(workspaceRoot, app.path);
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
envParser: app.envParser || "",
|
|
1921
|
-
logger: app.logger || "",
|
|
1922
|
-
openapi: app.openapi
|
|
1923
|
-
};
|
|
1924
|
-
return generateOpenApi(gkmConfig, { silent: true });
|
|
1949
|
+
return generateOpenApiFrom([(0, node_path.join)(appPath, "**/*.ts")], {
|
|
1950
|
+
openapi: app.openapi ?? { enabled: true },
|
|
1951
|
+
silent
|
|
1952
|
+
});
|
|
1925
1953
|
}
|
|
1926
1954
|
/**
|
|
1927
1955
|
* Resolve the gkm bin path. Tests can override via `GKM_BIN_PATH` env var
|
|
@@ -1953,46 +1981,58 @@ async function runOpenApiInSubprocess(appCwd, appName) {
|
|
|
1953
1981
|
child.on("error", reject);
|
|
1954
1982
|
child.on("close", (code) => {
|
|
1955
1983
|
if (code === 0) resolve();
|
|
1956
|
-
else reject(new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
|
|
1984
|
+
else reject(/* @__PURE__ */ new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
|
|
1957
1985
|
});
|
|
1958
1986
|
});
|
|
1959
1987
|
}
|
|
1960
|
-
|
|
1961
1988
|
//#endregion
|
|
1962
|
-
Object.defineProperty(exports,
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1989
|
+
Object.defineProperty(exports, "EndpointGenerator", {
|
|
1990
|
+
enumerable: true,
|
|
1991
|
+
get: function() {
|
|
1992
|
+
return EndpointGenerator;
|
|
1993
|
+
}
|
|
1967
1994
|
});
|
|
1968
|
-
Object.defineProperty(exports,
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1995
|
+
Object.defineProperty(exports, "OPENAPI_OUTPUT_PATH", {
|
|
1996
|
+
enumerable: true,
|
|
1997
|
+
get: function() {
|
|
1998
|
+
return OPENAPI_OUTPUT_PATH;
|
|
1999
|
+
}
|
|
1973
2000
|
});
|
|
1974
|
-
Object.defineProperty(exports,
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2001
|
+
Object.defineProperty(exports, "generateOpenApi", {
|
|
2002
|
+
enumerable: true,
|
|
2003
|
+
get: function() {
|
|
2004
|
+
return generateOpenApi;
|
|
2005
|
+
}
|
|
1979
2006
|
});
|
|
1980
|
-
Object.defineProperty(exports,
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
2007
|
+
Object.defineProperty(exports, "generateOpenApiFrom", {
|
|
2008
|
+
enumerable: true,
|
|
2009
|
+
get: function() {
|
|
2010
|
+
return generateOpenApiFrom;
|
|
2011
|
+
}
|
|
1985
2012
|
});
|
|
1986
|
-
Object.defineProperty(exports,
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
2013
|
+
Object.defineProperty(exports, "openApiPathFor", {
|
|
2014
|
+
enumerable: true,
|
|
2015
|
+
get: function() {
|
|
2016
|
+
return openApiPathFor;
|
|
2017
|
+
}
|
|
1991
2018
|
});
|
|
1992
|
-
Object.defineProperty(exports,
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
2019
|
+
Object.defineProperty(exports, "openapiCommand", {
|
|
2020
|
+
enumerable: true,
|
|
2021
|
+
get: function() {
|
|
2022
|
+
return openapiCommand;
|
|
2023
|
+
}
|
|
2024
|
+
});
|
|
2025
|
+
Object.defineProperty(exports, "resolveOpenApiConfig", {
|
|
2026
|
+
enumerable: true,
|
|
2027
|
+
get: function() {
|
|
2028
|
+
return resolveOpenApiConfig;
|
|
2029
|
+
}
|
|
2030
|
+
});
|
|
2031
|
+
Object.defineProperty(exports, "runtimeFor", {
|
|
2032
|
+
enumerable: true,
|
|
2033
|
+
get: function() {
|
|
2034
|
+
return runtimeFor;
|
|
2035
|
+
}
|
|
1997
2036
|
});
|
|
1998
|
-
|
|
2037
|
+
|
|
2038
|
+
//# sourceMappingURL=openapi-B8bu_OXN.cjs.map
|