@geekmidas/cli 10.0.0-alpha.5 → 10.0.0-alpha.51
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 +196 -257
- package/bin/adjacent-tsconfig.mjs +97 -0
- package/bin/gkm.mjs +16 -2
- package/bin/owning-tsconfig-jsx-register.mjs +18 -0
- package/bin/owning-tsconfig-jsx.mjs +108 -0
- 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-GF6NAZAK.mjs} +20 -21
- package/dist/HostingerProvider-GF6NAZAK.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-BN0PIZxd.cjs} +157 -372
- package/dist/OpenApiTsGenerator-BN0PIZxd.cjs.map +1 -0
- package/dist/{openapi-kkQbsRVj.mjs → OpenApiTsGenerator-BzIGy8KE.mjs} +128 -324
- package/dist/OpenApiTsGenerator-BzIGy8KE.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/backends-B9V2XD2M.cjs +82 -0
- package/dist/backends-B9V2XD2M.cjs.map +1 -0
- package/dist/backends-CSuLl0YP.mjs +59 -0
- package/dist/backends-CSuLl0YP.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-C21ocYNd.cjs → config-Cvr5fCbn.cjs} +210 -210
- package/dist/config-Cvr5fCbn.cjs.map +1 -0
- package/dist/{config-WRdsQYZK.mjs → config-SOkDH-n1.mjs} +143 -154
- package/dist/config-SOkDH-n1.mjs.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-CAlFgYec.mjs → discover-Cf2jAcgF.mjs} +56 -63
- package/dist/discover-Cf2jAcgF.mjs.map +1 -0
- package/dist/{discover-DTmFeloL.cjs → discover-DXNviAh-.cjs} +86 -110
- package/dist/discover-DXNviAh-.cjs.map +1 -0
- package/dist/{emit-CiZS_5Ub.mjs → emit-C1e8qD08.mjs} +13 -26
- package/dist/emit-C1e8qD08.mjs.map +1 -0
- package/dist/{emit-CbcRolsa.cjs → emit-Dmc1nvdS.cjs} +31 -57
- package/dist/emit-Dmc1nvdS.cjs.map +1 -0
- package/dist/encryption-Bt8SHRI6.cjs +91 -0
- package/dist/encryption-Bt8SHRI6.cjs.map +1 -0
- package/dist/encryption-DRCXp-U4.mjs +90 -0
- package/dist/encryption-DRCXp-U4.mjs.map +1 -0
- package/dist/github-BGx4U61b.cjs +213 -0
- package/dist/github-BGx4U61b.cjs.map +1 -0
- package/dist/github-U_frvZgD.mjs +213 -0
- package/dist/github-U_frvZgD.mjs.map +1 -0
- package/dist/{index-CHB4tSzX.d.cts → index-DYh5TrsZ.d.mts} +4 -23
- package/dist/index-DYh5TrsZ.d.mts.map +1 -0
- package/dist/{index-BThUzEIp.d.mts → index-fU3qHy7c.d.cts} +4 -23
- package/dist/index-fU3qHy7c.d.cts.map +1 -0
- package/dist/index.cjs +9561 -7232
- 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 +9479 -7177
- package/dist/index.mjs.map +1 -1
- package/dist/migrate-dx4I0epp.cjs +743 -0
- package/dist/migrate-dx4I0epp.cjs.map +1 -0
- package/dist/migrate-soUQtku3.mjs +736 -0
- package/dist/migrate-soUQtku3.mjs.map +1 -0
- package/dist/openapi.cjs +198 -8
- package/dist/openapi.cjs.map +1 -0
- package/dist/openapi.d.cts +53 -15
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +53 -15
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +193 -5
- package/dist/openapi.mjs.map +1 -0
- package/dist/ready-WfT-eWlm.mjs +861 -0
- package/dist/ready-WfT-eWlm.mjs.map +1 -0
- package/dist/ready-lr2Fm-ep.cjs +932 -0
- package/dist/ready-lr2Fm-ep.cjs.map +1 -0
- package/dist/reconcile/public.cjs +3 -5
- package/dist/reconcile/public.d.cts +30 -33
- package/dist/reconcile/public.d.cts.map +1 -1
- package/dist/reconcile/public.d.mts +30 -33
- 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-CT0ymlBk.d.mts +6230 -0
- package/dist/types-CT0ymlBk.d.mts.map +1 -0
- package/dist/types-DYDT4FfE.d.cts +6231 -0
- package/dist/types-DYDT4FfE.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/{workspace-BcucjwvA.cjs → workspace-BcCiLzTO.cjs} +1040 -1120
- package/dist/workspace-BcCiLzTO.cjs.map +1 -0
- package/dist/{credentials-BBIRJVp4.mjs → workspace-Dp2zK_Nk.mjs} +2212 -1732
- package/dist/workspace-Dp2zK_Nk.mjs.map +1 -0
- package/dist/{credentials-G1JwBoXH.cjs → workspace-GBzR_hID.cjs} +2348 -1849
- package/dist/workspace-GBzR_hID.cjs.map +1 -0
- package/dist/{workspace-BFMrAKqI.mjs → workspace-bOsks1uk.mjs} +871 -974
- package/dist/workspace-bOsks1uk.mjs.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-CHB4tSzX.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-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-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,13 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const node_child_process = require_chunk.__toESM(require("node:child_process"));
|
|
7
|
-
const __geekmidas_constructs_endpoints = require_chunk.__toESM(require("@geekmidas/constructs/endpoints"));
|
|
8
|
-
const node_url = require_chunk.__toESM(require("node:url"));
|
|
9
|
-
const __geekmidas_schema_conversion = require_chunk.__toESM(require("@geekmidas/schema/conversion"));
|
|
10
|
-
|
|
1
|
+
const require_discover = require("./discover-DXNviAh-.cjs");
|
|
2
|
+
let node_fs_promises = require("node:fs/promises");
|
|
3
|
+
let node_path = require("node:path");
|
|
4
|
+
let _geekmidas_constructs_endpoints = require("@geekmidas/constructs/endpoints");
|
|
5
|
+
let _geekmidas_schema_conversion = require("@geekmidas/schema/conversion");
|
|
11
6
|
//#region src/build/endpoint-analyzer.ts
|
|
12
7
|
/**
|
|
13
8
|
* Analyze an endpoint to extract its features
|
|
@@ -84,7 +79,6 @@ function summarizeAnalysis(analyses) {
|
|
|
84
79
|
byFeature
|
|
85
80
|
};
|
|
86
81
|
}
|
|
87
|
-
|
|
88
82
|
//#endregion
|
|
89
83
|
//#region src/build/handler-templates.ts
|
|
90
84
|
/**
|
|
@@ -106,8 +100,7 @@ function generateMinimalHandler(analysis) {
|
|
|
106
100
|
const { exportName, features } = analysis;
|
|
107
101
|
const method = analysis.method.toLowerCase();
|
|
108
102
|
const validators = generateValidators(exportName, features);
|
|
109
|
-
|
|
110
|
-
if (!hasValidators && !features.hasOutputValidation) return `
|
|
103
|
+
if (!(validators.length > 0) && !features.hasOutputValidation) return `
|
|
111
104
|
// Minimal handler: ${analysis.route} (${analysis.method})
|
|
112
105
|
app.${method}('${analysis.route}', async (c) => {
|
|
113
106
|
const result = await ${exportName}.handler(
|
|
@@ -255,10 +248,10 @@ function generateValidatorsFile(analyses) {
|
|
|
255
248
|
const needsQuery = analyses.some((a) => a.features.hasQueryValidation);
|
|
256
249
|
const needsParams = analyses.some((a) => a.features.hasParamValidation);
|
|
257
250
|
if (!needsBody && !needsQuery && !needsParams) return `// No validators needed for this build\nexport {};\n`;
|
|
258
|
-
const exports
|
|
251
|
+
const exports = [];
|
|
259
252
|
const factories = [];
|
|
260
253
|
if (needsBody) {
|
|
261
|
-
exports
|
|
254
|
+
exports.push("validateBody");
|
|
262
255
|
factories.push(`
|
|
263
256
|
export const validateBody = (endpoint: any) =>
|
|
264
257
|
validator('json', async (value, c) => {
|
|
@@ -269,7 +262,7 @@ export const validateBody = (endpoint: any) =>
|
|
|
269
262
|
});`);
|
|
270
263
|
}
|
|
271
264
|
if (needsQuery) {
|
|
272
|
-
exports
|
|
265
|
+
exports.push("validateQuery");
|
|
273
266
|
factories.push(`
|
|
274
267
|
export const validateQuery = (endpoint: any) =>
|
|
275
268
|
validator('query', async (_, c) => {
|
|
@@ -281,7 +274,7 @@ export const validateQuery = (endpoint: any) =>
|
|
|
281
274
|
});`);
|
|
282
275
|
}
|
|
283
276
|
if (needsParams) {
|
|
284
|
-
exports
|
|
277
|
+
exports.push("validateParams");
|
|
285
278
|
factories.push(`
|
|
286
279
|
export const validateParams = (endpoint: any) =>
|
|
287
280
|
validator('param', async (params, c) => {
|
|
@@ -305,8 +298,7 @@ ${factories.join("\n")}
|
|
|
305
298
|
*/
|
|
306
299
|
function generateMinimalEndpointFile(analysis, endpointImport) {
|
|
307
300
|
const { exportName, features } = analysis;
|
|
308
|
-
const
|
|
309
|
-
const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
301
|
+
const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
310
302
|
const handler = generateMinimalHandler(analysis);
|
|
311
303
|
return `/**
|
|
312
304
|
* Minimal endpoint: ${analysis.route} (${analysis.method})
|
|
@@ -331,8 +323,7 @@ ${handler}
|
|
|
331
323
|
*/
|
|
332
324
|
function generateStandardEndpointFile(analysis, endpointImport) {
|
|
333
325
|
const { exportName, features } = analysis;
|
|
334
|
-
const
|
|
335
|
-
const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
326
|
+
const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
|
|
336
327
|
const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
|
|
337
328
|
const handler = generateStandardHandler(analysis);
|
|
338
329
|
return `/**
|
|
@@ -424,7 +415,7 @@ export function setupFullEndpoints(
|
|
|
424
415
|
}
|
|
425
416
|
const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
|
|
426
417
|
if (tier === "minimal") {
|
|
427
|
-
const calls
|
|
418
|
+
const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
|
|
428
419
|
return `/**
|
|
429
420
|
* Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
|
|
430
421
|
* Near-raw-Hono performance
|
|
@@ -437,12 +428,12 @@ export function setupMinimalEndpoints(
|
|
|
437
428
|
app: Hono,
|
|
438
429
|
logger: Logger,
|
|
439
430
|
): void {
|
|
440
|
-
${calls
|
|
431
|
+
${calls}
|
|
441
432
|
}
|
|
442
433
|
`;
|
|
443
434
|
}
|
|
444
435
|
if (tier === "standard") {
|
|
445
|
-
const calls
|
|
436
|
+
const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
|
|
446
437
|
return `/**
|
|
447
438
|
* Standard-tier endpoint index (${tierEndpoints.length} endpoints)
|
|
448
439
|
* Auth and/or services enabled
|
|
@@ -457,7 +448,7 @@ export function setupStandardEndpoints(
|
|
|
457
448
|
serviceDiscovery: ServiceDiscovery<any, any>,
|
|
458
449
|
logger: Logger,
|
|
459
450
|
): void {
|
|
460
|
-
${calls
|
|
451
|
+
${calls}
|
|
461
452
|
}
|
|
462
453
|
`;
|
|
463
454
|
}
|
|
@@ -527,9 +518,7 @@ function generateEndpointFilesNested(analyses, endpointImports) {
|
|
|
527
518
|
case "standard":
|
|
528
519
|
files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
|
|
529
520
|
break;
|
|
530
|
-
case "full":
|
|
531
|
-
files[fileName] = generateFullEndpointFile(analysis, endpointImport);
|
|
532
|
-
break;
|
|
521
|
+
case "full": files[fileName] = generateFullEndpointFile(analysis, endpointImport);
|
|
533
522
|
}
|
|
534
523
|
}
|
|
535
524
|
return files;
|
|
@@ -586,7 +575,6 @@ export async function setupEndpoints(
|
|
|
586
575
|
}
|
|
587
576
|
`;
|
|
588
577
|
}
|
|
589
|
-
|
|
590
578
|
//#endregion
|
|
591
579
|
//#region src/generators/EndpointGenerator.ts
|
|
592
580
|
/**
|
|
@@ -603,24 +591,21 @@ export async function setupEndpoints(
|
|
|
603
591
|
*
|
|
604
592
|
* Falls back to the configured paths for an app that declares no surface.
|
|
605
593
|
*/
|
|
606
|
-
function runtimeFor(context, fromDir) {
|
|
607
|
-
const module
|
|
608
|
-
if (module
|
|
609
|
-
const specifier = importSpecifier(fromDir, module
|
|
594
|
+
function runtimeFor(context, fromDir, owner) {
|
|
595
|
+
const module = owner ? context.owners?.[owner] ?? context.surface?.module : context.surface?.module;
|
|
596
|
+
if (module) {
|
|
597
|
+
const specifier = importSpecifier(fromDir, module.specifier);
|
|
610
598
|
return {
|
|
611
|
-
imports: `import { ${module
|
|
599
|
+
imports: `import { ${module.exportName} as __surface } from '${specifier}';`,
|
|
612
600
|
bindings: [
|
|
613
|
-
"// What this
|
|
614
|
-
"// 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.",
|
|
615
603
|
"const envParser = __surface.envParser;",
|
|
616
604
|
"const logger = __surface.logger;"
|
|
617
605
|
].join("\n")
|
|
618
606
|
};
|
|
619
607
|
}
|
|
620
|
-
|
|
621
|
-
imports: [`import ${context.envParserImportPattern} from '${importSpecifier(fromDir, context.envParserPath)}';`, `import ${context.loggerImportPattern} from '${importSpecifier(fromDir, context.loggerPath)}';`].join("\n"),
|
|
622
|
-
bindings: ""
|
|
623
|
-
};
|
|
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\`.`);
|
|
624
609
|
}
|
|
625
610
|
/** A relative specifier ESM will accept: always prefixed, never bare. */
|
|
626
611
|
function importSpecifier(fromDir, target) {
|
|
@@ -679,48 +664,35 @@ function corsFor(surface) {
|
|
|
679
664
|
}
|
|
680
665
|
var EndpointGenerator = class extends require_discover.ConstructGenerator {
|
|
681
666
|
isConstruct(value) {
|
|
682
|
-
return
|
|
667
|
+
return _geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
|
|
683
668
|
}
|
|
684
669
|
async build(context, constructs, outputDir, options) {
|
|
685
|
-
const
|
|
670
|
+
const target = options?.target ?? "aws";
|
|
671
|
+
const root = options?.root ?? process.cwd();
|
|
686
672
|
const enableOpenApi = options?.enableOpenApi || false;
|
|
687
673
|
const logger = console;
|
|
688
674
|
const routes = [];
|
|
689
675
|
if (constructs.length === 0) return routes;
|
|
690
|
-
if (
|
|
676
|
+
if (target === "server") {
|
|
691
677
|
await this.generateEndpointsFile(outputDir, constructs, context);
|
|
692
678
|
const appFile = await this.generateAppFile(outputDir, context);
|
|
693
679
|
routes.push({
|
|
694
680
|
path: "*",
|
|
695
681
|
method: "ALL",
|
|
696
|
-
handler: (0, node_path.relative)(
|
|
682
|
+
handler: (0, node_path.relative)(root, appFile),
|
|
697
683
|
authorizer: "none"
|
|
698
684
|
});
|
|
699
685
|
logger.log(`Generated server with ${constructs.length} endpoints${enableOpenApi ? " (OpenAPI enabled)" : ""}`);
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
path: construct._path,
|
|
707
|
-
method: construct.method,
|
|
708
|
-
handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
|
|
709
|
-
timeout: construct.timeout,
|
|
710
|
-
memorySize: construct.memorySize,
|
|
711
|
-
environment: await construct.getEnvironment({ markOptional: context.markOptional }),
|
|
712
|
-
dependencies: construct.constructs,
|
|
713
|
-
authorizer: construct.authorizer?.name ?? "none"
|
|
714
|
-
};
|
|
715
|
-
routes.push(routeInfo);
|
|
716
|
-
logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
|
|
717
|
-
}
|
|
718
|
-
} else for (const { key, construct, path } of constructs) {
|
|
719
|
-
const handlerFile = await this.generateHandlerFile(outputDir, path.relative, key, provider, construct, context);
|
|
686
|
+
return routes;
|
|
687
|
+
}
|
|
688
|
+
const routesDir = (0, node_path.join)(outputDir, "routes");
|
|
689
|
+
await (0, node_fs_promises.mkdir)(routesDir, { recursive: true });
|
|
690
|
+
for (const { key, construct, path } of constructs) {
|
|
691
|
+
const handlerFile = await this.generateHandlerFile(routesDir, path.relative, key, context);
|
|
720
692
|
const routeInfo = {
|
|
721
693
|
path: construct._path,
|
|
722
694
|
method: construct.method,
|
|
723
|
-
handler: (0, node_path.relative)(
|
|
695
|
+
handler: (0, node_path.relative)(root, handlerFile).replace(/\.ts$/, ".handler"),
|
|
724
696
|
timeout: construct.timeout,
|
|
725
697
|
memorySize: construct.memorySize,
|
|
726
698
|
environment: await construct.getEnvironment({ markOptional: context.markOptional }),
|
|
@@ -732,38 +704,21 @@ var EndpointGenerator = class extends require_discover.ConstructGenerator {
|
|
|
732
704
|
}
|
|
733
705
|
return routes;
|
|
734
706
|
}
|
|
735
|
-
async generateHandlerFile(outputDir, sourceFile, exportName,
|
|
736
|
-
const
|
|
737
|
-
const
|
|
738
|
-
|
|
739
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
740
|
-
let content;
|
|
741
|
-
switch (provider) {
|
|
742
|
-
case "aws-apigatewayv1":
|
|
743
|
-
content = this.generateAWSApiGatewayV1Handler(importPath, exportName, context.storageDrivers);
|
|
744
|
-
break;
|
|
745
|
-
case "aws-apigatewayv2":
|
|
746
|
-
content = this.generateAWSApiGatewayV2Handler(importPath, exportName, context.storageDrivers);
|
|
747
|
-
break;
|
|
748
|
-
case "server":
|
|
749
|
-
content = this.generateServerHandler(importPath, exportName);
|
|
750
|
-
break;
|
|
751
|
-
default: throw new Error(`Unsupported provider: ${provider}`);
|
|
752
|
-
}
|
|
753
|
-
await (0, node_fs_promises.writeFile)(handlerPath, content);
|
|
707
|
+
async generateHandlerFile(outputDir, sourceFile, exportName, context) {
|
|
708
|
+
const handlerPath = (0, node_path.join)(outputDir, `${exportName}.ts`);
|
|
709
|
+
const importPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile).replace(/\.ts$/, ".js");
|
|
710
|
+
await (0, node_fs_promises.writeFile)(handlerPath, this.generateAWSApiGatewayV2Handler(importPath, exportName, context.storageDrivers));
|
|
754
711
|
return handlerPath;
|
|
755
712
|
}
|
|
756
713
|
async generateEndpointsFile(outputDir, endpoints, context) {
|
|
757
|
-
const
|
|
758
|
-
const endpointsPath = (0, node_path.join)(outputDir, endpointsFileName);
|
|
714
|
+
const endpointsPath = (0, node_path.join)(outputDir, "endpoints.ts");
|
|
759
715
|
const importsByFile = /* @__PURE__ */ new Map();
|
|
760
716
|
for (const { path, key } of endpoints) {
|
|
761
|
-
const
|
|
762
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
717
|
+
const importPath = (0, node_path.relative)((0, node_path.dirname)(endpointsPath), path.relative).replace(/\.ts$/, ".js");
|
|
763
718
|
if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
|
|
764
719
|
importsByFile.get(importPath)?.push(key);
|
|
765
720
|
}
|
|
766
|
-
const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports
|
|
721
|
+
const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports]) => `import { ${exports.join(", ")} } from '${importPath}';`).join("\n");
|
|
767
722
|
const allExportNames = endpoints.map(({ key }) => key);
|
|
768
723
|
if (context.production?.enabled && context.production.optimizedHandlers) return this.generateOptimizedEndpointsFile(endpointsPath, endpoints, endpointImports, allExportNames);
|
|
769
724
|
const content = `import type { EnvironmentParser } from '@geekmidas/envkit';
|
|
@@ -774,7 +729,7 @@ import { ServiceDiscovery } from '@geekmidas/services';
|
|
|
774
729
|
import type { Hono } from 'hono';
|
|
775
730
|
${endpointImports}
|
|
776
731
|
|
|
777
|
-
export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any
|
|
732
|
+
export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any>[] = [
|
|
778
733
|
${allExportNames.join(",\n ")}
|
|
779
734
|
];
|
|
780
735
|
|
|
@@ -825,11 +780,9 @@ export async function setupEndpoints(
|
|
|
825
780
|
const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
|
|
826
781
|
const endpointImports = endpoints.map(({ key, path }) => {
|
|
827
782
|
const tierDir = (0, node_path.join)(endpointsDir, "standard");
|
|
828
|
-
const relativePath = (0, node_path.relative)(tierDir, path.relative);
|
|
829
|
-
const importPath = relativePath.replace(/\.ts$/, ".js");
|
|
830
783
|
return {
|
|
831
784
|
exportName: key,
|
|
832
|
-
importPath
|
|
785
|
+
importPath: (0, node_path.relative)(tierDir, path.relative).replace(/\.ts$/, ".js")
|
|
833
786
|
};
|
|
834
787
|
});
|
|
835
788
|
const summary = summarizeAnalysis(analyses);
|
|
@@ -851,8 +804,7 @@ export async function setupEndpoints(
|
|
|
851
804
|
}
|
|
852
805
|
async generateAppFile(outputDir, context) {
|
|
853
806
|
if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
|
|
854
|
-
const
|
|
855
|
-
const appPath = (0, node_path.join)(outputDir, appFileName);
|
|
807
|
+
const appPath = (0, node_path.join)(outputDir, "app.ts");
|
|
856
808
|
const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
|
|
857
809
|
const telescopeEnabled = context.telescope?.enabled;
|
|
858
810
|
const telescopeWebSocketEnabled = context.telescope?.websocket;
|
|
@@ -862,32 +814,36 @@ export async function setupEndpoints(
|
|
|
862
814
|
const studioFromDatabase = !usesExternalStudio && !!context.studio?.database;
|
|
863
815
|
const telescopeFromSurface = !!context.surface?.module && !usesExternalTelescope;
|
|
864
816
|
let telescopeImports = "";
|
|
865
|
-
if (telescopeEnabled)
|
|
866
|
-
|
|
867
|
-
const relativeTelescopePath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.telescope?.telescopePath);
|
|
868
|
-
telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
|
|
817
|
+
if (telescopeEnabled) {
|
|
818
|
+
if (telescopeFromSurface) telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
|
|
869
819
|
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
870
|
-
|
|
820
|
+
else if (usesExternalTelescope) {
|
|
821
|
+
const relativeTelescopePath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.telescope?.telescopePath);
|
|
822
|
+
telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
|
|
871
823
|
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
824
|
+
} else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
|
|
825
|
+
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
|
|
826
|
+
}
|
|
872
827
|
let studioImports = "";
|
|
873
|
-
if (studioEnabled)
|
|
874
|
-
|
|
875
|
-
|
|
828
|
+
if (studioEnabled) {
|
|
829
|
+
if (usesExternalStudio) {
|
|
830
|
+
const relativeStudioPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.studio?.studioPath);
|
|
831
|
+
studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
|
|
876
832
|
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
833
|
+
} else if (studioFromDatabase) {
|
|
834
|
+
const dbSpecifier = importSpecifier((0, node_path.dirname)(appPath), context.studio.database.specifier);
|
|
835
|
+
studioImports = `import { snifferContext } from '@geekmidas/constructs';
|
|
880
836
|
import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
|
|
881
837
|
import { ${context.studio.database.exportName} as __studioDb } from '${dbSpecifier}';
|
|
882
838
|
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
883
|
-
|
|
839
|
+
} else studioImports = "";
|
|
840
|
+
}
|
|
884
841
|
const cors = corsFor(context.surface);
|
|
885
842
|
let hooksImports = "";
|
|
886
843
|
let beforeSetupCall = "";
|
|
887
844
|
let afterSetupCall = "";
|
|
888
845
|
if (context.hooks?.serverHooksPath) {
|
|
889
|
-
|
|
890
|
-
hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
|
|
846
|
+
hooksImports = `import * as serverHooks from '${(0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath)}';`;
|
|
891
847
|
beforeSetupCall = `
|
|
892
848
|
// Call beforeSetup hook if defined
|
|
893
849
|
if (typeof serverHooks.beforeSetup === 'function') {
|
|
@@ -933,7 +889,8 @@ import { createStudioApp } from '@geekmidas/studio/server/hono';`;
|
|
|
933
889
|
}
|
|
934
890
|
` : "";
|
|
935
891
|
let telescopeSetup = "";
|
|
936
|
-
if (telescopeEnabled)
|
|
892
|
+
if (telescopeEnabled) {
|
|
893
|
+
if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
|
|
937
894
|
${telescopeWebSocketSetupCode}
|
|
938
895
|
// Add telescope middleware (before endpoints to capture all requests)
|
|
939
896
|
honoApp.use('*', createMiddleware(telescope));
|
|
@@ -942,7 +899,7 @@ ${telescopeWebSocketSetupCode}
|
|
|
942
899
|
const telescopeUI = createUI(telescope);
|
|
943
900
|
honoApp.route('${context.telescope?.path}', telescopeUI);
|
|
944
901
|
`;
|
|
945
|
-
|
|
902
|
+
else telescopeSetup = `
|
|
946
903
|
// Setup Telescope for debugging/monitoring
|
|
947
904
|
const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
|
|
948
905
|
const telescope = new Telescope({
|
|
@@ -960,6 +917,7 @@ ${telescopeWebSocketSetupCode}
|
|
|
960
917
|
const telescopeUI = createUI(telescope);
|
|
961
918
|
honoApp.route('${context.telescope?.path}', telescopeUI);
|
|
962
919
|
`;
|
|
920
|
+
}
|
|
963
921
|
let studioSetup = "";
|
|
964
922
|
if (studioEnabled && studioFromDatabase) studioSetup = `
|
|
965
923
|
// Studio, built from the declared database. The client comes from the
|
|
@@ -993,6 +951,7 @@ import type { Hono as HonoType } from 'hono';
|
|
|
993
951
|
import { setupEndpoints } from './endpoints.js';
|
|
994
952
|
import { setupSubscribers } from './subscribers.js';
|
|
995
953
|
import { setupQueues } from './queues.js';
|
|
954
|
+
import { setupCrons } from './crons.js';
|
|
996
955
|
${runtime.imports}
|
|
997
956
|
${telescopeImports}
|
|
998
957
|
${studioImports}
|
|
@@ -1001,7 +960,16 @@ ${cors.imports}
|
|
|
1001
960
|
${context.storageDrivers?.imports ?? ""}
|
|
1002
961
|
|
|
1003
962
|
${runtime.bindings}
|
|
1004
|
-
${telescopeFromSurface ?
|
|
963
|
+
${telescopeEnabled && telescopeFromSurface ? `// The surface's own Telescope, or the one \`telescope\` config describes.
|
|
964
|
+
const telescope =
|
|
965
|
+
__surface.telescope ??
|
|
966
|
+
new Telescope({
|
|
967
|
+
enabled: true,
|
|
968
|
+
path: '${context.telescope?.path}',
|
|
969
|
+
ignorePatterns: ${JSON.stringify(context.telescope?.ignore)},
|
|
970
|
+
recordBody: ${context.telescope?.recordBody},
|
|
971
|
+
storage: new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} }),
|
|
972
|
+
});` : ""}
|
|
1005
973
|
|
|
1006
974
|
${context.storageDrivers?.setup ? `// Which storage drivers exist is the entry point's decision: the scheme in
|
|
1007
975
|
// each injected URL picks one, so no construct and no application module names
|
|
@@ -1070,9 +1038,11 @@ ${afterSetupCall}
|
|
|
1070
1038
|
|
|
1071
1039
|
const port = options.port ?? 3000;
|
|
1072
1040
|
|
|
1073
|
-
//
|
|
1074
|
-
|
|
1041
|
+
// Mount pushed subscribers' routes and start polled ones. What comes
|
|
1042
|
+
// back subscribes the routes, once the server can answer them.
|
|
1043
|
+
const subscribeForPush = await setupSubscribers(honoApp, envParser, logger).catch((error) => {
|
|
1075
1044
|
logger.error({ error }, 'Failed to start subscribers');
|
|
1045
|
+
return async (_port: number) => {};
|
|
1076
1046
|
});
|
|
1077
1047
|
|
|
1078
1048
|
// Start queue workers in background (non-blocking, local development only)
|
|
@@ -1080,12 +1050,20 @@ ${afterSetupCall}
|
|
|
1080
1050
|
logger.error({ error }, 'Failed to start queue workers');
|
|
1081
1051
|
});
|
|
1082
1052
|
|
|
1053
|
+
// Schedule this app's crons. Caught like the others: a scheduler that
|
|
1054
|
+
// cannot start is not a reason for the HTTP server not to.
|
|
1055
|
+
await setupCrons(envParser, logger).catch((error) => {
|
|
1056
|
+
logger.error({ error }, 'Failed to schedule crons');
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1083
1059
|
logger.info({ port }, 'Starting server');
|
|
1084
1060
|
|
|
1085
1061
|
// Start HTTP server using provided serve function
|
|
1086
1062
|
await options.serve(honoApp, port);
|
|
1087
1063
|
|
|
1088
1064
|
logger.info({ port }, 'Server started');
|
|
1065
|
+
|
|
1066
|
+
await subscribeForPush(port);
|
|
1089
1067
|
}
|
|
1090
1068
|
};
|
|
1091
1069
|
}
|
|
@@ -1106,26 +1084,6 @@ export default createApp;
|
|
|
1106
1084
|
* object. Nothing has to be printed now, which is also why nothing has to be
|
|
1107
1085
|
* named in config.
|
|
1108
1086
|
*/
|
|
1109
|
-
generateAWSApiGatewayV1Handler(importPath, exportName, drivers) {
|
|
1110
|
-
return `import { AmazonApiGatewayV1Endpoint } from '@geekmidas/constructs/aws';
|
|
1111
|
-
import { ${exportName} } from '${importPath}';
|
|
1112
|
-
${drivers?.imports ?? ""}
|
|
1113
|
-
${drivers?.setup ? `\n// The handler registers the drivers its target needs.\n${drivers.setup}\n` : ""}
|
|
1114
|
-
const adapter = new AmazonApiGatewayV1Endpoint(${exportName});
|
|
1115
|
-
|
|
1116
|
-
export const handler = adapter.handler;
|
|
1117
|
-
`;
|
|
1118
|
-
}
|
|
1119
|
-
/**
|
|
1120
|
-
* One Lambda, one endpoint — and no environment import.
|
|
1121
|
-
*
|
|
1122
|
-
* The endpoint was built from its surface, so it carries the parser the
|
|
1123
|
-
* adaptor needs. This used to read
|
|
1124
|
-
* `import { envParser } from '../../config/env'`, a line the build wrote
|
|
1125
|
-
* because a generator can print a module specifier and cannot print an
|
|
1126
|
-
* object. Nothing has to be printed now, which is also why nothing has to be
|
|
1127
|
-
* named in config.
|
|
1128
|
-
*/
|
|
1129
1087
|
generateAWSApiGatewayV2Handler(importPath, exportName, drivers) {
|
|
1130
1088
|
return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';
|
|
1131
1089
|
import { ${exportName} } from '${importPath}';
|
|
@@ -1134,13 +1092,6 @@ ${drivers?.setup ? `\n// The handler registers the drivers its target needs.\n${
|
|
|
1134
1092
|
const adapter = new AmazonApiGatewayV2Endpoint(${exportName});
|
|
1135
1093
|
|
|
1136
1094
|
export const handler = adapter.handler;
|
|
1137
|
-
`;
|
|
1138
|
-
}
|
|
1139
|
-
generateServerHandler(importPath, exportName) {
|
|
1140
|
-
return `import { ${exportName} } from '${importPath}';
|
|
1141
|
-
|
|
1142
|
-
// Server handler - implement based on your server framework
|
|
1143
|
-
export const handler = ${exportName};
|
|
1144
1095
|
`;
|
|
1145
1096
|
}
|
|
1146
1097
|
/**
|
|
@@ -1148,10 +1099,8 @@ export const handler = ${exportName};
|
|
|
1148
1099
|
* No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
|
|
1149
1100
|
*/
|
|
1150
1101
|
async generateProductionAppFile(outputDir, context) {
|
|
1151
|
-
const
|
|
1152
|
-
const
|
|
1153
|
-
const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.loggerPath);
|
|
1154
|
-
const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.envParserPath);
|
|
1102
|
+
const appPath = (0, node_path.join)(outputDir, "app.ts");
|
|
1103
|
+
const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
|
|
1155
1104
|
const production = context.production;
|
|
1156
1105
|
const healthCheckPath = production.healthCheck;
|
|
1157
1106
|
const enableGracefulShutdown = production.gracefulShutdown;
|
|
@@ -1162,8 +1111,7 @@ export const handler = ${exportName};
|
|
|
1162
1111
|
let beforeSetupCall = "";
|
|
1163
1112
|
let afterSetupCall = "";
|
|
1164
1113
|
if (context.hooks?.serverHooksPath) {
|
|
1165
|
-
|
|
1166
|
-
hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
|
|
1114
|
+
hooksImports = `import * as serverHooks from '${(0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath)}';`;
|
|
1167
1115
|
beforeSetupCall = `
|
|
1168
1116
|
// Call beforeSetup hook if defined
|
|
1169
1117
|
if (typeof serverHooks.beforeSetup === 'function') {
|
|
@@ -1178,18 +1126,27 @@ export const handler = ${exportName};
|
|
|
1178
1126
|
`;
|
|
1179
1127
|
}
|
|
1180
1128
|
const subscriberSetup = includeSubscribers ? `
|
|
1181
|
-
//
|
|
1182
|
-
|
|
1129
|
+
// Mount pushed subscribers' routes and start polled ones. What comes
|
|
1130
|
+
// back subscribes the routes, once the server can answer them.
|
|
1131
|
+
const subscribeForPush = await setupSubscribers(honoApp, envParser, logger).catch((error) => {
|
|
1183
1132
|
logger.error({ error }, 'Failed to start subscribers');
|
|
1133
|
+
return async (_port: number) => {};
|
|
1184
1134
|
});
|
|
1185
1135
|
|
|
1186
1136
|
// Start queue workers in background
|
|
1187
1137
|
await setupQueues(envParser, logger).catch((error) => {
|
|
1188
1138
|
logger.error({ error }, 'Failed to start queue workers');
|
|
1189
1139
|
});
|
|
1140
|
+
|
|
1141
|
+
// Schedule this app's crons. Caught like the others: a scheduler that
|
|
1142
|
+
// cannot start is not a reason for the HTTP server not to.
|
|
1143
|
+
await setupCrons(envParser, logger).catch((error) => {
|
|
1144
|
+
logger.error({ error }, 'Failed to schedule crons');
|
|
1145
|
+
});
|
|
1190
1146
|
` : "";
|
|
1191
1147
|
const subscriberImport = includeSubscribers ? `import { setupSubscribers } from './subscribers.js';
|
|
1192
|
-
import { setupQueues } from './queues.js'
|
|
1148
|
+
import { setupQueues } from './queues.js';
|
|
1149
|
+
import { setupCrons } from './crons.js';` : "";
|
|
1193
1150
|
const gracefulShutdownCode = enableGracefulShutdown ? `
|
|
1194
1151
|
// Graceful shutdown handling
|
|
1195
1152
|
let isShuttingDown = false;
|
|
@@ -1205,7 +1162,6 @@ import { setupQueues } from './queues.js';` : "";
|
|
|
1205
1162
|
process.on('SIGTERM', shutdown);
|
|
1206
1163
|
process.on('SIGINT', shutdown);
|
|
1207
1164
|
` : "";
|
|
1208
|
-
const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
|
|
1209
1165
|
const content = `/**
|
|
1210
1166
|
* Generated production server application
|
|
1211
1167
|
*
|
|
@@ -1217,10 +1173,10 @@ import { setupQueues } from './queues.js';` : "";
|
|
|
1217
1173
|
*/
|
|
1218
1174
|
import { Hono } from 'hono';
|
|
1219
1175
|
import type { Hono as HonoType } from 'hono';
|
|
1220
|
-
import { setupEndpoints } from '${
|
|
1176
|
+
import { setupEndpoints } from '${production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js"}';
|
|
1221
1177
|
${subscriberImport}
|
|
1222
|
-
|
|
1223
|
-
|
|
1178
|
+
${runtime.imports}
|
|
1179
|
+
${runtime.bindings}
|
|
1224
1180
|
${hooksImports}
|
|
1225
1181
|
${cors.imports}
|
|
1226
1182
|
${context.storageDrivers?.imports ?? ""}
|
|
@@ -1268,6 +1224,7 @@ ${gracefulShutdownCode}${subscriberSetup}
|
|
|
1268
1224
|
await options.serve(honoApp, port);
|
|
1269
1225
|
|
|
1270
1226
|
logger.info({ port }, 'Production server started');
|
|
1227
|
+
${includeSubscribers ? "\n await subscribeForPush(port);" : ""}
|
|
1271
1228
|
}
|
|
1272
1229
|
};
|
|
1273
1230
|
}
|
|
@@ -1284,10 +1241,10 @@ export default createApp;
|
|
|
1284
1241
|
*/
|
|
1285
1242
|
async generateProductionServerEntry(outputDir) {
|
|
1286
1243
|
const serverPath = (0, node_path.join)(outputDir, "server.ts");
|
|
1287
|
-
|
|
1244
|
+
await (0, node_fs_promises.writeFile)(serverPath, `#!/usr/bin/env node
|
|
1288
1245
|
/**
|
|
1289
1246
|
* Production server entry point
|
|
1290
|
-
* Generated by 'gkm build --
|
|
1247
|
+
* Generated by 'gkm build --production'
|
|
1291
1248
|
*/
|
|
1292
1249
|
import { serve } from '@hono/node-server';
|
|
1293
1250
|
import { createApp } from './app.js';
|
|
@@ -1300,11 +1257,9 @@ await start({
|
|
|
1300
1257
|
port,
|
|
1301
1258
|
serve: (app, port) => { serve({ fetch: app.fetch, port }); },
|
|
1302
1259
|
});
|
|
1303
|
-
|
|
1304
|
-
await (0, node_fs_promises.writeFile)(serverPath, content);
|
|
1260
|
+
`);
|
|
1305
1261
|
}
|
|
1306
1262
|
};
|
|
1307
|
-
|
|
1308
1263
|
//#endregion
|
|
1309
1264
|
//#region src/generators/OpenApiTsGenerator.ts
|
|
1310
1265
|
/**
|
|
@@ -1455,11 +1410,11 @@ var OpenApiTsGenerator = class {
|
|
|
1455
1410
|
}
|
|
1456
1411
|
}
|
|
1457
1412
|
}
|
|
1458
|
-
const registrySchemas = await (0,
|
|
1413
|
+
const registrySchemas = await (0, _geekmidas_schema_conversion.getRegisteredZodJsonSchemas)();
|
|
1459
1414
|
for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
|
|
1460
1415
|
const defName = this.pascalCase(rawName);
|
|
1461
1416
|
if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
|
|
1462
|
-
const { id: _id, $defs: _defs
|
|
1417
|
+
const { id: _id, $defs: _defs, ...rest } = rawSchema;
|
|
1463
1418
|
collectedDefs.set(defName, rest);
|
|
1464
1419
|
}
|
|
1465
1420
|
for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
|
|
@@ -1475,7 +1430,7 @@ var OpenApiTsGenerator = class {
|
|
|
1475
1430
|
*/
|
|
1476
1431
|
async getSchemaName(schema, defaultName) {
|
|
1477
1432
|
try {
|
|
1478
|
-
const metadata = await (0,
|
|
1433
|
+
const metadata = await (0, _geekmidas_schema_conversion.getSchemaMetadata)(schema);
|
|
1479
1434
|
if (metadata?.id) return this.pascalCase(metadata.id);
|
|
1480
1435
|
} catch {}
|
|
1481
1436
|
return defaultName;
|
|
@@ -1495,17 +1450,17 @@ var OpenApiTsGenerator = class {
|
|
|
1495
1450
|
async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
|
|
1496
1451
|
try {
|
|
1497
1452
|
const vendor = schema["~standard"]?.vendor;
|
|
1498
|
-
if (!vendor || !(vendor in
|
|
1499
|
-
const toJsonSchema =
|
|
1453
|
+
if (!vendor || !(vendor in _geekmidas_schema_conversion.StandardSchemaJsonSchema)) return unknownType(name);
|
|
1454
|
+
const toJsonSchema = _geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
|
|
1500
1455
|
const jsonSchema = await toJsonSchema(schema);
|
|
1501
|
-
if (!jsonSchema) return
|
|
1456
|
+
if (!jsonSchema) return unknownType(name);
|
|
1502
1457
|
if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
|
|
1503
1458
|
for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
|
|
1504
|
-
const { id
|
|
1459
|
+
const { id, ...schemaWithoutId } = defSchema;
|
|
1505
1460
|
collectedDefs.set(defName, schemaWithoutId);
|
|
1506
1461
|
}
|
|
1507
1462
|
}
|
|
1508
|
-
const { $defs
|
|
1463
|
+
const { $defs, ...schemaWithoutDefs } = jsonSchema;
|
|
1509
1464
|
const ref = schemaWithoutDefs.$ref;
|
|
1510
1465
|
if (ref && Object.keys(schemaWithoutDefs).every((k) => k === "$ref" || k === "$schema")) {
|
|
1511
1466
|
const target = ref.split("/").pop();
|
|
@@ -1513,14 +1468,11 @@ var OpenApiTsGenerator = class {
|
|
|
1513
1468
|
}
|
|
1514
1469
|
return this.jsonSchemaToInterface(schemaWithoutDefs, name);
|
|
1515
1470
|
} catch {
|
|
1516
|
-
return
|
|
1471
|
+
return unknownType(name);
|
|
1517
1472
|
}
|
|
1518
1473
|
}
|
|
1519
1474
|
jsonSchemaToInterface(schema, name) {
|
|
1520
|
-
if (schema.type !== "object" || !schema.properties) {
|
|
1521
|
-
const typeStr = this.jsonSchemaTypeToTs(schema);
|
|
1522
|
-
return `export type ${name} = ${typeStr};`;
|
|
1523
|
-
}
|
|
1475
|
+
if (schema.type !== "object" || !schema.properties) return `export type ${name} = ${this.jsonSchemaTypeToTs(schema)};`;
|
|
1524
1476
|
const props = [];
|
|
1525
1477
|
const required = new Set(schema.required || []);
|
|
1526
1478
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
@@ -1533,13 +1485,15 @@ var OpenApiTsGenerator = class {
|
|
|
1533
1485
|
}
|
|
1534
1486
|
jsonSchemaTypeToTs(schema) {
|
|
1535
1487
|
if (!schema) return "unknown";
|
|
1536
|
-
if (schema.$ref)
|
|
1537
|
-
|
|
1538
|
-
return refName;
|
|
1539
|
-
}
|
|
1488
|
+
if (schema.$ref) return schema.$ref.split("/").pop() || "unknown";
|
|
1489
|
+
if (schema.const !== void 0) return typeof schema.const === "string" ? `'${schema.const}'` : String(schema.const);
|
|
1540
1490
|
if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
1541
1491
|
if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
1542
1492
|
if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
|
|
1493
|
+
if (Array.isArray(schema.type)) return schema.type.map((type) => this.jsonSchemaTypeToTs({
|
|
1494
|
+
...schema,
|
|
1495
|
+
type
|
|
1496
|
+
})).join(" | ");
|
|
1543
1497
|
switch (schema.type) {
|
|
1544
1498
|
case "string":
|
|
1545
1499
|
if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
|
|
@@ -1563,10 +1517,7 @@ var OpenApiTsGenerator = class {
|
|
|
1563
1517
|
}
|
|
1564
1518
|
return `{ ${props.join("; ")} }`;
|
|
1565
1519
|
}
|
|
1566
|
-
if (schema.additionalProperties) {
|
|
1567
|
-
const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
|
|
1568
|
-
return `Record<string, ${valueType}>`;
|
|
1569
|
-
}
|
|
1520
|
+
if (schema.additionalProperties) return `Record<string, ${this.jsonSchemaTypeToTs(schema.additionalProperties)}>`;
|
|
1570
1521
|
return "Record<string, unknown>";
|
|
1571
1522
|
default: return "unknown";
|
|
1572
1523
|
}
|
|
@@ -1587,10 +1538,7 @@ var OpenApiTsGenerator = class {
|
|
|
1587
1538
|
}
|
|
1588
1539
|
const firstWithParams = infos.find((i) => i.input?.params);
|
|
1589
1540
|
let paramsEntry = "";
|
|
1590
|
-
if (firstWithParams?.input?.params) {
|
|
1591
|
-
const paramsName = await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`);
|
|
1592
|
-
paramsEntry = `\n parameters: {\n path: ${paramsName};\n };`;
|
|
1593
|
-
}
|
|
1541
|
+
if (firstWithParams?.input?.params) paramsEntry = `\n parameters: {\n path: ${await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`)};\n };`;
|
|
1594
1542
|
pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
|
|
1595
1543
|
}
|
|
1596
1544
|
return `export interface paths {\n${pathEntries.join("\n")}\n}`;
|
|
@@ -1629,8 +1577,7 @@ var OpenApiTsGenerator = class {
|
|
|
1629
1577
|
return acc;
|
|
1630
1578
|
}, {});
|
|
1631
1579
|
const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
|
|
1632
|
-
const
|
|
1633
|
-
const createApiSection = hasSecuritySchemes ? `
|
|
1580
|
+
const createApiSection = schemeNames.length > 0 ? `
|
|
1634
1581
|
// ============================================================
|
|
1635
1582
|
// API Client Factory
|
|
1636
1583
|
// ============================================================
|
|
@@ -1654,6 +1601,8 @@ export interface CreateApiOptions {
|
|
|
1654
1601
|
queryClient?: QueryClient;
|
|
1655
1602
|
/** Optional request interceptor */
|
|
1656
1603
|
onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
|
|
1604
|
+
/** The \`fetch\` requests go out on — a test browser's, for one */
|
|
1605
|
+
fetch?: typeof fetch;
|
|
1657
1606
|
}
|
|
1658
1607
|
|
|
1659
1608
|
/**
|
|
@@ -1683,6 +1632,7 @@ export function createApi(options: CreateApiOptions) {
|
|
|
1683
1632
|
securitySchemes,
|
|
1684
1633
|
authStrategies: options.authStrategies,
|
|
1685
1634
|
onRequest: options.onRequest,
|
|
1635
|
+
...(options.fetch ? { fetch: options.fetch } : {}),
|
|
1686
1636
|
});
|
|
1687
1637
|
|
|
1688
1638
|
const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });
|
|
@@ -1807,197 +1757,32 @@ ${createApiSection}
|
|
|
1807
1757
|
`;
|
|
1808
1758
|
}
|
|
1809
1759
|
};
|
|
1810
|
-
|
|
1811
|
-
//#endregion
|
|
1812
|
-
//#region src/workspace/client-generator.ts
|
|
1813
1760
|
/**
|
|
1814
|
-
*
|
|
1815
|
-
*
|
|
1816
|
-
*
|
|
1761
|
+
* The declaration for a schema that cannot be converted — a vendor with no
|
|
1762
|
+
* converter, or one that fails. The paths interface names it either way, so
|
|
1763
|
+
* leaving it undeclared made the generated client fail to compile.
|
|
1817
1764
|
*/
|
|
1818
|
-
function
|
|
1819
|
-
|
|
1820
|
-
if (require_discover.isPartitionedRoutes(routes)) return Array.isArray(routes.paths) ? routes.paths : [routes.paths];
|
|
1821
|
-
return Array.isArray(routes) ? routes : [routes];
|
|
1765
|
+
function unknownType(name) {
|
|
1766
|
+
return `export type ${name} = unknown;`;
|
|
1822
1767
|
}
|
|
1823
|
-
|
|
1824
1768
|
//#endregion
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
|
|
1830
|
-
/**
|
|
1831
|
-
* Resolve OpenAPI config from GkmConfig
|
|
1832
|
-
*/
|
|
1833
|
-
function resolveOpenApiConfig(config) {
|
|
1834
|
-
if (config.openapi === false) return { enabled: false };
|
|
1835
|
-
if (config.openapi === true || config.openapi === void 0) return {
|
|
1836
|
-
enabled: true,
|
|
1837
|
-
title: "API Documentation",
|
|
1838
|
-
version: "1.0.0",
|
|
1839
|
-
description: "Auto-generated API documentation from endpoints"
|
|
1840
|
-
};
|
|
1841
|
-
return {
|
|
1842
|
-
enabled: config.openapi.enabled !== false,
|
|
1843
|
-
title: config.openapi.title || "API Documentation",
|
|
1844
|
-
version: config.openapi.version || "1.0.0",
|
|
1845
|
-
description: config.openapi.description || "Auto-generated API documentation from endpoints"
|
|
1846
|
-
};
|
|
1847
|
-
}
|
|
1848
|
-
/**
|
|
1849
|
-
* Generate OpenAPI spec from endpoints
|
|
1850
|
-
* @returns Object with output path and endpoint count, or null if disabled
|
|
1851
|
-
*/
|
|
1852
|
-
async function generateOpenApi(config, options = {}) {
|
|
1853
|
-
const logger = options.silent ? { log: () => {} } : console;
|
|
1854
|
-
const openApiConfig = resolveOpenApiConfig(config);
|
|
1855
|
-
if (!openApiConfig.enabled) return null;
|
|
1856
|
-
const endpointGenerator = new EndpointGenerator();
|
|
1857
|
-
const loadedEndpoints = await endpointGenerator.load(config.routes, void 0, options.bustCache);
|
|
1858
|
-
if (loadedEndpoints.length === 0) {
|
|
1859
|
-
logger.log("No valid endpoints found for OpenAPI generation");
|
|
1860
|
-
return null;
|
|
1769
|
+
Object.defineProperty(exports, "EndpointGenerator", {
|
|
1770
|
+
enumerable: true,
|
|
1771
|
+
get: function() {
|
|
1772
|
+
return EndpointGenerator;
|
|
1861
1773
|
}
|
|
1862
|
-
const endpoints = loadedEndpoints.map(({ construct }) => construct);
|
|
1863
|
-
const outputPath = (0, node_path.join)(process.cwd(), OPENAPI_OUTPUT_PATH);
|
|
1864
|
-
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
|
|
1865
|
-
const tsGenerator = new OpenApiTsGenerator();
|
|
1866
|
-
const tsContent = await tsGenerator.generate(endpoints, {
|
|
1867
|
-
title: openApiConfig.title,
|
|
1868
|
-
version: openApiConfig.version,
|
|
1869
|
-
description: openApiConfig.description
|
|
1870
|
-
});
|
|
1871
|
-
await (0, node_fs_promises.writeFile)(outputPath, tsContent);
|
|
1872
|
-
logger.log(`📄 OpenAPI client generated: ${OPENAPI_OUTPUT_PATH}`);
|
|
1873
|
-
return {
|
|
1874
|
-
outputPath,
|
|
1875
|
-
endpointCount: loadedEndpoints.length
|
|
1876
|
-
};
|
|
1877
|
-
}
|
|
1878
|
-
async function openapiCommand(options = {}) {
|
|
1879
|
-
const logger = console;
|
|
1880
|
-
try {
|
|
1881
|
-
const loadedConfig = await require_config.loadWorkspaceConfig(options.cwd);
|
|
1882
|
-
if (loadedConfig.type === "single") {
|
|
1883
|
-
const config = loadedConfig.raw;
|
|
1884
|
-
if (!config.openapi) config.openapi = { enabled: true };
|
|
1885
|
-
const result = await generateOpenApi(config);
|
|
1886
|
-
if (result) logger.log(`Found ${result.endpointCount} endpoints`);
|
|
1887
|
-
} else {
|
|
1888
|
-
const { workspace } = loadedConfig;
|
|
1889
|
-
const workspaceRoot = workspace.root;
|
|
1890
|
-
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));
|
|
1891
|
-
if (backendApps.length === 0) {
|
|
1892
|
-
logger.log("No backend apps with OpenAPI enabled found");
|
|
1893
|
-
return;
|
|
1894
|
-
}
|
|
1895
|
-
if (options.app) {
|
|
1896
|
-
const entry = backendApps.find(([name]) => name === options.app);
|
|
1897
|
-
if (!entry) throw new Error(`App "${options.app}" not found or has OpenAPI disabled`);
|
|
1898
|
-
const [appName, app] = entry;
|
|
1899
|
-
const result = await generateOpenApiForApp(workspaceRoot, appName, app);
|
|
1900
|
-
if (result) logger.log(`📄 [${appName}] Generated OpenAPI (${result.endpointCount} endpoints)`);
|
|
1901
|
-
return;
|
|
1902
|
-
}
|
|
1903
|
-
for (const [appName, app] of backendApps) {
|
|
1904
|
-
if (app.type !== "backend" || !app.routes) continue;
|
|
1905
|
-
const appPath = (0, node_path.join)(workspaceRoot, app.path);
|
|
1906
|
-
await runOpenApiInSubprocess(appPath, appName);
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
} catch (error) {
|
|
1910
|
-
throw new Error(`OpenAPI generation failed: ${error.message}`);
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
/**
|
|
1914
|
-
* Generate OpenAPI for a single named app within a workspace.
|
|
1915
|
-
* Runs in-process. The caller is responsible for ensuring `process.cwd()`
|
|
1916
|
-
* is the app's directory so tsx loads the app's tsconfig path aliases.
|
|
1917
|
-
*/
|
|
1918
|
-
async function generateOpenApiForApp(workspaceRoot, _appName, app) {
|
|
1919
|
-
if (app.type !== "backend" || !app.routes) return null;
|
|
1920
|
-
const appPath = (0, node_path.join)(workspaceRoot, app.path);
|
|
1921
|
-
const routes = normalizeRoutes(app.routes);
|
|
1922
|
-
const routesGlob = routes.map((r) => (0, node_path.join)(appPath, r));
|
|
1923
|
-
const gkmConfig = {
|
|
1924
|
-
routes: routesGlob,
|
|
1925
|
-
envParser: app.envParser || "",
|
|
1926
|
-
logger: app.logger || "",
|
|
1927
|
-
openapi: app.openapi
|
|
1928
|
-
};
|
|
1929
|
-
return generateOpenApi(gkmConfig, { silent: true });
|
|
1930
|
-
}
|
|
1931
|
-
/**
|
|
1932
|
-
* Resolve the gkm bin path. Tests can override via `GKM_BIN_PATH` env var
|
|
1933
|
-
* to avoid depending on the built dist.
|
|
1934
|
-
*/
|
|
1935
|
-
function resolveGkmBinPath() {
|
|
1936
|
-
if (process.env.GKM_BIN_PATH) return process.env.GKM_BIN_PATH;
|
|
1937
|
-
return (0, node_url.fileURLToPath)(new URL("../bin/gkm.mjs", require("url").pathToFileURL(__filename).href));
|
|
1938
|
-
}
|
|
1939
|
-
/**
|
|
1940
|
-
* Spawn a subprocess that runs `gkm openapi --app <name>` with `cwd` set to
|
|
1941
|
-
* the app's directory. Inherits `NODE_OPTIONS` (which already contains
|
|
1942
|
-
* `--import tsx`), so the child gets a fresh tsx instance whose tsconfig
|
|
1943
|
-
* discovery picks up the app's tsconfig path aliases.
|
|
1944
|
-
*/
|
|
1945
|
-
async function runOpenApiInSubprocess(appCwd, appName) {
|
|
1946
|
-
const binPath = resolveGkmBinPath();
|
|
1947
|
-
await new Promise((resolve, reject) => {
|
|
1948
|
-
const child = (0, node_child_process.spawn)(process.execPath, [
|
|
1949
|
-
binPath,
|
|
1950
|
-
"openapi",
|
|
1951
|
-
"--app",
|
|
1952
|
-
appName
|
|
1953
|
-
], {
|
|
1954
|
-
cwd: appCwd,
|
|
1955
|
-
stdio: "inherit",
|
|
1956
|
-
env: process.env
|
|
1957
|
-
});
|
|
1958
|
-
child.on("error", reject);
|
|
1959
|
-
child.on("close", (code) => {
|
|
1960
|
-
if (code === 0) resolve();
|
|
1961
|
-
else reject(new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
|
|
1962
|
-
});
|
|
1963
|
-
});
|
|
1964
|
-
}
|
|
1965
|
-
|
|
1966
|
-
//#endregion
|
|
1967
|
-
Object.defineProperty(exports, 'EndpointGenerator', {
|
|
1968
|
-
enumerable: true,
|
|
1969
|
-
get: function () {
|
|
1970
|
-
return EndpointGenerator;
|
|
1971
|
-
}
|
|
1972
|
-
});
|
|
1973
|
-
Object.defineProperty(exports, 'OPENAPI_OUTPUT_PATH', {
|
|
1974
|
-
enumerable: true,
|
|
1975
|
-
get: function () {
|
|
1976
|
-
return OPENAPI_OUTPUT_PATH;
|
|
1977
|
-
}
|
|
1978
1774
|
});
|
|
1979
|
-
Object.defineProperty(exports,
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
});
|
|
1985
|
-
Object.defineProperty(exports, 'normalizeRoutes', {
|
|
1986
|
-
enumerable: true,
|
|
1987
|
-
get: function () {
|
|
1988
|
-
return normalizeRoutes;
|
|
1989
|
-
}
|
|
1990
|
-
});
|
|
1991
|
-
Object.defineProperty(exports, 'openapiCommand', {
|
|
1992
|
-
enumerable: true,
|
|
1993
|
-
get: function () {
|
|
1994
|
-
return openapiCommand;
|
|
1995
|
-
}
|
|
1775
|
+
Object.defineProperty(exports, "OpenApiTsGenerator", {
|
|
1776
|
+
enumerable: true,
|
|
1777
|
+
get: function() {
|
|
1778
|
+
return OpenApiTsGenerator;
|
|
1779
|
+
}
|
|
1996
1780
|
});
|
|
1997
|
-
Object.defineProperty(exports,
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
1781
|
+
Object.defineProperty(exports, "runtimeFor", {
|
|
1782
|
+
enumerable: true,
|
|
1783
|
+
get: function() {
|
|
1784
|
+
return runtimeFor;
|
|
1785
|
+
}
|
|
2002
1786
|
});
|
|
2003
|
-
|
|
1787
|
+
|
|
1788
|
+
//# sourceMappingURL=OpenApiTsGenerator-BN0PIZxd.cjs.map
|