@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,12 +1,12 @@
|
|
|
1
|
-
import { ConstructGenerator
|
|
2
|
-
import { loadWorkspaceConfig } from "./config-
|
|
3
|
-
import { dirname, join, relative } from "node:path";
|
|
1
|
+
import { r as ConstructGenerator } from "./discover-CK-n3w6b.mjs";
|
|
2
|
+
import { o as loadWorkspaceConfig } from "./config-DdKkoUE1.mjs";
|
|
4
3
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
|
+
import { kebabCase } from "@geekmidas/manifest";
|
|
6
7
|
import { Endpoint } from "@geekmidas/constructs/endpoints";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
8
9
|
import { StandardSchemaJsonSchema, getRegisteredZodJsonSchemas, getSchemaMetadata } from "@geekmidas/schema/conversion";
|
|
9
|
-
|
|
10
10
|
//#region src/build/endpoint-analyzer.ts
|
|
11
11
|
/**
|
|
12
12
|
* Analyze an endpoint to extract its features
|
|
@@ -83,7 +83,6 @@ function summarizeAnalysis(analyses) {
|
|
|
83
83
|
byFeature
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
|
-
|
|
87
86
|
//#endregion
|
|
88
87
|
//#region src/build/handler-templates.ts
|
|
89
88
|
/**
|
|
@@ -105,8 +104,7 @@ function generateMinimalHandler(analysis) {
|
|
|
105
104
|
const { exportName, features } = analysis;
|
|
106
105
|
const method = analysis.method.toLowerCase();
|
|
107
106
|
const validators = generateValidators(exportName, features);
|
|
108
|
-
|
|
109
|
-
if (!hasValidators && !features.hasOutputValidation) return `
|
|
107
|
+
if (!(validators.length > 0) && !features.hasOutputValidation) return `
|
|
110
108
|
// Minimal handler: ${analysis.route} (${analysis.method})
|
|
111
109
|
app.${method}('${analysis.route}', async (c) => {
|
|
112
110
|
const result = await ${exportName}.handler(
|
|
@@ -304,8 +302,7 @@ ${factories.join("\n")}
|
|
|
304
302
|
*/
|
|
305
303
|
function generateMinimalEndpointFile(analysis, endpointImport) {
|
|
306
304
|
const { exportName, features } = analysis;
|
|
307
|
-
const
|
|
308
|
-
const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
305
|
+
const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
309
306
|
const handler = generateMinimalHandler(analysis);
|
|
310
307
|
return `/**
|
|
311
308
|
* Minimal endpoint: ${analysis.route} (${analysis.method})
|
|
@@ -330,8 +327,7 @@ ${handler}
|
|
|
330
327
|
*/
|
|
331
328
|
function generateStandardEndpointFile(analysis, endpointImport) {
|
|
332
329
|
const { exportName, features } = analysis;
|
|
333
|
-
const
|
|
334
|
-
const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
330
|
+
const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
335
331
|
const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
|
|
336
332
|
const handler = generateStandardHandler(analysis);
|
|
337
333
|
return `/**
|
|
@@ -423,7 +419,7 @@ export function setupFullEndpoints(
|
|
|
423
419
|
}
|
|
424
420
|
const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
|
|
425
421
|
if (tier === "minimal") {
|
|
426
|
-
const calls
|
|
422
|
+
const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
|
|
427
423
|
return `/**
|
|
428
424
|
* Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
|
|
429
425
|
* Near-raw-Hono performance
|
|
@@ -436,12 +432,12 @@ export function setupMinimalEndpoints(
|
|
|
436
432
|
app: Hono,
|
|
437
433
|
logger: Logger,
|
|
438
434
|
): void {
|
|
439
|
-
${calls
|
|
435
|
+
${calls}
|
|
440
436
|
}
|
|
441
437
|
`;
|
|
442
438
|
}
|
|
443
439
|
if (tier === "standard") {
|
|
444
|
-
const calls
|
|
440
|
+
const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
|
|
445
441
|
return `/**
|
|
446
442
|
* Standard-tier endpoint index (${tierEndpoints.length} endpoints)
|
|
447
443
|
* Auth and/or services enabled
|
|
@@ -456,7 +452,7 @@ export function setupStandardEndpoints(
|
|
|
456
452
|
serviceDiscovery: ServiceDiscovery<any, any>,
|
|
457
453
|
logger: Logger,
|
|
458
454
|
): void {
|
|
459
|
-
${calls
|
|
455
|
+
${calls}
|
|
460
456
|
}
|
|
461
457
|
`;
|
|
462
458
|
}
|
|
@@ -526,9 +522,7 @@ function generateEndpointFilesNested(analyses, endpointImports) {
|
|
|
526
522
|
case "standard":
|
|
527
523
|
files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
|
|
528
524
|
break;
|
|
529
|
-
case "full":
|
|
530
|
-
files[fileName] = generateFullEndpointFile(analysis, endpointImport);
|
|
531
|
-
break;
|
|
525
|
+
case "full": files[fileName] = generateFullEndpointFile(analysis, endpointImport);
|
|
532
526
|
}
|
|
533
527
|
}
|
|
534
528
|
return files;
|
|
@@ -585,7 +579,6 @@ export async function setupEndpoints(
|
|
|
585
579
|
}
|
|
586
580
|
`;
|
|
587
581
|
}
|
|
588
|
-
|
|
589
582
|
//#endregion
|
|
590
583
|
//#region src/generators/EndpointGenerator.ts
|
|
591
584
|
/**
|
|
@@ -602,24 +595,21 @@ export async function setupEndpoints(
|
|
|
602
595
|
*
|
|
603
596
|
* Falls back to the configured paths for an app that declares no surface.
|
|
604
597
|
*/
|
|
605
|
-
function runtimeFor(context, fromDir) {
|
|
606
|
-
const module = context.surface?.module;
|
|
598
|
+
function runtimeFor(context, fromDir, owner) {
|
|
599
|
+
const module = owner ? context.owners?.[owner] ?? context.surface?.module : context.surface?.module;
|
|
607
600
|
if (module) {
|
|
608
601
|
const specifier = importSpecifier(fromDir, module.specifier);
|
|
609
602
|
return {
|
|
610
603
|
imports: `import { ${module.exportName} as __surface } from '${specifier}';`,
|
|
611
604
|
bindings: [
|
|
612
|
-
"// What this
|
|
613
|
-
"// 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.",
|
|
614
607
|
"const envParser = __surface.envParser;",
|
|
615
608
|
"const logger = __surface.logger;"
|
|
616
609
|
].join("\n")
|
|
617
610
|
};
|
|
618
611
|
}
|
|
619
|
-
|
|
620
|
-
imports: [`import ${context.envParserImportPattern} from '${importSpecifier(fromDir, context.envParserPath)}';`, `import ${context.loggerImportPattern} from '${importSpecifier(fromDir, context.loggerPath)}';`].join("\n"),
|
|
621
|
-
bindings: ""
|
|
622
|
-
};
|
|
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\`.`);
|
|
623
613
|
}
|
|
624
614
|
/** A relative specifier ESM will accept: always prefixed, never bare. */
|
|
625
615
|
function importSpecifier(fromDir, target) {
|
|
@@ -734,8 +724,7 @@ var EndpointGenerator = class extends ConstructGenerator {
|
|
|
734
724
|
async generateHandlerFile(outputDir, sourceFile, exportName, provider, _endpoint, context) {
|
|
735
725
|
const handlerFileName = `${exportName}.ts`;
|
|
736
726
|
const handlerPath = join(outputDir, handlerFileName);
|
|
737
|
-
const
|
|
738
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
727
|
+
const importPath = relative(dirname(handlerPath), sourceFile).replace(/\.ts$/, ".js");
|
|
739
728
|
let content;
|
|
740
729
|
switch (provider) {
|
|
741
730
|
case "aws-apigatewayv1":
|
|
@@ -753,12 +742,10 @@ var EndpointGenerator = class extends ConstructGenerator {
|
|
|
753
742
|
return handlerPath;
|
|
754
743
|
}
|
|
755
744
|
async generateEndpointsFile(outputDir, endpoints, context) {
|
|
756
|
-
const
|
|
757
|
-
const endpointsPath = join(outputDir, endpointsFileName);
|
|
745
|
+
const endpointsPath = join(outputDir, "endpoints.ts");
|
|
758
746
|
const importsByFile = /* @__PURE__ */ new Map();
|
|
759
747
|
for (const { path, key } of endpoints) {
|
|
760
|
-
const
|
|
761
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
748
|
+
const importPath = relative(dirname(endpointsPath), path.relative).replace(/\.ts$/, ".js");
|
|
762
749
|
if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
|
|
763
750
|
importsByFile.get(importPath)?.push(key);
|
|
764
751
|
}
|
|
@@ -824,11 +811,9 @@ export async function setupEndpoints(
|
|
|
824
811
|
const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
|
|
825
812
|
const endpointImports = endpoints.map(({ key, path }) => {
|
|
826
813
|
const tierDir = join(endpointsDir, "standard");
|
|
827
|
-
const relativePath = relative(tierDir, path.relative);
|
|
828
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
829
814
|
return {
|
|
830
815
|
exportName: key,
|
|
831
|
-
importPath
|
|
816
|
+
importPath: relative(tierDir, path.relative).replace(/\.ts$/, ".js")
|
|
832
817
|
};
|
|
833
818
|
});
|
|
834
819
|
const summary = summarizeAnalysis(analyses);
|
|
@@ -850,8 +835,7 @@ export async function setupEndpoints(
|
|
|
850
835
|
}
|
|
851
836
|
async generateAppFile(outputDir, context) {
|
|
852
837
|
if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
|
|
853
|
-
const
|
|
854
|
-
const appPath = join(outputDir, appFileName);
|
|
838
|
+
const appPath = join(outputDir, "app.ts");
|
|
855
839
|
const runtime = runtimeFor(context, dirname(appPath));
|
|
856
840
|
const telescopeEnabled = context.telescope?.enabled;
|
|
857
841
|
const telescopeWebSocketEnabled = context.telescope?.websocket;
|
|
@@ -861,32 +845,35 @@ export async function setupEndpoints(
|
|
|
861
845
|
const studioFromDatabase = !usesExternalStudio && !!context.studio?.database;
|
|
862
846
|
const telescopeFromSurface = !!context.surface?.module && !usesExternalTelescope;
|
|
863
847
|
let telescopeImports = "";
|
|
864
|
-
if (telescopeEnabled)
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
848
|
+
if (telescopeEnabled) {
|
|
849
|
+
if (telescopeFromSurface) telescopeImports = "import { createMiddleware, createUI } from '@geekmidas/telescope/hono';";
|
|
850
|
+
else if (usesExternalTelescope) {
|
|
851
|
+
const relativeTelescopePath = relative(dirname(appPath), context.telescope?.telescopePath);
|
|
852
|
+
telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
|
|
868
853
|
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
869
|
-
|
|
854
|
+
} else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
|
|
870
855
|
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
856
|
+
}
|
|
871
857
|
let studioImports = "";
|
|
872
|
-
if (studioEnabled)
|
|
873
|
-
|
|
874
|
-
|
|
858
|
+
if (studioEnabled) {
|
|
859
|
+
if (usesExternalStudio) {
|
|
860
|
+
const relativeStudioPath = relative(dirname(appPath), context.studio?.studioPath);
|
|
861
|
+
studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
|
|
875
862
|
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
863
|
+
} else if (studioFromDatabase) {
|
|
864
|
+
const dbSpecifier = importSpecifier(dirname(appPath), context.studio.database.specifier);
|
|
865
|
+
studioImports = `import { snifferContext } from '@geekmidas/constructs';
|
|
879
866
|
import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
|
|
880
867
|
import { ${context.studio.database.exportName} as __studioDb } from '${dbSpecifier}';
|
|
881
868
|
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
882
|
-
|
|
869
|
+
} else studioImports = "";
|
|
870
|
+
}
|
|
883
871
|
const cors = corsFor(context.surface);
|
|
884
872
|
let hooksImports = "";
|
|
885
873
|
let beforeSetupCall = "";
|
|
886
874
|
let afterSetupCall = "";
|
|
887
875
|
if (context.hooks?.serverHooksPath) {
|
|
888
|
-
|
|
889
|
-
hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
|
|
876
|
+
hooksImports = `import * as serverHooks from '${relative(dirname(appPath), context.hooks.serverHooksPath)}';`;
|
|
890
877
|
beforeSetupCall = `
|
|
891
878
|
// Call beforeSetup hook if defined
|
|
892
879
|
if (typeof serverHooks.beforeSetup === 'function') {
|
|
@@ -932,7 +919,8 @@ import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
|
932
919
|
}
|
|
933
920
|
` : "";
|
|
934
921
|
let telescopeSetup = "";
|
|
935
|
-
if (telescopeEnabled)
|
|
922
|
+
if (telescopeEnabled) {
|
|
923
|
+
if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
|
|
936
924
|
${telescopeWebSocketSetupCode}
|
|
937
925
|
// Add telescope middleware (before endpoints to capture all requests)
|
|
938
926
|
honoApp.use('*', createMiddleware(telescope));
|
|
@@ -941,7 +929,7 @@ ${telescopeWebSocketSetupCode}
|
|
|
941
929
|
const telescopeUI = createUI(telescope);
|
|
942
930
|
honoApp.route('${context.telescope?.path}', telescopeUI);
|
|
943
931
|
`;
|
|
944
|
-
|
|
932
|
+
else telescopeSetup = `
|
|
945
933
|
// Setup Telescope for debugging/monitoring
|
|
946
934
|
const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
|
|
947
935
|
const telescope = new Telescope({
|
|
@@ -959,6 +947,7 @@ ${telescopeWebSocketSetupCode}
|
|
|
959
947
|
const telescopeUI = createUI(telescope);
|
|
960
948
|
honoApp.route('${context.telescope?.path}', telescopeUI);
|
|
961
949
|
`;
|
|
950
|
+
}
|
|
962
951
|
let studioSetup = "";
|
|
963
952
|
if (studioEnabled && studioFromDatabase) studioSetup = `
|
|
964
953
|
// Studio, built from the declared database. The client comes from the
|
|
@@ -992,6 +981,7 @@ import type { Hono as HonoType } from 'hono';
|
|
|
992
981
|
import { setupEndpoints } from './endpoints.js';
|
|
993
982
|
import { setupSubscribers } from './subscribers.js';
|
|
994
983
|
import { setupQueues } from './queues.js';
|
|
984
|
+
import { setupCrons } from './crons.js';
|
|
995
985
|
${runtime.imports}
|
|
996
986
|
${telescopeImports}
|
|
997
987
|
${studioImports}
|
|
@@ -1079,6 +1069,12 @@ ${afterSetupCall}
|
|
|
1079
1069
|
logger.error({ error }, 'Failed to start queue workers');
|
|
1080
1070
|
});
|
|
1081
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
|
+
|
|
1082
1078
|
logger.info({ port }, 'Starting server');
|
|
1083
1079
|
|
|
1084
1080
|
// Start HTTP server using provided serve function
|
|
@@ -1147,10 +1143,8 @@ export const handler = ${exportName};
|
|
|
1147
1143
|
* No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
|
|
1148
1144
|
*/
|
|
1149
1145
|
async generateProductionAppFile(outputDir, context) {
|
|
1150
|
-
const
|
|
1151
|
-
const
|
|
1152
|
-
const relativeLoggerPath = relative(dirname(appPath), context.loggerPath);
|
|
1153
|
-
const relativeEnvParserPath = relative(dirname(appPath), context.envParserPath);
|
|
1146
|
+
const appPath = join(outputDir, "app.ts");
|
|
1147
|
+
const runtime = runtimeFor(context, dirname(appPath));
|
|
1154
1148
|
const production = context.production;
|
|
1155
1149
|
const healthCheckPath = production.healthCheck;
|
|
1156
1150
|
const enableGracefulShutdown = production.gracefulShutdown;
|
|
@@ -1161,8 +1155,7 @@ export const handler = ${exportName};
|
|
|
1161
1155
|
let beforeSetupCall = "";
|
|
1162
1156
|
let afterSetupCall = "";
|
|
1163
1157
|
if (context.hooks?.serverHooksPath) {
|
|
1164
|
-
|
|
1165
|
-
hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
|
|
1158
|
+
hooksImports = `import * as serverHooks from '${relative(dirname(appPath), context.hooks.serverHooksPath)}';`;
|
|
1166
1159
|
beforeSetupCall = `
|
|
1167
1160
|
// Call beforeSetup hook if defined
|
|
1168
1161
|
if (typeof serverHooks.beforeSetup === 'function') {
|
|
@@ -1186,9 +1179,16 @@ export const handler = ${exportName};
|
|
|
1186
1179
|
await setupQueues(envParser, logger).catch((error) => {
|
|
1187
1180
|
logger.error({ error }, 'Failed to start queue workers');
|
|
1188
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
|
+
});
|
|
1189
1188
|
` : "";
|
|
1190
1189
|
const subscriberImport = includeSubscribers ? `import { setupSubscribers } from './subscribers.js';
|
|
1191
|
-
import { setupQueues } from './queues.js'
|
|
1190
|
+
import { setupQueues } from './queues.js';
|
|
1191
|
+
import { setupCrons } from './crons.js';` : "";
|
|
1192
1192
|
const gracefulShutdownCode = enableGracefulShutdown ? `
|
|
1193
1193
|
// Graceful shutdown handling
|
|
1194
1194
|
let isShuttingDown = false;
|
|
@@ -1204,7 +1204,6 @@ import { setupQueues } from './queues.js';` : "";
|
|
|
1204
1204
|
process.on('SIGTERM', shutdown);
|
|
1205
1205
|
process.on('SIGINT', shutdown);
|
|
1206
1206
|
` : "";
|
|
1207
|
-
const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
|
|
1208
1207
|
const content = `/**
|
|
1209
1208
|
* Generated production server application
|
|
1210
1209
|
*
|
|
@@ -1216,10 +1215,10 @@ import { setupQueues } from './queues.js';` : "";
|
|
|
1216
1215
|
*/
|
|
1217
1216
|
import { Hono } from 'hono';
|
|
1218
1217
|
import type { Hono as HonoType } from 'hono';
|
|
1219
|
-
import { setupEndpoints } from '${
|
|
1218
|
+
import { setupEndpoints } from '${production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js"}';
|
|
1220
1219
|
${subscriberImport}
|
|
1221
|
-
|
|
1222
|
-
|
|
1220
|
+
${runtime.imports}
|
|
1221
|
+
${runtime.bindings}
|
|
1223
1222
|
${hooksImports}
|
|
1224
1223
|
${cors.imports}
|
|
1225
1224
|
${context.storageDrivers?.imports ?? ""}
|
|
@@ -1283,7 +1282,7 @@ export default createApp;
|
|
|
1283
1282
|
*/
|
|
1284
1283
|
async generateProductionServerEntry(outputDir) {
|
|
1285
1284
|
const serverPath = join(outputDir, "server.ts");
|
|
1286
|
-
|
|
1285
|
+
await writeFile(serverPath, `#!/usr/bin/env node
|
|
1287
1286
|
/**
|
|
1288
1287
|
* Production server entry point
|
|
1289
1288
|
* Generated by 'gkm build --provider server --production'
|
|
@@ -1299,11 +1298,9 @@ await start({
|
|
|
1299
1298
|
port,
|
|
1300
1299
|
serve: (app, port) => { serve({ fetch: app.fetch, port }); },
|
|
1301
1300
|
});
|
|
1302
|
-
|
|
1303
|
-
await writeFile(serverPath, content);
|
|
1301
|
+
`);
|
|
1304
1302
|
}
|
|
1305
1303
|
};
|
|
1306
|
-
|
|
1307
1304
|
//#endregion
|
|
1308
1305
|
//#region src/generators/OpenApiTsGenerator.ts
|
|
1309
1306
|
/**
|
|
@@ -1458,7 +1455,7 @@ var OpenApiTsGenerator = class {
|
|
|
1458
1455
|
for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
|
|
1459
1456
|
const defName = this.pascalCase(rawName);
|
|
1460
1457
|
if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
|
|
1461
|
-
const { id: _id, $defs: _defs
|
|
1458
|
+
const { id: _id, $defs: _defs, ...rest } = rawSchema;
|
|
1462
1459
|
collectedDefs.set(defName, rest);
|
|
1463
1460
|
}
|
|
1464
1461
|
for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
|
|
@@ -1494,27 +1491,29 @@ var OpenApiTsGenerator = class {
|
|
|
1494
1491
|
async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
|
|
1495
1492
|
try {
|
|
1496
1493
|
const vendor = schema["~standard"]?.vendor;
|
|
1497
|
-
if (!vendor || !(vendor in StandardSchemaJsonSchema)) return
|
|
1494
|
+
if (!vendor || !(vendor in StandardSchemaJsonSchema)) return unknownType(name);
|
|
1498
1495
|
const toJsonSchema = StandardSchemaJsonSchema[vendor];
|
|
1499
1496
|
const jsonSchema = await toJsonSchema(schema);
|
|
1500
|
-
if (!jsonSchema) return
|
|
1497
|
+
if (!jsonSchema) return unknownType(name);
|
|
1501
1498
|
if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
|
|
1502
1499
|
for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
|
|
1503
|
-
const { id
|
|
1500
|
+
const { id, ...schemaWithoutId } = defSchema;
|
|
1504
1501
|
collectedDefs.set(defName, schemaWithoutId);
|
|
1505
1502
|
}
|
|
1506
1503
|
}
|
|
1507
|
-
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
|
+
}
|
|
1508
1510
|
return this.jsonSchemaToInterface(schemaWithoutDefs, name);
|
|
1509
1511
|
} catch {
|
|
1510
|
-
return
|
|
1512
|
+
return unknownType(name);
|
|
1511
1513
|
}
|
|
1512
1514
|
}
|
|
1513
1515
|
jsonSchemaToInterface(schema, name) {
|
|
1514
|
-
if (schema.type !== "object" || !schema.properties) {
|
|
1515
|
-
const typeStr = this.jsonSchemaTypeToTs(schema);
|
|
1516
|
-
return `export type ${name} = ${typeStr};`;
|
|
1517
|
-
}
|
|
1516
|
+
if (schema.type !== "object" || !schema.properties) return `export type ${name} = ${this.jsonSchemaTypeToTs(schema)};`;
|
|
1518
1517
|
const props = [];
|
|
1519
1518
|
const required = new Set(schema.required || []);
|
|
1520
1519
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
@@ -1527,13 +1526,15 @@ var OpenApiTsGenerator = class {
|
|
|
1527
1526
|
}
|
|
1528
1527
|
jsonSchemaTypeToTs(schema) {
|
|
1529
1528
|
if (!schema) return "unknown";
|
|
1530
|
-
if (schema.$ref)
|
|
1531
|
-
|
|
1532
|
-
return refName;
|
|
1533
|
-
}
|
|
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);
|
|
1534
1531
|
if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
1535
1532
|
if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
1536
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(" | ");
|
|
1537
1538
|
switch (schema.type) {
|
|
1538
1539
|
case "string":
|
|
1539
1540
|
if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
|
|
@@ -1557,10 +1558,7 @@ var OpenApiTsGenerator = class {
|
|
|
1557
1558
|
}
|
|
1558
1559
|
return `{ ${props.join("; ")} }`;
|
|
1559
1560
|
}
|
|
1560
|
-
if (schema.additionalProperties) {
|
|
1561
|
-
const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
|
|
1562
|
-
return `Record<string, ${valueType}>`;
|
|
1563
|
-
}
|
|
1561
|
+
if (schema.additionalProperties) return `Record<string, ${this.jsonSchemaTypeToTs(schema.additionalProperties)}>`;
|
|
1564
1562
|
return "Record<string, unknown>";
|
|
1565
1563
|
default: return "unknown";
|
|
1566
1564
|
}
|
|
@@ -1581,10 +1579,7 @@ var OpenApiTsGenerator = class {
|
|
|
1581
1579
|
}
|
|
1582
1580
|
const firstWithParams = infos.find((i) => i.input?.params);
|
|
1583
1581
|
let paramsEntry = "";
|
|
1584
|
-
if (firstWithParams?.input?.params) {
|
|
1585
|
-
const paramsName = await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`);
|
|
1586
|
-
paramsEntry = `\n parameters: {\n path: ${paramsName};\n };`;
|
|
1587
|
-
}
|
|
1582
|
+
if (firstWithParams?.input?.params) paramsEntry = `\n parameters: {\n path: ${await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`)};\n };`;
|
|
1588
1583
|
pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
|
|
1589
1584
|
}
|
|
1590
1585
|
return `export interface paths {\n${pathEntries.join("\n")}\n}`;
|
|
@@ -1623,8 +1618,7 @@ var OpenApiTsGenerator = class {
|
|
|
1623
1618
|
return acc;
|
|
1624
1619
|
}, {});
|
|
1625
1620
|
const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
|
|
1626
|
-
const
|
|
1627
|
-
const createApiSection = hasSecuritySchemes ? `
|
|
1621
|
+
const createApiSection = schemeNames.length > 0 ? `
|
|
1628
1622
|
// ============================================================
|
|
1629
1623
|
// API Client Factory
|
|
1630
1624
|
// ============================================================
|
|
@@ -1801,20 +1795,14 @@ ${createApiSection}
|
|
|
1801
1795
|
`;
|
|
1802
1796
|
}
|
|
1803
1797
|
};
|
|
1804
|
-
|
|
1805
|
-
//#endregion
|
|
1806
|
-
//#region src/workspace/client-generator.ts
|
|
1807
1798
|
/**
|
|
1808
|
-
*
|
|
1809
|
-
*
|
|
1810
|
-
*
|
|
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.
|
|
1811
1802
|
*/
|
|
1812
|
-
function
|
|
1813
|
-
|
|
1814
|
-
if (isPartitionedRoutes(routes)) return Array.isArray(routes.paths) ? routes.paths : [routes.paths];
|
|
1815
|
-
return Array.isArray(routes) ? routes : [routes];
|
|
1803
|
+
function unknownType(name) {
|
|
1804
|
+
return `export type ${name} = unknown;`;
|
|
1816
1805
|
}
|
|
1817
|
-
|
|
1818
1806
|
//#endregion
|
|
1819
1807
|
//#region src/openapi.ts
|
|
1820
1808
|
/**
|
|
@@ -1822,6 +1810,16 @@ function normalizeRoutes(routes) {
|
|
|
1822
1810
|
*/
|
|
1823
1811
|
const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
|
|
1824
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/${kebabCase(surfaceId)}.ts`;
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1825
1823
|
* Resolve OpenAPI config from GkmConfig
|
|
1826
1824
|
*/
|
|
1827
1825
|
function resolveOpenApiConfig(config) {
|
|
@@ -1840,33 +1838,65 @@ function resolveOpenApiConfig(config) {
|
|
|
1840
1838
|
};
|
|
1841
1839
|
}
|
|
1842
1840
|
/**
|
|
1843
|
-
*
|
|
1844
|
-
*
|
|
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.
|
|
1845
1846
|
*/
|
|
1846
|
-
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 = {}) {
|
|
1847
1862
|
const logger = options.silent ? { log: () => {} } : console;
|
|
1848
|
-
const openApiConfig = resolveOpenApiConfig(
|
|
1863
|
+
const openApiConfig = resolveOpenApiConfig({ openapi: options.openapi });
|
|
1849
1864
|
if (!openApiConfig.enabled) return null;
|
|
1850
|
-
|
|
1851
|
-
const loadedEndpoints = await endpointGenerator.load(config.routes, void 0, options.bustCache);
|
|
1852
|
-
if (loadedEndpoints.length === 0) {
|
|
1865
|
+
if (endpoints.length === 0) {
|
|
1853
1866
|
logger.log("No valid endpoints found for OpenAPI generation");
|
|
1854
1867
|
return null;
|
|
1855
1868
|
}
|
|
1856
|
-
const
|
|
1857
|
-
const
|
|
1858
|
-
|
|
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
|
+
}
|
|
1859
1881
|
const tsGenerator = new OpenApiTsGenerator();
|
|
1860
|
-
const
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1882
|
+
const written = [];
|
|
1883
|
+
for (const [surfaceId, surfaceEndpoints] of bySurface) {
|
|
1884
|
+
const relative = openApiPathFor(surfaceId);
|
|
1885
|
+
const outputPath = join(process.cwd(), relative);
|
|
1886
|
+
await mkdir(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 writeFile(outputPath, tsContent);
|
|
1893
|
+
written.push(relative);
|
|
1894
|
+
logger.log(`📄 OpenAPI client generated: ${relative} (${surfaceEndpoints.length} endpoints)`);
|
|
1895
|
+
}
|
|
1867
1896
|
return {
|
|
1868
|
-
outputPath,
|
|
1869
|
-
|
|
1897
|
+
outputPath: join(process.cwd(), written[0]),
|
|
1898
|
+
outputPaths: written.map((r) => join(process.cwd(), r)),
|
|
1899
|
+
endpointCount: endpoints.length
|
|
1870
1900
|
};
|
|
1871
1901
|
}
|
|
1872
1902
|
async function openapiCommand(options = {}) {
|
|
@@ -1876,12 +1906,12 @@ async function openapiCommand(options = {}) {
|
|
|
1876
1906
|
if (loadedConfig.type === "single") {
|
|
1877
1907
|
const config = loadedConfig.raw;
|
|
1878
1908
|
if (!config.openapi) config.openapi = { enabled: true };
|
|
1879
|
-
const result = await
|
|
1909
|
+
const result = await generateOpenApiFrom(config.constructs, { openapi: config.openapi });
|
|
1880
1910
|
if (result) logger.log(`Found ${result.endpointCount} endpoints`);
|
|
1881
1911
|
} else {
|
|
1882
1912
|
const { workspace } = loadedConfig;
|
|
1883
1913
|
const workspaceRoot = workspace.root;
|
|
1884
|
-
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));
|
|
1885
1915
|
if (backendApps.length === 0) {
|
|
1886
1916
|
logger.log("No backend apps with OpenAPI enabled found");
|
|
1887
1917
|
return;
|
|
@@ -1895,8 +1925,12 @@ async function openapiCommand(options = {}) {
|
|
|
1895
1925
|
return;
|
|
1896
1926
|
}
|
|
1897
1927
|
for (const [appName, app] of backendApps) {
|
|
1898
|
-
if (app.type !== "backend" || !app.routes) continue;
|
|
1899
1928
|
const appPath = join(workspaceRoot, app.path);
|
|
1929
|
+
if (resolve(appPath) === resolve(workspaceRoot)) {
|
|
1930
|
+
const result = await generateOpenApiForApp(workspaceRoot, appName, app, false);
|
|
1931
|
+
if (result) logger.log(`Found ${result.endpointCount} endpoints`);
|
|
1932
|
+
continue;
|
|
1933
|
+
}
|
|
1900
1934
|
await runOpenApiInSubprocess(appPath, appName);
|
|
1901
1935
|
}
|
|
1902
1936
|
}
|
|
@@ -1909,18 +1943,13 @@ async function openapiCommand(options = {}) {
|
|
|
1909
1943
|
* Runs in-process. The caller is responsible for ensuring `process.cwd()`
|
|
1910
1944
|
* is the app's directory so tsx loads the app's tsconfig path aliases.
|
|
1911
1945
|
*/
|
|
1912
|
-
async function generateOpenApiForApp(workspaceRoot, _appName, app) {
|
|
1913
|
-
if (app.type !== "backend"
|
|
1946
|
+
async function generateOpenApiForApp(workspaceRoot, _appName, app, silent = true) {
|
|
1947
|
+
if (app.type !== "backend") return null;
|
|
1914
1948
|
const appPath = join(workspaceRoot, app.path);
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
envParser: app.envParser || "",
|
|
1920
|
-
logger: app.logger || "",
|
|
1921
|
-
openapi: app.openapi
|
|
1922
|
-
};
|
|
1923
|
-
return generateOpenApi(gkmConfig, { silent: true });
|
|
1949
|
+
return generateOpenApiFrom([join(appPath, "**/*.ts")], {
|
|
1950
|
+
openapi: app.openapi ?? { enabled: true },
|
|
1951
|
+
silent
|
|
1952
|
+
});
|
|
1924
1953
|
}
|
|
1925
1954
|
/**
|
|
1926
1955
|
* Resolve the gkm bin path. Tests can override via `GKM_BIN_PATH` env var
|
|
@@ -1938,7 +1967,7 @@ function resolveGkmBinPath() {
|
|
|
1938
1967
|
*/
|
|
1939
1968
|
async function runOpenApiInSubprocess(appCwd, appName) {
|
|
1940
1969
|
const binPath = resolveGkmBinPath();
|
|
1941
|
-
await new Promise((resolve
|
|
1970
|
+
await new Promise((resolve, reject) => {
|
|
1942
1971
|
const child = spawn(process.execPath, [
|
|
1943
1972
|
binPath,
|
|
1944
1973
|
"openapi",
|
|
@@ -1951,12 +1980,12 @@ async function runOpenApiInSubprocess(appCwd, appName) {
|
|
|
1951
1980
|
});
|
|
1952
1981
|
child.on("error", reject);
|
|
1953
1982
|
child.on("close", (code) => {
|
|
1954
|
-
if (code === 0) resolve
|
|
1955
|
-
else reject(new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
|
|
1983
|
+
if (code === 0) resolve();
|
|
1984
|
+
else reject(/* @__PURE__ */ new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
|
|
1956
1985
|
});
|
|
1957
1986
|
});
|
|
1958
1987
|
}
|
|
1959
|
-
|
|
1960
1988
|
//#endregion
|
|
1961
|
-
export {
|
|
1962
|
-
|
|
1989
|
+
export { openapiCommand as a, runtimeFor as c, openApiPathFor as i, generateOpenApi as n, resolveOpenApiConfig as o, generateOpenApiFrom as r, EndpointGenerator as s, OPENAPI_OUTPUT_PATH as t };
|
|
1990
|
+
|
|
1991
|
+
//# sourceMappingURL=openapi-DfjbhrsM.mjs.map
|