@geekmidas/cli 10.0.0-alpha.4 → 10.0.0-alpha.40
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 +52 -74
- package/bin/adjacent-tsconfig.mjs +97 -0
- package/bin/gkm.mjs +7 -1
- package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
- package/dist/HostingerProvider-BZFGYYVA.cjs.map +1 -0
- package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-Bh6K7QYz.mjs} +20 -21
- package/dist/HostingerProvider-Bh6K7QYz.mjs.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/{openapi-CA0yJUTN.cjs → OpenApiTsGenerator-B4Kj_qNU.cjs} +142 -303
- package/dist/OpenApiTsGenerator-B4Kj_qNU.cjs.map +1 -0
- package/dist/{openapi-kkQbsRVj.mjs → OpenApiTsGenerator-CEh3EKN3.mjs} +113 -255
- package/dist/OpenApiTsGenerator-CEh3EKN3.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/aws-DkHdTV-p.cjs +61 -0
- package/dist/aws-DkHdTV-p.cjs.map +1 -0
- package/dist/aws-DojzQnLd.mjs +61 -0
- package/dist/aws-DojzQnLd.mjs.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-Be8Zg4Wd.mjs → bundler--fyybf1N.mjs} +19 -30
- package/dist/bundler--fyybf1N.mjs.map +1 -0
- package/dist/{bundler-BY1OmV1e.cjs → bundler-By6_sXiL.cjs} +20 -32
- package/dist/bundler-By6_sXiL.cjs.map +1 -0
- package/dist/{config-WRdsQYZK.mjs → config-5watB1D0.mjs} +142 -154
- package/dist/config-5watB1D0.mjs.map +1 -0
- package/dist/{config-C21ocYNd.cjs → config-CJ-PAb7M.cjs} +209 -210
- package/dist/config-CJ-PAb7M.cjs.map +1 -0
- package/dist/config.cjs +9 -6
- package/dist/config.d.cts +62 -33
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +62 -33
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -5
- 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 +3 -3
- 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-B0f_kuNN.cjs} +118 -66
- package/dist/discover-B0f_kuNN.cjs.map +1 -0
- package/dist/{discover-CAlFgYec.mjs → discover-BLhf7V_J.mjs} +67 -22
- package/dist/discover-BLhf7V_J.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/github-BAr8WGkR.cjs +213 -0
- package/dist/github-BAr8WGkR.cjs.map +1 -0
- package/dist/github-D5MthUlR.mjs +213 -0
- package/dist/github-D5MthUlR.mjs.map +1 -0
- package/dist/{index-DCtipn2h.d.cts → index-B3PeGOQp.d.cts} +4 -23
- package/dist/index-B3PeGOQp.d.cts.map +1 -0
- package/dist/{index-BThUzEIp.d.mts → index-BOyaGcCm.d.mts} +4 -23
- package/dist/index-BOyaGcCm.d.mts.map +1 -0
- package/dist/index.cjs +7071 -4519
- 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 +7117 -4586
- package/dist/index.mjs.map +1 -1
- package/dist/migrate-BVI3yqcE.mjs +736 -0
- package/dist/migrate-BVI3yqcE.mjs.map +1 -0
- package/dist/migrate-CFOUApUt.cjs +743 -0
- package/dist/migrate-CFOUApUt.cjs.map +1 -0
- package/dist/openapi.cjs +197 -8
- package/dist/openapi.cjs.map +1 -0
- 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 +191 -5
- package/dist/openapi.mjs.map +1 -0
- package/dist/ready-D8UXsP6q.mjs +516 -0
- package/dist/ready-D8UXsP6q.mjs.map +1 -0
- package/dist/ready-mcxamf73.cjs +563 -0
- package/dist/ready-mcxamf73.cjs.map +1 -0
- package/dist/reconcile/public.cjs +4 -4
- package/dist/reconcile/public.d.cts +27 -26
- package/dist/reconcile/public.d.cts.map +1 -1
- package/dist/reconcile/public.d.mts +27 -26
- package/dist/reconcile/public.d.mts.map +1 -1
- package/dist/reconcile/public.mjs +3 -4
- package/dist/{reconcile-CFs8C_1a.mjs → reconcile--I7V4Klj.mjs} +4 -7
- package/dist/reconcile--I7V4Klj.mjs.map +1 -0
- package/dist/{reconcile-D0pimNiy.cjs → reconcile-CuCQBa5-.cjs} +5 -8
- package/dist/reconcile-CuCQBa5-.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/storage-BzaUxmqe.mjs +124 -0
- package/dist/storage-BzaUxmqe.mjs.map +1 -0
- package/dist/storage-CSGoC3bK.cjs +152 -0
- package/dist/storage-CSGoC3bK.cjs.map +1 -0
- package/dist/store-DQgxT_WR.cjs +211 -0
- package/dist/store-DQgxT_WR.cjs.map +1 -0
- package/dist/store-DeGATCS-.mjs +182 -0
- package/dist/store-DeGATCS-.mjs.map +1 -0
- package/dist/types-0R124hrY.d.mts +6324 -0
- package/dist/types-0R124hrY.d.mts.map +1 -0
- package/dist/types-DfdYe31u.d.cts +6325 -0
- package/dist/types-DfdYe31u.d.cts.map +1 -0
- package/dist/vitest.cjs +65 -0
- package/dist/vitest.cjs.map +1 -0
- package/dist/vitest.d.cts +29 -0
- package/dist/vitest.d.cts.map +1 -0
- package/dist/vitest.d.mts +29 -0
- package/dist/vitest.d.mts.map +1 -0
- package/dist/vitest.mjs +65 -0
- package/dist/vitest.mjs.map +1 -0
- package/dist/workspace/index.cjs +3 -4
- 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/{credentials-G1JwBoXH.cjs → workspace-BIqeeqcR.cjs} +2248 -1809
- package/dist/workspace-BIqeeqcR.cjs.map +1 -0
- package/dist/{workspace-BFMrAKqI.mjs → workspace-DOmIhiau.mjs} +863 -952
- package/dist/workspace-DOmIhiau.mjs.map +1 -0
- package/dist/{credentials-BBIRJVp4.mjs → workspace-DwS1JK5u.mjs} +2114 -1706
- package/dist/workspace-DwS1JK5u.mjs.map +1 -0
- package/dist/{workspace-BcucjwvA.cjs → workspace-RYSYtHP7.cjs} +1032 -1098
- package/dist/workspace-RYSYtHP7.cjs.map +1 -0
- package/package.json +29 -20
- 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-C21ocYNd.cjs.map +0 -1
- package/dist/config-WRdsQYZK.mjs.map +0 -1
- package/dist/credentials-B5zRHdAl.mjs +0 -141
- package/dist/credentials-B5zRHdAl.mjs.map +0 -1
- package/dist/credentials-BBIRJVp4.mjs.map +0 -1
- package/dist/credentials-BapzjyV5.cjs +0 -195
- package/dist/credentials-BapzjyV5.cjs.map +0 -1
- package/dist/credentials-G1JwBoXH.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 +0 -111
- package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
- package/dist/fullstack-secrets-D1o9-G5l.mjs +0 -87
- package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
- package/dist/generator-CNzBw7g5.cjs +0 -289
- package/dist/generator-CNzBw7g5.cjs.map +0 -1
- package/dist/generator-VE2JrFlY.mjs +0 -253
- package/dist/generator-VE2JrFlY.mjs.map +0 -1
- package/dist/index-BThUzEIp.d.mts.map +0 -1
- package/dist/index-DCtipn2h.d.cts.map +0 -1
- package/dist/openapi-CA0yJUTN.cjs.map +0 -1
- package/dist/openapi-kkQbsRVj.mjs.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.map +0 -1
- package/dist/reconcile-D0pimNiy.cjs.map +0 -1
- package/dist/setup-B5_oHHUj.cjs +0 -11
- package/dist/setup-Cm2UnAdh.cjs +0 -473
- package/dist/setup-Cm2UnAdh.cjs.map +0 -1
- package/dist/setup-DXvRLTZN.mjs +0 -443
- package/dist/setup-DXvRLTZN.mjs.map +0 -1
- package/dist/setup-ZijS4qeC.mjs +0 -11
- package/dist/storage-BJmzYxt8.cjs +0 -363
- package/dist/storage-BJmzYxt8.cjs.map +0 -1
- package/dist/storage-BM9hGpgv.cjs +0 -7
- package/dist/storage-Bi24WfoW.mjs +0 -297
- 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-BhIl-COG.d.cts +0 -2184
- package/dist/types-BhIl-COG.d.cts.map +0 -1
- package/dist/types-C-arnQ1r.d.mts +0 -2184
- package/dist/types-C-arnQ1r.d.mts.map +0 -1
- package/dist/workspace-BFMrAKqI.mjs.map +0 -1
- package/dist/workspace-BcucjwvA.cjs.map +0 -1
- package/dist/workspace-DdJss8I6.cjs +0 -9
- package/dist/workspace-k4l3rsFh.mjs +0 -8
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { ConstructGenerator
|
|
2
|
-
import { loadWorkspaceConfig } from "./config-WRdsQYZK.mjs";
|
|
3
|
-
import { dirname, join, relative } from "node:path";
|
|
1
|
+
import { i as ConstructGenerator } from "./discover-BLhf7V_J.mjs";
|
|
4
2
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
5
|
-
import {
|
|
3
|
+
import { dirname, join, relative } from "node:path";
|
|
6
4
|
import { Endpoint } from "@geekmidas/constructs/endpoints";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
5
|
import { StandardSchemaJsonSchema, getRegisteredZodJsonSchemas, getSchemaMetadata } from "@geekmidas/schema/conversion";
|
|
9
|
-
|
|
10
6
|
//#region src/build/endpoint-analyzer.ts
|
|
11
7
|
/**
|
|
12
8
|
* Analyze an endpoint to extract its features
|
|
@@ -83,7 +79,6 @@ function summarizeAnalysis(analyses) {
|
|
|
83
79
|
byFeature
|
|
84
80
|
};
|
|
85
81
|
}
|
|
86
|
-
|
|
87
82
|
//#endregion
|
|
88
83
|
//#region src/build/handler-templates.ts
|
|
89
84
|
/**
|
|
@@ -105,8 +100,7 @@ function generateMinimalHandler(analysis) {
|
|
|
105
100
|
const { exportName, features } = analysis;
|
|
106
101
|
const method = analysis.method.toLowerCase();
|
|
107
102
|
const validators = generateValidators(exportName, features);
|
|
108
|
-
|
|
109
|
-
if (!hasValidators && !features.hasOutputValidation) return `
|
|
103
|
+
if (!(validators.length > 0) && !features.hasOutputValidation) return `
|
|
110
104
|
// Minimal handler: ${analysis.route} (${analysis.method})
|
|
111
105
|
app.${method}('${analysis.route}', async (c) => {
|
|
112
106
|
const result = await ${exportName}.handler(
|
|
@@ -304,8 +298,7 @@ ${factories.join("\n")}
|
|
|
304
298
|
*/
|
|
305
299
|
function generateMinimalEndpointFile(analysis, endpointImport) {
|
|
306
300
|
const { exportName, features } = analysis;
|
|
307
|
-
const
|
|
308
|
-
const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
301
|
+
const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
309
302
|
const handler = generateMinimalHandler(analysis);
|
|
310
303
|
return `/**
|
|
311
304
|
* Minimal endpoint: ${analysis.route} (${analysis.method})
|
|
@@ -330,8 +323,7 @@ ${handler}
|
|
|
330
323
|
*/
|
|
331
324
|
function generateStandardEndpointFile(analysis, endpointImport) {
|
|
332
325
|
const { exportName, features } = analysis;
|
|
333
|
-
const
|
|
334
|
-
const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
326
|
+
const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
335
327
|
const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
|
|
336
328
|
const handler = generateStandardHandler(analysis);
|
|
337
329
|
return `/**
|
|
@@ -423,7 +415,7 @@ export function setupFullEndpoints(
|
|
|
423
415
|
}
|
|
424
416
|
const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
|
|
425
417
|
if (tier === "minimal") {
|
|
426
|
-
const calls
|
|
418
|
+
const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
|
|
427
419
|
return `/**
|
|
428
420
|
* Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
|
|
429
421
|
* Near-raw-Hono performance
|
|
@@ -436,12 +428,12 @@ export function setupMinimalEndpoints(
|
|
|
436
428
|
app: Hono,
|
|
437
429
|
logger: Logger,
|
|
438
430
|
): void {
|
|
439
|
-
${calls
|
|
431
|
+
${calls}
|
|
440
432
|
}
|
|
441
433
|
`;
|
|
442
434
|
}
|
|
443
435
|
if (tier === "standard") {
|
|
444
|
-
const calls
|
|
436
|
+
const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
|
|
445
437
|
return `/**
|
|
446
438
|
* Standard-tier endpoint index (${tierEndpoints.length} endpoints)
|
|
447
439
|
* Auth and/or services enabled
|
|
@@ -456,7 +448,7 @@ export function setupStandardEndpoints(
|
|
|
456
448
|
serviceDiscovery: ServiceDiscovery<any, any>,
|
|
457
449
|
logger: Logger,
|
|
458
450
|
): void {
|
|
459
|
-
${calls
|
|
451
|
+
${calls}
|
|
460
452
|
}
|
|
461
453
|
`;
|
|
462
454
|
}
|
|
@@ -526,9 +518,7 @@ function generateEndpointFilesNested(analyses, endpointImports) {
|
|
|
526
518
|
case "standard":
|
|
527
519
|
files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
|
|
528
520
|
break;
|
|
529
|
-
case "full":
|
|
530
|
-
files[fileName] = generateFullEndpointFile(analysis, endpointImport);
|
|
531
|
-
break;
|
|
521
|
+
case "full": files[fileName] = generateFullEndpointFile(analysis, endpointImport);
|
|
532
522
|
}
|
|
533
523
|
}
|
|
534
524
|
return files;
|
|
@@ -585,7 +575,6 @@ export async function setupEndpoints(
|
|
|
585
575
|
}
|
|
586
576
|
`;
|
|
587
577
|
}
|
|
588
|
-
|
|
589
578
|
//#endregion
|
|
590
579
|
//#region src/generators/EndpointGenerator.ts
|
|
591
580
|
/**
|
|
@@ -602,24 +591,21 @@ export async function setupEndpoints(
|
|
|
602
591
|
*
|
|
603
592
|
* Falls back to the configured paths for an app that declares no surface.
|
|
604
593
|
*/
|
|
605
|
-
function runtimeFor(context, fromDir) {
|
|
606
|
-
const module = context.surface?.module;
|
|
594
|
+
function runtimeFor(context, fromDir, owner) {
|
|
595
|
+
const module = owner ? context.owners?.[owner] ?? context.surface?.module : context.surface?.module;
|
|
607
596
|
if (module) {
|
|
608
597
|
const specifier = importSpecifier(fromDir, module.specifier);
|
|
609
598
|
return {
|
|
610
599
|
imports: `import { ${module.exportName} as __surface } from '${specifier}';`,
|
|
611
600
|
bindings: [
|
|
612
|
-
"// What this
|
|
613
|
-
"// the entry imports the
|
|
601
|
+
"// What this construct was declared with. Objects, not module paths:",
|
|
602
|
+
"// the entry imports the owner, so there is nothing to print.",
|
|
614
603
|
"const envParser = __surface.envParser;",
|
|
615
604
|
"const logger = __surface.logger;"
|
|
616
605
|
].join("\n")
|
|
617
606
|
};
|
|
618
607
|
}
|
|
619
|
-
|
|
620
|
-
imports: [`import ${context.envParserImportPattern} from '${importSpecifier(fromDir, context.envParserPath)}';`, `import ${context.loggerImportPattern} from '${importSpecifier(fromDir, context.loggerPath)}';`].join("\n"),
|
|
621
|
-
bindings: ""
|
|
622
|
-
};
|
|
608
|
+
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
609
|
}
|
|
624
610
|
/** A relative specifier ESM will accept: always prefixed, never bare. */
|
|
625
611
|
function importSpecifier(fromDir, target) {
|
|
@@ -734,8 +720,7 @@ var EndpointGenerator = class extends ConstructGenerator {
|
|
|
734
720
|
async generateHandlerFile(outputDir, sourceFile, exportName, provider, _endpoint, context) {
|
|
735
721
|
const handlerFileName = `${exportName}.ts`;
|
|
736
722
|
const handlerPath = join(outputDir, handlerFileName);
|
|
737
|
-
const
|
|
738
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
723
|
+
const importPath = relative(dirname(handlerPath), sourceFile).replace(/\.ts$/, ".js");
|
|
739
724
|
let content;
|
|
740
725
|
switch (provider) {
|
|
741
726
|
case "aws-apigatewayv1":
|
|
@@ -753,12 +738,10 @@ var EndpointGenerator = class extends ConstructGenerator {
|
|
|
753
738
|
return handlerPath;
|
|
754
739
|
}
|
|
755
740
|
async generateEndpointsFile(outputDir, endpoints, context) {
|
|
756
|
-
const
|
|
757
|
-
const endpointsPath = join(outputDir, endpointsFileName);
|
|
741
|
+
const endpointsPath = join(outputDir, "endpoints.ts");
|
|
758
742
|
const importsByFile = /* @__PURE__ */ new Map();
|
|
759
743
|
for (const { path, key } of endpoints) {
|
|
760
|
-
const
|
|
761
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
744
|
+
const importPath = relative(dirname(endpointsPath), path.relative).replace(/\.ts$/, ".js");
|
|
762
745
|
if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
|
|
763
746
|
importsByFile.get(importPath)?.push(key);
|
|
764
747
|
}
|
|
@@ -773,7 +756,7 @@ import { ServiceDiscovery } from '@geekmidas/services';
|
|
|
773
756
|
import type { Hono } from 'hono';
|
|
774
757
|
${endpointImports}
|
|
775
758
|
|
|
776
|
-
export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any
|
|
759
|
+
export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any>[] = [
|
|
777
760
|
${allExportNames.join(",\n ")}
|
|
778
761
|
];
|
|
779
762
|
|
|
@@ -824,11 +807,9 @@ export async function setupEndpoints(
|
|
|
824
807
|
const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
|
|
825
808
|
const endpointImports = endpoints.map(({ key, path }) => {
|
|
826
809
|
const tierDir = join(endpointsDir, "standard");
|
|
827
|
-
const relativePath = relative(tierDir, path.relative);
|
|
828
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
829
810
|
return {
|
|
830
811
|
exportName: key,
|
|
831
|
-
importPath
|
|
812
|
+
importPath: relative(tierDir, path.relative).replace(/\.ts$/, ".js")
|
|
832
813
|
};
|
|
833
814
|
});
|
|
834
815
|
const summary = summarizeAnalysis(analyses);
|
|
@@ -850,8 +831,7 @@ export async function setupEndpoints(
|
|
|
850
831
|
}
|
|
851
832
|
async generateAppFile(outputDir, context) {
|
|
852
833
|
if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
|
|
853
|
-
const
|
|
854
|
-
const appPath = join(outputDir, appFileName);
|
|
834
|
+
const appPath = join(outputDir, "app.ts");
|
|
855
835
|
const runtime = runtimeFor(context, dirname(appPath));
|
|
856
836
|
const telescopeEnabled = context.telescope?.enabled;
|
|
857
837
|
const telescopeWebSocketEnabled = context.telescope?.websocket;
|
|
@@ -861,32 +841,36 @@ export async function setupEndpoints(
|
|
|
861
841
|
const studioFromDatabase = !usesExternalStudio && !!context.studio?.database;
|
|
862
842
|
const telescopeFromSurface = !!context.surface?.module && !usesExternalTelescope;
|
|
863
843
|
let telescopeImports = "";
|
|
864
|
-
if (telescopeEnabled)
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
844
|
+
if (telescopeEnabled) {
|
|
845
|
+
if (telescopeFromSurface) telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
|
|
846
|
+
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
847
|
+
else if (usesExternalTelescope) {
|
|
848
|
+
const relativeTelescopePath = relative(dirname(appPath), context.telescope?.telescopePath);
|
|
849
|
+
telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
|
|
868
850
|
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
869
|
-
|
|
851
|
+
} else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
|
|
870
852
|
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
853
|
+
}
|
|
871
854
|
let studioImports = "";
|
|
872
|
-
if (studioEnabled)
|
|
873
|
-
|
|
874
|
-
|
|
855
|
+
if (studioEnabled) {
|
|
856
|
+
if (usesExternalStudio) {
|
|
857
|
+
const relativeStudioPath = relative(dirname(appPath), context.studio?.studioPath);
|
|
858
|
+
studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
|
|
875
859
|
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
860
|
+
} else if (studioFromDatabase) {
|
|
861
|
+
const dbSpecifier = importSpecifier(dirname(appPath), context.studio.database.specifier);
|
|
862
|
+
studioImports = `import { snifferContext } from '@geekmidas/constructs';
|
|
879
863
|
import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
|
|
880
864
|
import { ${context.studio.database.exportName} as __studioDb } from '${dbSpecifier}';
|
|
881
865
|
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
882
|
-
|
|
866
|
+
} else studioImports = "";
|
|
867
|
+
}
|
|
883
868
|
const cors = corsFor(context.surface);
|
|
884
869
|
let hooksImports = "";
|
|
885
870
|
let beforeSetupCall = "";
|
|
886
871
|
let afterSetupCall = "";
|
|
887
872
|
if (context.hooks?.serverHooksPath) {
|
|
888
|
-
|
|
889
|
-
hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
|
|
873
|
+
hooksImports = `import * as serverHooks from '${relative(dirname(appPath), context.hooks.serverHooksPath)}';`;
|
|
890
874
|
beforeSetupCall = `
|
|
891
875
|
// Call beforeSetup hook if defined
|
|
892
876
|
if (typeof serverHooks.beforeSetup === 'function') {
|
|
@@ -932,7 +916,8 @@ import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
|
932
916
|
}
|
|
933
917
|
` : "";
|
|
934
918
|
let telescopeSetup = "";
|
|
935
|
-
if (telescopeEnabled)
|
|
919
|
+
if (telescopeEnabled) {
|
|
920
|
+
if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
|
|
936
921
|
${telescopeWebSocketSetupCode}
|
|
937
922
|
// Add telescope middleware (before endpoints to capture all requests)
|
|
938
923
|
honoApp.use('*', createMiddleware(telescope));
|
|
@@ -941,7 +926,7 @@ ${telescopeWebSocketSetupCode}
|
|
|
941
926
|
const telescopeUI = createUI(telescope);
|
|
942
927
|
honoApp.route('${context.telescope?.path}', telescopeUI);
|
|
943
928
|
`;
|
|
944
|
-
|
|
929
|
+
else telescopeSetup = `
|
|
945
930
|
// Setup Telescope for debugging/monitoring
|
|
946
931
|
const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
|
|
947
932
|
const telescope = new Telescope({
|
|
@@ -959,6 +944,7 @@ ${telescopeWebSocketSetupCode}
|
|
|
959
944
|
const telescopeUI = createUI(telescope);
|
|
960
945
|
honoApp.route('${context.telescope?.path}', telescopeUI);
|
|
961
946
|
`;
|
|
947
|
+
}
|
|
962
948
|
let studioSetup = "";
|
|
963
949
|
if (studioEnabled && studioFromDatabase) studioSetup = `
|
|
964
950
|
// Studio, built from the declared database. The client comes from the
|
|
@@ -992,6 +978,7 @@ import type { Hono as HonoType } from 'hono';
|
|
|
992
978
|
import { setupEndpoints } from './endpoints.js';
|
|
993
979
|
import { setupSubscribers } from './subscribers.js';
|
|
994
980
|
import { setupQueues } from './queues.js';
|
|
981
|
+
import { setupCrons } from './crons.js';
|
|
995
982
|
${runtime.imports}
|
|
996
983
|
${telescopeImports}
|
|
997
984
|
${studioImports}
|
|
@@ -1000,7 +987,16 @@ ${cors.imports}
|
|
|
1000
987
|
${context.storageDrivers?.imports ?? ""}
|
|
1001
988
|
|
|
1002
989
|
${runtime.bindings}
|
|
1003
|
-
${telescopeFromSurface ?
|
|
990
|
+
${telescopeEnabled && telescopeFromSurface ? `// The surface's own Telescope, or the one \`telescope\` config describes.
|
|
991
|
+
const telescope =
|
|
992
|
+
__surface.telescope ??
|
|
993
|
+
new Telescope({
|
|
994
|
+
enabled: true,
|
|
995
|
+
path: '${context.telescope?.path}',
|
|
996
|
+
ignorePatterns: ${JSON.stringify(context.telescope?.ignore)},
|
|
997
|
+
recordBody: ${context.telescope?.recordBody},
|
|
998
|
+
storage: new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} }),
|
|
999
|
+
});` : ""}
|
|
1004
1000
|
|
|
1005
1001
|
${context.storageDrivers?.setup ? `// Which storage drivers exist is the entry point's decision: the scheme in
|
|
1006
1002
|
// each injected URL picks one, so no construct and no application module names
|
|
@@ -1069,9 +1065,11 @@ ${afterSetupCall}
|
|
|
1069
1065
|
|
|
1070
1066
|
const port = options.port ?? 3000;
|
|
1071
1067
|
|
|
1072
|
-
//
|
|
1073
|
-
|
|
1068
|
+
// Mount pushed subscribers' routes and start polled ones. What comes
|
|
1069
|
+
// back subscribes the routes, once the server can answer them.
|
|
1070
|
+
const subscribeForPush = await setupSubscribers(honoApp, envParser, logger).catch((error) => {
|
|
1074
1071
|
logger.error({ error }, 'Failed to start subscribers');
|
|
1072
|
+
return async (_port: number) => {};
|
|
1075
1073
|
});
|
|
1076
1074
|
|
|
1077
1075
|
// Start queue workers in background (non-blocking, local development only)
|
|
@@ -1079,12 +1077,20 @@ ${afterSetupCall}
|
|
|
1079
1077
|
logger.error({ error }, 'Failed to start queue workers');
|
|
1080
1078
|
});
|
|
1081
1079
|
|
|
1080
|
+
// Schedule this app's crons. Caught like the others: a scheduler that
|
|
1081
|
+
// cannot start is not a reason for the HTTP server not to.
|
|
1082
|
+
await setupCrons(envParser, logger).catch((error) => {
|
|
1083
|
+
logger.error({ error }, 'Failed to schedule crons');
|
|
1084
|
+
});
|
|
1085
|
+
|
|
1082
1086
|
logger.info({ port }, 'Starting server');
|
|
1083
1087
|
|
|
1084
1088
|
// Start HTTP server using provided serve function
|
|
1085
1089
|
await options.serve(honoApp, port);
|
|
1086
1090
|
|
|
1087
1091
|
logger.info({ port }, 'Server started');
|
|
1092
|
+
|
|
1093
|
+
await subscribeForPush(port);
|
|
1088
1094
|
}
|
|
1089
1095
|
};
|
|
1090
1096
|
}
|
|
@@ -1147,10 +1153,8 @@ export const handler = ${exportName};
|
|
|
1147
1153
|
* No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
|
|
1148
1154
|
*/
|
|
1149
1155
|
async generateProductionAppFile(outputDir, context) {
|
|
1150
|
-
const
|
|
1151
|
-
const
|
|
1152
|
-
const relativeLoggerPath = relative(dirname(appPath), context.loggerPath);
|
|
1153
|
-
const relativeEnvParserPath = relative(dirname(appPath), context.envParserPath);
|
|
1156
|
+
const appPath = join(outputDir, "app.ts");
|
|
1157
|
+
const runtime = runtimeFor(context, dirname(appPath));
|
|
1154
1158
|
const production = context.production;
|
|
1155
1159
|
const healthCheckPath = production.healthCheck;
|
|
1156
1160
|
const enableGracefulShutdown = production.gracefulShutdown;
|
|
@@ -1161,8 +1165,7 @@ export const handler = ${exportName};
|
|
|
1161
1165
|
let beforeSetupCall = "";
|
|
1162
1166
|
let afterSetupCall = "";
|
|
1163
1167
|
if (context.hooks?.serverHooksPath) {
|
|
1164
|
-
|
|
1165
|
-
hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
|
|
1168
|
+
hooksImports = `import * as serverHooks from '${relative(dirname(appPath), context.hooks.serverHooksPath)}';`;
|
|
1166
1169
|
beforeSetupCall = `
|
|
1167
1170
|
// Call beforeSetup hook if defined
|
|
1168
1171
|
if (typeof serverHooks.beforeSetup === 'function') {
|
|
@@ -1177,18 +1180,27 @@ export const handler = ${exportName};
|
|
|
1177
1180
|
`;
|
|
1178
1181
|
}
|
|
1179
1182
|
const subscriberSetup = includeSubscribers ? `
|
|
1180
|
-
//
|
|
1181
|
-
|
|
1183
|
+
// Mount pushed subscribers' routes and start polled ones. What comes
|
|
1184
|
+
// back subscribes the routes, once the server can answer them.
|
|
1185
|
+
const subscribeForPush = await setupSubscribers(honoApp, envParser, logger).catch((error) => {
|
|
1182
1186
|
logger.error({ error }, 'Failed to start subscribers');
|
|
1187
|
+
return async (_port: number) => {};
|
|
1183
1188
|
});
|
|
1184
1189
|
|
|
1185
1190
|
// Start queue workers in background
|
|
1186
1191
|
await setupQueues(envParser, logger).catch((error) => {
|
|
1187
1192
|
logger.error({ error }, 'Failed to start queue workers');
|
|
1188
1193
|
});
|
|
1194
|
+
|
|
1195
|
+
// Schedule this app's crons. Caught like the others: a scheduler that
|
|
1196
|
+
// cannot start is not a reason for the HTTP server not to.
|
|
1197
|
+
await setupCrons(envParser, logger).catch((error) => {
|
|
1198
|
+
logger.error({ error }, 'Failed to schedule crons');
|
|
1199
|
+
});
|
|
1189
1200
|
` : "";
|
|
1190
1201
|
const subscriberImport = includeSubscribers ? `import { setupSubscribers } from './subscribers.js';
|
|
1191
|
-
import { setupQueues } from './queues.js'
|
|
1202
|
+
import { setupQueues } from './queues.js';
|
|
1203
|
+
import { setupCrons } from './crons.js';` : "";
|
|
1192
1204
|
const gracefulShutdownCode = enableGracefulShutdown ? `
|
|
1193
1205
|
// Graceful shutdown handling
|
|
1194
1206
|
let isShuttingDown = false;
|
|
@@ -1204,7 +1216,6 @@ import { setupQueues } from './queues.js';` : "";
|
|
|
1204
1216
|
process.on('SIGTERM', shutdown);
|
|
1205
1217
|
process.on('SIGINT', shutdown);
|
|
1206
1218
|
` : "";
|
|
1207
|
-
const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
|
|
1208
1219
|
const content = `/**
|
|
1209
1220
|
* Generated production server application
|
|
1210
1221
|
*
|
|
@@ -1216,10 +1227,10 @@ import { setupQueues } from './queues.js';` : "";
|
|
|
1216
1227
|
*/
|
|
1217
1228
|
import { Hono } from 'hono';
|
|
1218
1229
|
import type { Hono as HonoType } from 'hono';
|
|
1219
|
-
import { setupEndpoints } from '${
|
|
1230
|
+
import { setupEndpoints } from '${production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js"}';
|
|
1220
1231
|
${subscriberImport}
|
|
1221
|
-
|
|
1222
|
-
|
|
1232
|
+
${runtime.imports}
|
|
1233
|
+
${runtime.bindings}
|
|
1223
1234
|
${hooksImports}
|
|
1224
1235
|
${cors.imports}
|
|
1225
1236
|
${context.storageDrivers?.imports ?? ""}
|
|
@@ -1267,6 +1278,7 @@ ${gracefulShutdownCode}${subscriberSetup}
|
|
|
1267
1278
|
await options.serve(honoApp, port);
|
|
1268
1279
|
|
|
1269
1280
|
logger.info({ port }, 'Production server started');
|
|
1281
|
+
${includeSubscribers ? "\n await subscribeForPush(port);" : ""}
|
|
1270
1282
|
}
|
|
1271
1283
|
};
|
|
1272
1284
|
}
|
|
@@ -1283,7 +1295,7 @@ export default createApp;
|
|
|
1283
1295
|
*/
|
|
1284
1296
|
async generateProductionServerEntry(outputDir) {
|
|
1285
1297
|
const serverPath = join(outputDir, "server.ts");
|
|
1286
|
-
|
|
1298
|
+
await writeFile(serverPath, `#!/usr/bin/env node
|
|
1287
1299
|
/**
|
|
1288
1300
|
* Production server entry point
|
|
1289
1301
|
* Generated by 'gkm build --provider server --production'
|
|
@@ -1299,11 +1311,9 @@ await start({
|
|
|
1299
1311
|
port,
|
|
1300
1312
|
serve: (app, port) => { serve({ fetch: app.fetch, port }); },
|
|
1301
1313
|
});
|
|
1302
|
-
|
|
1303
|
-
await writeFile(serverPath, content);
|
|
1314
|
+
`);
|
|
1304
1315
|
}
|
|
1305
1316
|
};
|
|
1306
|
-
|
|
1307
1317
|
//#endregion
|
|
1308
1318
|
//#region src/generators/OpenApiTsGenerator.ts
|
|
1309
1319
|
/**
|
|
@@ -1458,7 +1468,7 @@ var OpenApiTsGenerator = class {
|
|
|
1458
1468
|
for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
|
|
1459
1469
|
const defName = this.pascalCase(rawName);
|
|
1460
1470
|
if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
|
|
1461
|
-
const { id: _id, $defs: _defs
|
|
1471
|
+
const { id: _id, $defs: _defs, ...rest } = rawSchema;
|
|
1462
1472
|
collectedDefs.set(defName, rest);
|
|
1463
1473
|
}
|
|
1464
1474
|
for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
|
|
@@ -1494,17 +1504,17 @@ var OpenApiTsGenerator = class {
|
|
|
1494
1504
|
async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
|
|
1495
1505
|
try {
|
|
1496
1506
|
const vendor = schema["~standard"]?.vendor;
|
|
1497
|
-
if (!vendor || !(vendor in StandardSchemaJsonSchema)) return
|
|
1507
|
+
if (!vendor || !(vendor in StandardSchemaJsonSchema)) return unknownType(name);
|
|
1498
1508
|
const toJsonSchema = StandardSchemaJsonSchema[vendor];
|
|
1499
1509
|
const jsonSchema = await toJsonSchema(schema);
|
|
1500
|
-
if (!jsonSchema) return
|
|
1510
|
+
if (!jsonSchema) return unknownType(name);
|
|
1501
1511
|
if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
|
|
1502
1512
|
for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
|
|
1503
|
-
const { id
|
|
1513
|
+
const { id, ...schemaWithoutId } = defSchema;
|
|
1504
1514
|
collectedDefs.set(defName, schemaWithoutId);
|
|
1505
1515
|
}
|
|
1506
1516
|
}
|
|
1507
|
-
const { $defs
|
|
1517
|
+
const { $defs, ...schemaWithoutDefs } = jsonSchema;
|
|
1508
1518
|
const ref = schemaWithoutDefs.$ref;
|
|
1509
1519
|
if (ref && Object.keys(schemaWithoutDefs).every((k) => k === "$ref" || k === "$schema")) {
|
|
1510
1520
|
const target = ref.split("/").pop();
|
|
@@ -1512,14 +1522,11 @@ var OpenApiTsGenerator = class {
|
|
|
1512
1522
|
}
|
|
1513
1523
|
return this.jsonSchemaToInterface(schemaWithoutDefs, name);
|
|
1514
1524
|
} catch {
|
|
1515
|
-
return
|
|
1525
|
+
return unknownType(name);
|
|
1516
1526
|
}
|
|
1517
1527
|
}
|
|
1518
1528
|
jsonSchemaToInterface(schema, name) {
|
|
1519
|
-
if (schema.type !== "object" || !schema.properties) {
|
|
1520
|
-
const typeStr = this.jsonSchemaTypeToTs(schema);
|
|
1521
|
-
return `export type ${name} = ${typeStr};`;
|
|
1522
|
-
}
|
|
1529
|
+
if (schema.type !== "object" || !schema.properties) return `export type ${name} = ${this.jsonSchemaTypeToTs(schema)};`;
|
|
1523
1530
|
const props = [];
|
|
1524
1531
|
const required = new Set(schema.required || []);
|
|
1525
1532
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
@@ -1532,13 +1539,15 @@ var OpenApiTsGenerator = class {
|
|
|
1532
1539
|
}
|
|
1533
1540
|
jsonSchemaTypeToTs(schema) {
|
|
1534
1541
|
if (!schema) return "unknown";
|
|
1535
|
-
if (schema.$ref)
|
|
1536
|
-
|
|
1537
|
-
return refName;
|
|
1538
|
-
}
|
|
1542
|
+
if (schema.$ref) return schema.$ref.split("/").pop() || "unknown";
|
|
1543
|
+
if (schema.const !== void 0) return typeof schema.const === "string" ? `'${schema.const}'` : String(schema.const);
|
|
1539
1544
|
if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
1540
1545
|
if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
1541
1546
|
if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
|
|
1547
|
+
if (Array.isArray(schema.type)) return schema.type.map((type) => this.jsonSchemaTypeToTs({
|
|
1548
|
+
...schema,
|
|
1549
|
+
type
|
|
1550
|
+
})).join(" | ");
|
|
1542
1551
|
switch (schema.type) {
|
|
1543
1552
|
case "string":
|
|
1544
1553
|
if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
|
|
@@ -1562,10 +1571,7 @@ var OpenApiTsGenerator = class {
|
|
|
1562
1571
|
}
|
|
1563
1572
|
return `{ ${props.join("; ")} }`;
|
|
1564
1573
|
}
|
|
1565
|
-
if (schema.additionalProperties) {
|
|
1566
|
-
const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
|
|
1567
|
-
return `Record<string, ${valueType}>`;
|
|
1568
|
-
}
|
|
1574
|
+
if (schema.additionalProperties) return `Record<string, ${this.jsonSchemaTypeToTs(schema.additionalProperties)}>`;
|
|
1569
1575
|
return "Record<string, unknown>";
|
|
1570
1576
|
default: return "unknown";
|
|
1571
1577
|
}
|
|
@@ -1586,10 +1592,7 @@ var OpenApiTsGenerator = class {
|
|
|
1586
1592
|
}
|
|
1587
1593
|
const firstWithParams = infos.find((i) => i.input?.params);
|
|
1588
1594
|
let paramsEntry = "";
|
|
1589
|
-
if (firstWithParams?.input?.params) {
|
|
1590
|
-
const paramsName = await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`);
|
|
1591
|
-
paramsEntry = `\n parameters: {\n path: ${paramsName};\n };`;
|
|
1592
|
-
}
|
|
1595
|
+
if (firstWithParams?.input?.params) paramsEntry = `\n parameters: {\n path: ${await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`)};\n };`;
|
|
1593
1596
|
pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
|
|
1594
1597
|
}
|
|
1595
1598
|
return `export interface paths {\n${pathEntries.join("\n")}\n}`;
|
|
@@ -1628,8 +1631,7 @@ var OpenApiTsGenerator = class {
|
|
|
1628
1631
|
return acc;
|
|
1629
1632
|
}, {});
|
|
1630
1633
|
const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
|
|
1631
|
-
const
|
|
1632
|
-
const createApiSection = hasSecuritySchemes ? `
|
|
1634
|
+
const createApiSection = schemeNames.length > 0 ? `
|
|
1633
1635
|
// ============================================================
|
|
1634
1636
|
// API Client Factory
|
|
1635
1637
|
// ============================================================
|
|
@@ -1653,6 +1655,8 @@ export interface CreateApiOptions {
|
|
|
1653
1655
|
queryClient?: QueryClient;
|
|
1654
1656
|
/** Optional request interceptor */
|
|
1655
1657
|
onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
|
|
1658
|
+
/** The \`fetch\` requests go out on — a test browser's, for one */
|
|
1659
|
+
fetch?: typeof fetch;
|
|
1656
1660
|
}
|
|
1657
1661
|
|
|
1658
1662
|
/**
|
|
@@ -1682,6 +1686,7 @@ export function createApi(options: CreateApiOptions) {
|
|
|
1682
1686
|
securitySchemes,
|
|
1683
1687
|
authStrategies: options.authStrategies,
|
|
1684
1688
|
onRequest: options.onRequest,
|
|
1689
|
+
...(options.fetch ? { fetch: options.fetch } : {}),
|
|
1685
1690
|
});
|
|
1686
1691
|
|
|
1687
1692
|
const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });
|
|
@@ -1806,162 +1811,15 @@ ${createApiSection}
|
|
|
1806
1811
|
`;
|
|
1807
1812
|
}
|
|
1808
1813
|
};
|
|
1809
|
-
|
|
1810
|
-
//#endregion
|
|
1811
|
-
//#region src/workspace/client-generator.ts
|
|
1812
1814
|
/**
|
|
1813
|
-
*
|
|
1814
|
-
*
|
|
1815
|
-
*
|
|
1815
|
+
* The declaration for a schema that cannot be converted — a vendor with no
|
|
1816
|
+
* converter, or one that fails. The paths interface names it either way, so
|
|
1817
|
+
* leaving it undeclared made the generated client fail to compile.
|
|
1816
1818
|
*/
|
|
1817
|
-
function
|
|
1818
|
-
|
|
1819
|
-
if (isPartitionedRoutes(routes)) return Array.isArray(routes.paths) ? routes.paths : [routes.paths];
|
|
1820
|
-
return Array.isArray(routes) ? routes : [routes];
|
|
1819
|
+
function unknownType(name) {
|
|
1820
|
+
return `export type ${name} = unknown;`;
|
|
1821
1821
|
}
|
|
1822
|
-
|
|
1823
1822
|
//#endregion
|
|
1824
|
-
|
|
1825
|
-
/**
|
|
1826
|
-
* Default output path for generated OpenAPI client (used for single-app configs)
|
|
1827
|
-
*/
|
|
1828
|
-
const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
|
|
1829
|
-
/**
|
|
1830
|
-
* Resolve OpenAPI config from GkmConfig
|
|
1831
|
-
*/
|
|
1832
|
-
function resolveOpenApiConfig(config) {
|
|
1833
|
-
if (config.openapi === false) return { enabled: false };
|
|
1834
|
-
if (config.openapi === true || config.openapi === void 0) return {
|
|
1835
|
-
enabled: true,
|
|
1836
|
-
title: "API Documentation",
|
|
1837
|
-
version: "1.0.0",
|
|
1838
|
-
description: "Auto-generated API documentation from endpoints"
|
|
1839
|
-
};
|
|
1840
|
-
return {
|
|
1841
|
-
enabled: config.openapi.enabled !== false,
|
|
1842
|
-
title: config.openapi.title || "API Documentation",
|
|
1843
|
-
version: config.openapi.version || "1.0.0",
|
|
1844
|
-
description: config.openapi.description || "Auto-generated API documentation from endpoints"
|
|
1845
|
-
};
|
|
1846
|
-
}
|
|
1847
|
-
/**
|
|
1848
|
-
* Generate OpenAPI spec from endpoints
|
|
1849
|
-
* @returns Object with output path and endpoint count, or null if disabled
|
|
1850
|
-
*/
|
|
1851
|
-
async function generateOpenApi(config, options = {}) {
|
|
1852
|
-
const logger = options.silent ? { log: () => {} } : console;
|
|
1853
|
-
const openApiConfig = resolveOpenApiConfig(config);
|
|
1854
|
-
if (!openApiConfig.enabled) return null;
|
|
1855
|
-
const endpointGenerator = new EndpointGenerator();
|
|
1856
|
-
const loadedEndpoints = await endpointGenerator.load(config.routes, void 0, options.bustCache);
|
|
1857
|
-
if (loadedEndpoints.length === 0) {
|
|
1858
|
-
logger.log("No valid endpoints found for OpenAPI generation");
|
|
1859
|
-
return null;
|
|
1860
|
-
}
|
|
1861
|
-
const endpoints = loadedEndpoints.map(({ construct }) => construct);
|
|
1862
|
-
const outputPath = join(process.cwd(), OPENAPI_OUTPUT_PATH);
|
|
1863
|
-
await mkdir(dirname(outputPath), { recursive: true });
|
|
1864
|
-
const tsGenerator = new OpenApiTsGenerator();
|
|
1865
|
-
const tsContent = await tsGenerator.generate(endpoints, {
|
|
1866
|
-
title: openApiConfig.title,
|
|
1867
|
-
version: openApiConfig.version,
|
|
1868
|
-
description: openApiConfig.description
|
|
1869
|
-
});
|
|
1870
|
-
await writeFile(outputPath, tsContent);
|
|
1871
|
-
logger.log(`📄 OpenAPI client generated: ${OPENAPI_OUTPUT_PATH}`);
|
|
1872
|
-
return {
|
|
1873
|
-
outputPath,
|
|
1874
|
-
endpointCount: loadedEndpoints.length
|
|
1875
|
-
};
|
|
1876
|
-
}
|
|
1877
|
-
async function openapiCommand(options = {}) {
|
|
1878
|
-
const logger = console;
|
|
1879
|
-
try {
|
|
1880
|
-
const loadedConfig = await loadWorkspaceConfig(options.cwd);
|
|
1881
|
-
if (loadedConfig.type === "single") {
|
|
1882
|
-
const config = loadedConfig.raw;
|
|
1883
|
-
if (!config.openapi) config.openapi = { enabled: true };
|
|
1884
|
-
const result = await generateOpenApi(config);
|
|
1885
|
-
if (result) logger.log(`Found ${result.endpointCount} endpoints`);
|
|
1886
|
-
} else {
|
|
1887
|
-
const { workspace } = loadedConfig;
|
|
1888
|
-
const workspaceRoot = workspace.root;
|
|
1889
|
-
const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend" && app.routes !== void 0 && app.openapi !== false && (typeof app.openapi !== "object" || app.openapi.enabled !== false));
|
|
1890
|
-
if (backendApps.length === 0) {
|
|
1891
|
-
logger.log("No backend apps with OpenAPI enabled found");
|
|
1892
|
-
return;
|
|
1893
|
-
}
|
|
1894
|
-
if (options.app) {
|
|
1895
|
-
const entry = backendApps.find(([name]) => name === options.app);
|
|
1896
|
-
if (!entry) throw new Error(`App "${options.app}" not found or has OpenAPI disabled`);
|
|
1897
|
-
const [appName, app] = entry;
|
|
1898
|
-
const result = await generateOpenApiForApp(workspaceRoot, appName, app);
|
|
1899
|
-
if (result) logger.log(`📄 [${appName}] Generated OpenAPI (${result.endpointCount} endpoints)`);
|
|
1900
|
-
return;
|
|
1901
|
-
}
|
|
1902
|
-
for (const [appName, app] of backendApps) {
|
|
1903
|
-
if (app.type !== "backend" || !app.routes) continue;
|
|
1904
|
-
const appPath = join(workspaceRoot, app.path);
|
|
1905
|
-
await runOpenApiInSubprocess(appPath, appName);
|
|
1906
|
-
}
|
|
1907
|
-
}
|
|
1908
|
-
} catch (error) {
|
|
1909
|
-
throw new Error(`OpenAPI generation failed: ${error.message}`);
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
/**
|
|
1913
|
-
* Generate OpenAPI for a single named app within a workspace.
|
|
1914
|
-
* Runs in-process. The caller is responsible for ensuring `process.cwd()`
|
|
1915
|
-
* is the app's directory so tsx loads the app's tsconfig path aliases.
|
|
1916
|
-
*/
|
|
1917
|
-
async function generateOpenApiForApp(workspaceRoot, _appName, app) {
|
|
1918
|
-
if (app.type !== "backend" || !app.routes) return null;
|
|
1919
|
-
const appPath = join(workspaceRoot, app.path);
|
|
1920
|
-
const routes = normalizeRoutes(app.routes);
|
|
1921
|
-
const routesGlob = routes.map((r) => join(appPath, r));
|
|
1922
|
-
const gkmConfig = {
|
|
1923
|
-
routes: routesGlob,
|
|
1924
|
-
envParser: app.envParser || "",
|
|
1925
|
-
logger: app.logger || "",
|
|
1926
|
-
openapi: app.openapi
|
|
1927
|
-
};
|
|
1928
|
-
return generateOpenApi(gkmConfig, { silent: true });
|
|
1929
|
-
}
|
|
1930
|
-
/**
|
|
1931
|
-
* Resolve the gkm bin path. Tests can override via `GKM_BIN_PATH` env var
|
|
1932
|
-
* to avoid depending on the built dist.
|
|
1933
|
-
*/
|
|
1934
|
-
function resolveGkmBinPath() {
|
|
1935
|
-
if (process.env.GKM_BIN_PATH) return process.env.GKM_BIN_PATH;
|
|
1936
|
-
return fileURLToPath(new URL("../bin/gkm.mjs", import.meta.url));
|
|
1937
|
-
}
|
|
1938
|
-
/**
|
|
1939
|
-
* Spawn a subprocess that runs `gkm openapi --app <name>` with `cwd` set to
|
|
1940
|
-
* the app's directory. Inherits `NODE_OPTIONS` (which already contains
|
|
1941
|
-
* `--import tsx`), so the child gets a fresh tsx instance whose tsconfig
|
|
1942
|
-
* discovery picks up the app's tsconfig path aliases.
|
|
1943
|
-
*/
|
|
1944
|
-
async function runOpenApiInSubprocess(appCwd, appName) {
|
|
1945
|
-
const binPath = resolveGkmBinPath();
|
|
1946
|
-
await new Promise((resolve$1, reject) => {
|
|
1947
|
-
const child = spawn(process.execPath, [
|
|
1948
|
-
binPath,
|
|
1949
|
-
"openapi",
|
|
1950
|
-
"--app",
|
|
1951
|
-
appName
|
|
1952
|
-
], {
|
|
1953
|
-
cwd: appCwd,
|
|
1954
|
-
stdio: "inherit",
|
|
1955
|
-
env: process.env
|
|
1956
|
-
});
|
|
1957
|
-
child.on("error", reject);
|
|
1958
|
-
child.on("close", (code) => {
|
|
1959
|
-
if (code === 0) resolve$1();
|
|
1960
|
-
else reject(new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
|
|
1961
|
-
});
|
|
1962
|
-
});
|
|
1963
|
-
}
|
|
1823
|
+
export { EndpointGenerator as n, runtimeFor as r, OpenApiTsGenerator as t };
|
|
1964
1824
|
|
|
1965
|
-
//#
|
|
1966
|
-
export { EndpointGenerator, OPENAPI_OUTPUT_PATH, generateOpenApi, normalizeRoutes, openapiCommand, resolveOpenApiConfig };
|
|
1967
|
-
//# sourceMappingURL=openapi-kkQbsRVj.mjs.map
|
|
1825
|
+
//# sourceMappingURL=OpenApiTsGenerator-CEh3EKN3.mjs.map
|