@orval/hono 7.13.2 → 7.15.0
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/dist/index.js +152 -345
- package/dist/index.js.map +1 -1
- package/dist/zValidator.ts +137 -0
- package/package.json +9 -8
package/dist/index.js
CHANGED
|
@@ -55,6 +55,7 @@ const getRoute = (route) => {
|
|
|
55
55
|
|
|
56
56
|
//#endregion
|
|
57
57
|
//#region src/index.ts
|
|
58
|
+
const ZVALIDATOR_SOURCE = fs_extra.default.readFileSync(__orval_core.upath.join(__dirname, "zValidator.ts")).toString("utf8");
|
|
58
59
|
const HONO_DEPENDENCIES = [{
|
|
59
60
|
exports: [
|
|
60
61
|
{
|
|
@@ -66,17 +67,41 @@ const HONO_DEPENDENCIES = [{
|
|
|
66
67
|
],
|
|
67
68
|
dependency: "hono"
|
|
68
69
|
}];
|
|
70
|
+
/**
|
|
71
|
+
* generateModuleSpecifier generates the specifier that _from_ would use to
|
|
72
|
+
* import _to_. This is syntactical and does not validate the paths.
|
|
73
|
+
*
|
|
74
|
+
* @param from The filesystem path to the importer.
|
|
75
|
+
* @param to If a filesystem path, it and _from_ must be use the same frame of
|
|
76
|
+
* reference, such as process.cwd() or both be absolute. If only one is
|
|
77
|
+
* absolute, the other must be relative to process.cwd().
|
|
78
|
+
*
|
|
79
|
+
* Otherwise, treated as a package name and returned directly.
|
|
80
|
+
*
|
|
81
|
+
* @return A module specifier that can be used at _from_ to import _to_. It is
|
|
82
|
+
* extensionless to conform with the rest of orval.
|
|
83
|
+
*/
|
|
84
|
+
const generateModuleSpecifier = (from, to) => {
|
|
85
|
+
if (to.startsWith(".") || __orval_core.upath.isAbsolute(to)) {
|
|
86
|
+
let ret;
|
|
87
|
+
ret = __orval_core.upath.relativeSafe(__orval_core.upath.dirname(from), to);
|
|
88
|
+
ret = ret.replace(/\.ts$/, "");
|
|
89
|
+
ret = ret.replaceAll(__orval_core.upath.separator, "/");
|
|
90
|
+
return ret;
|
|
91
|
+
}
|
|
92
|
+
return to;
|
|
93
|
+
};
|
|
69
94
|
const getHonoDependencies = () => HONO_DEPENDENCIES;
|
|
70
95
|
const getHonoHeader = ({ verbOptions, output, tag, clientImplementation }) => {
|
|
71
96
|
const targetInfo = (0, __orval_core.getFileInfo)(output.target);
|
|
72
|
-
let handlers
|
|
97
|
+
let handlers;
|
|
73
98
|
const importHandlers = Object.values(verbOptions).filter((verbOption) => clientImplementation.includes(`${verbOption.operationName}Handlers`));
|
|
74
99
|
if (output.override.hono.handlers) {
|
|
75
100
|
const handlerFileInfo = (0, __orval_core.getFileInfo)(output.override.hono.handlers);
|
|
76
101
|
handlers = importHandlers.map((verbOption) => {
|
|
77
102
|
const isTagMode = output.mode === "tags" || output.mode === "tags-split";
|
|
78
103
|
const tag$1 = (0, __orval_core.kebab)(verbOption.tags[0] ?? "default");
|
|
79
|
-
const handlersPath = __orval_core.upath.relativeSafe(__orval_core.upath.join(targetInfo.dirname
|
|
104
|
+
const handlersPath = __orval_core.upath.relativeSafe(__orval_core.upath.join(targetInfo.dirname, isTagMode ? tag$1 : ""), __orval_core.upath.join(handlerFileInfo.dirname, `./${verbOption.operationName}`));
|
|
80
105
|
return `import { ${verbOption.operationName}Handlers } from '${handlersPath}';`;
|
|
81
106
|
}).join("\n");
|
|
82
107
|
} else handlers = `import {\n${importHandlers.map((verbOption) => ` ${verbOption.operationName}Handlers`).join(`, \n`)}\n} from './${tag ?? targetInfo.filename}.handlers';`;
|
|
@@ -89,7 +114,7 @@ const generateHonoRoute = ({ operationName, verb }, pathRoute) => {
|
|
|
89
114
|
return `
|
|
90
115
|
app.${verb.toLowerCase()}('${path}',...${operationName}Handlers)`;
|
|
91
116
|
};
|
|
92
|
-
const generateHono =
|
|
117
|
+
const generateHono = (verbOptions, options) => {
|
|
93
118
|
if (options.override.hono.compositeRoute) return {
|
|
94
119
|
implementation: "",
|
|
95
120
|
imports: []
|
|
@@ -104,7 +129,12 @@ const generateHono = async (verbOptions, options) => {
|
|
|
104
129
|
]
|
|
105
130
|
};
|
|
106
131
|
};
|
|
107
|
-
|
|
132
|
+
/**
|
|
133
|
+
* getHonoHandlers generates TypeScript code for the given verbs and reports
|
|
134
|
+
* whether the code requires zValidator.
|
|
135
|
+
*/
|
|
136
|
+
const getHonoHandlers = (...opts) => opts.reduce(([code, hasZValidator], opts$1) => {
|
|
137
|
+
const { handlerName, contextTypeName, verbOption, validator } = opts$1;
|
|
108
138
|
let currentValidator = "";
|
|
109
139
|
if (validator) {
|
|
110
140
|
if (verbOption.headers) currentValidator += `zValidator('header', ${verbOption.operationName}Header),\n`;
|
|
@@ -113,28 +143,25 @@ const getHonoHandlers = ({ handlerName, contextTypeName, verbOption, validator }
|
|
|
113
143
|
if (verbOption.body.definition) currentValidator += `zValidator('json', ${verbOption.operationName}Body),\n`;
|
|
114
144
|
if (validator !== "hono" && verbOption.response.originalSchema?.["200"]?.content?.["application/json"]) currentValidator += `zValidator('response', ${verbOption.operationName}Response),\n`;
|
|
115
145
|
}
|
|
116
|
-
|
|
146
|
+
code += `
|
|
117
147
|
export const ${handlerName} = factory.createHandlers(
|
|
118
148
|
${currentValidator}async (c: ${contextTypeName}) => {
|
|
119
149
|
|
|
120
150
|
},
|
|
121
151
|
);`;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return __orval_core.upath.relativeSafe(__orval_core.upath.dirname(handlerPath), pathWithoutExtension);
|
|
126
|
-
};
|
|
152
|
+
hasZValidator ||= currentValidator !== "";
|
|
153
|
+
return [code, hasZValidator];
|
|
154
|
+
}, ["", false]);
|
|
127
155
|
const getZvalidatorImports = (verbOptions, importPath, isHonoValidator) => {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
if (
|
|
132
|
-
if (
|
|
133
|
-
if (
|
|
134
|
-
if (!isHonoValidator &&
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return importImplementation ? `import {\n${importImplementation}\n} from '${importPath}'` : "";
|
|
156
|
+
const specifiers = [];
|
|
157
|
+
for (const { operationName, headers, params, queryParams, body, response } of verbOptions) {
|
|
158
|
+
if (headers) specifiers.push(`${operationName}Header`);
|
|
159
|
+
if (params.length > 0) specifiers.push(`${operationName}Params`);
|
|
160
|
+
if (queryParams) specifiers.push(`${operationName}QueryParams`);
|
|
161
|
+
if (body.definition) specifiers.push(`${operationName}Body`);
|
|
162
|
+
if (!isHonoValidator && response.originalSchema?.["200"]?.content?.["application/json"] != null) specifiers.push(`${operationName}Response`);
|
|
163
|
+
}
|
|
164
|
+
return specifiers.length === 0 ? "" : `import {\n${specifiers.join(",\n")}\n} from '${importPath}'`;
|
|
138
165
|
};
|
|
139
166
|
const getVerbOptionGroupByTag = (verbOptions) => {
|
|
140
167
|
return Object.values(verbOptions).reduce((acc, value) => {
|
|
@@ -144,155 +171,79 @@ const getVerbOptionGroupByTag = (verbOptions) => {
|
|
|
144
171
|
return acc;
|
|
145
172
|
}, {});
|
|
146
173
|
};
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
if (
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const handlerName = `${verbOption.operationName}Handlers`;
|
|
157
|
-
const contextTypeName = `${(0, __orval_core.pascal)(verbOption.operationName)}Context`;
|
|
158
|
-
if (isExist) {
|
|
159
|
-
const rawFile = await fs_extra.default.readFile(handlerPath$1, "utf8");
|
|
160
|
-
let content$1 = rawFile;
|
|
161
|
-
if (!rawFile.includes(handlerName)) content$1 += getHonoHandlers({
|
|
174
|
+
const generateHandlerFile = async ({ verbs, path, validatorModule, zodModule, contextModule }) => {
|
|
175
|
+
const validator = validatorModule === "@hono/zod-validator" ? "hono" : validatorModule != null;
|
|
176
|
+
if (fs_extra.default.existsSync(path)) {
|
|
177
|
+
const rawFile = await fs_extra.default.readFile(path, "utf8");
|
|
178
|
+
let content = rawFile;
|
|
179
|
+
content += Object.values(verbs).reduce((acc, verbOption) => {
|
|
180
|
+
const handlerName = `${verbOption.operationName}Handlers`;
|
|
181
|
+
const contextTypeName = `${(0, __orval_core.pascal)(verbOption.operationName)}Context`;
|
|
182
|
+
if (!rawFile.includes(handlerName)) acc += getHonoHandlers({
|
|
162
183
|
handlerName,
|
|
163
184
|
contextTypeName,
|
|
164
185
|
verbOption,
|
|
165
|
-
validator
|
|
166
|
-
});
|
|
167
|
-
return
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const factory = createFactory();
|
|
186
|
+
validator
|
|
187
|
+
})[0];
|
|
188
|
+
return acc;
|
|
189
|
+
}, "");
|
|
190
|
+
return content;
|
|
191
|
+
}
|
|
192
|
+
const [handlerCode, hasZValidator] = getHonoHandlers(...Object.values(verbs).map((verbOption) => ({
|
|
193
|
+
handlerName: `${verbOption.operationName}Handlers`,
|
|
194
|
+
contextTypeName: `${(0, __orval_core.pascal)(verbOption.operationName)}Context`,
|
|
195
|
+
verbOption,
|
|
196
|
+
validator
|
|
197
|
+
})));
|
|
198
|
+
const imports = ["import { createFactory } from 'hono/factory';"];
|
|
199
|
+
if (hasZValidator && validatorModule != null) imports.push(`import { zValidator } from '${generateModuleSpecifier(path, validatorModule)}';`);
|
|
200
|
+
imports.push(`import { ${Object.values(verbs).map((verb) => `${(0, __orval_core.pascal)(verb.operationName)}Context`).join(",\n")} } from '${generateModuleSpecifier(path, contextModule)}';`);
|
|
201
|
+
if (hasZValidator) imports.push(getZvalidatorImports(Object.values(verbs), generateModuleSpecifier(path, zodModule), validatorModule === "@hono/zod-validator"));
|
|
202
|
+
return `${imports.filter((imp) => imp !== "").join("\n")}
|
|
184
203
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
204
|
+
const factory = createFactory();${handlerCode}`;
|
|
205
|
+
};
|
|
206
|
+
const generateHandlerFiles = async (verbOptions, output, validatorModule) => {
|
|
207
|
+
const { extension, dirname, filename } = (0, __orval_core.getFileInfo)(output.target);
|
|
208
|
+
if (output.override.hono.handlers) return Promise.all(Object.values(verbOptions).map(async (verbOption) => {
|
|
209
|
+
const tag = (0, __orval_core.kebab)(verbOption.tags[0] ?? "default");
|
|
210
|
+
const path = __orval_core.upath.join(output.override.hono.handlers ?? "", `./${verbOption.operationName}` + extension);
|
|
211
|
+
return {
|
|
212
|
+
content: await generateHandlerFile({
|
|
213
|
+
path,
|
|
214
|
+
verbs: [verbOption],
|
|
215
|
+
validatorModule,
|
|
216
|
+
zodModule: output.mode === "tags" ? __orval_core.upath.join(dirname, `${(0, __orval_core.kebab)(tag)}.zod`) : __orval_core.upath.join(dirname, tag, tag + ".zod"),
|
|
217
|
+
contextModule: output.mode === "tags" ? __orval_core.upath.join(dirname, `${(0, __orval_core.kebab)(tag)}.context`) : __orval_core.upath.join(dirname, tag, tag + ".context")
|
|
218
|
+
}),
|
|
219
|
+
path
|
|
193
220
|
};
|
|
194
221
|
}));
|
|
195
222
|
if (output.mode === "tags" || output.mode === "tags-split") {
|
|
196
223
|
const groupByTags = getVerbOptionGroupByTag(verbOptions);
|
|
197
224
|
return Promise.all(Object.entries(groupByTags).map(async ([tag, verbs]) => {
|
|
198
225
|
const handlerPath$1 = output.mode === "tags" ? __orval_core.upath.join(dirname, `${(0, __orval_core.kebab)(tag)}.handlers${extension}`) : __orval_core.upath.join(dirname, tag, tag + ".handlers" + extension);
|
|
199
|
-
const hasZValidator$1 = verbs.some((verb) => !!verb.headers || verb.params.length > 0 || !!verb.queryParams || !!verb.body.definition);
|
|
200
|
-
if (fs_extra.default.existsSync(handlerPath$1)) {
|
|
201
|
-
const rawFile = await fs_extra.default.readFile(handlerPath$1, "utf8");
|
|
202
|
-
let content$2 = rawFile;
|
|
203
|
-
content$2 += Object.values(verbs).reduce((acc, verbOption) => {
|
|
204
|
-
const handlerName = `${verbOption.operationName}Handlers`;
|
|
205
|
-
const contextTypeName = `${(0, __orval_core.pascal)(verbOption.operationName)}Context`;
|
|
206
|
-
if (!rawFile.includes(handlerName)) acc += getHonoHandlers({
|
|
207
|
-
handlerName,
|
|
208
|
-
contextTypeName,
|
|
209
|
-
verbOption,
|
|
210
|
-
validator: output.override.hono.validator
|
|
211
|
-
});
|
|
212
|
-
return acc;
|
|
213
|
-
}, "");
|
|
214
|
-
return {
|
|
215
|
-
content: content$2,
|
|
216
|
-
path: handlerPath$1
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
let validatorImport$1 = "";
|
|
220
|
-
if (hasZValidator$1) {
|
|
221
|
-
if (output.override.hono.validator === true) {
|
|
222
|
-
const validatorOutputPath = output.override.hono.validatorOutputPath || `${dirname}/${filename}.validator${extension}`;
|
|
223
|
-
validatorImport$1 = `\nimport { zValidator } from '${getValidatorOutputRelativePath(validatorOutputPath, handlerPath$1)}';`;
|
|
224
|
-
} else if (output.override.hono.validator === "hono") validatorImport$1 = `\nimport { zValidator } from '@hono/zod-validator';`;
|
|
225
|
-
}
|
|
226
|
-
const outputRelativePath$1 = `./${(0, __orval_core.kebab)(tag)}`;
|
|
227
|
-
const zodImports$1 = output.override.hono.validator ? getZvalidatorImports(Object.values(verbs), `${outputRelativePath$1}.zod`, output.override.hono.validator === "hono") : "";
|
|
228
|
-
let content$1 = `import { createFactory } from 'hono/factory';${validatorImport$1}
|
|
229
|
-
import { ${Object.values(verbs).map((verb) => `${(0, __orval_core.pascal)(verb.operationName)}Context`).join(",\n")} } from '${outputRelativePath$1}.context';
|
|
230
|
-
${zodImports$1}
|
|
231
|
-
|
|
232
|
-
const factory = createFactory();`;
|
|
233
|
-
content$1 += Object.values(verbs).reduce((acc, verbOption) => {
|
|
234
|
-
const handlerName = `${verbOption.operationName}Handlers`;
|
|
235
|
-
const contextTypeName = `${(0, __orval_core.pascal)(verbOption.operationName)}Context`;
|
|
236
|
-
acc += getHonoHandlers({
|
|
237
|
-
handlerName,
|
|
238
|
-
contextTypeName,
|
|
239
|
-
verbOption,
|
|
240
|
-
validator: output.override.hono.validator
|
|
241
|
-
});
|
|
242
|
-
return acc;
|
|
243
|
-
}, "");
|
|
244
226
|
return {
|
|
245
|
-
content:
|
|
227
|
+
content: await generateHandlerFile({
|
|
228
|
+
path: handlerPath$1,
|
|
229
|
+
verbs,
|
|
230
|
+
validatorModule,
|
|
231
|
+
zodModule: output.mode === "tags" ? __orval_core.upath.join(dirname, `${(0, __orval_core.kebab)(tag)}.zod`) : __orval_core.upath.join(dirname, tag, tag + ".zod"),
|
|
232
|
+
contextModule: output.mode === "tags" ? __orval_core.upath.join(dirname, `${(0, __orval_core.kebab)(tag)}.context`) : __orval_core.upath.join(dirname, tag, tag + ".context")
|
|
233
|
+
}),
|
|
246
234
|
path: handlerPath$1
|
|
247
235
|
};
|
|
248
236
|
}));
|
|
249
237
|
}
|
|
250
|
-
const hasZValidator = Object.values(verbOptions).some((verb) => !!verb.headers || verb.params.length > 0 || !!verb.queryParams || !!verb.body.definition || verb.response.contentTypes.length === 1 && verb.response.contentTypes[0] === "application/json");
|
|
251
238
|
const handlerPath = __orval_core.upath.join(dirname, `${filename}.handlers${extension}`);
|
|
252
|
-
if (fs_extra.default.existsSync(handlerPath)) {
|
|
253
|
-
const rawFile = await fs_extra.default.readFile(handlerPath, "utf8");
|
|
254
|
-
let content$1 = rawFile;
|
|
255
|
-
content$1 += Object.values(verbOptions).reduce((acc, verbOption) => {
|
|
256
|
-
const handlerName = `${verbOption.operationName}Handlers`;
|
|
257
|
-
const contextTypeName = `${(0, __orval_core.pascal)(verbOption.operationName)}Context`;
|
|
258
|
-
if (!rawFile.includes(handlerName)) acc += getHonoHandlers({
|
|
259
|
-
handlerName,
|
|
260
|
-
contextTypeName,
|
|
261
|
-
verbOption,
|
|
262
|
-
validator: output.override.hono.validator
|
|
263
|
-
});
|
|
264
|
-
return acc;
|
|
265
|
-
}, "");
|
|
266
|
-
return [{
|
|
267
|
-
content: content$1,
|
|
268
|
-
path: handlerPath
|
|
269
|
-
}];
|
|
270
|
-
}
|
|
271
|
-
const outputRelativePath = `./${filename}`;
|
|
272
|
-
let validatorImport = "";
|
|
273
|
-
if (hasZValidator) {
|
|
274
|
-
if (output.override.hono.validator === true) validatorImport = `\nimport { zValidator } from '${output.override.hono.validatorOutputPath ? getValidatorOutputRelativePath(output.override.hono.validatorOutputPath, handlerPath) : `${outputRelativePath}.validator`}';`;
|
|
275
|
-
else if (output.override.hono.validator === "hono") validatorImport = `\nimport { zValidator } from '@hono/zod-validator';`;
|
|
276
|
-
}
|
|
277
|
-
const zodImports = output.override.hono.validator ? getZvalidatorImports(Object.values(verbOptions), `${outputRelativePath}.zod`, output.override.hono.validator === "hono") : "";
|
|
278
|
-
let content = `import { createFactory } from 'hono/factory';${validatorImport}
|
|
279
|
-
import { ${Object.values(verbOptions).map((verb) => `${(0, __orval_core.pascal)(verb.operationName)}Context`).join(",\n")} } from '${outputRelativePath}.context';
|
|
280
|
-
${zodImports}
|
|
281
|
-
|
|
282
|
-
const factory = createFactory();`;
|
|
283
|
-
content += Object.values(verbOptions).reduce((acc, verbOption) => {
|
|
284
|
-
const handlerName = `${verbOption.operationName}Handlers`;
|
|
285
|
-
const contextTypeName = `${(0, __orval_core.pascal)(verbOption.operationName)}Context`;
|
|
286
|
-
acc += getHonoHandlers({
|
|
287
|
-
handlerName,
|
|
288
|
-
contextTypeName,
|
|
289
|
-
verbOption,
|
|
290
|
-
validator: output.override.hono.validator
|
|
291
|
-
});
|
|
292
|
-
return acc;
|
|
293
|
-
}, "");
|
|
294
239
|
return [{
|
|
295
|
-
content
|
|
240
|
+
content: await generateHandlerFile({
|
|
241
|
+
path: handlerPath,
|
|
242
|
+
verbs: Object.values(verbOptions),
|
|
243
|
+
validatorModule,
|
|
244
|
+
zodModule: __orval_core.upath.join(dirname, `${filename}.zod`),
|
|
245
|
+
contextModule: __orval_core.upath.join(dirname, `${filename}.context`)
|
|
246
|
+
}),
|
|
296
247
|
path: handlerPath
|
|
297
248
|
}];
|
|
298
249
|
};
|
|
@@ -314,59 +265,51 @@ const getHeader = (option, info) => {
|
|
|
314
265
|
const header = option(info);
|
|
315
266
|
return Array.isArray(header) ? (0, __orval_core.jsDoc)({ description: header }) : header;
|
|
316
267
|
};
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
const groupByTags = getVerbOptionGroupByTag(verbOptions);
|
|
322
|
-
let relativeSchemasPath$1 = output.mode === "tags-split" ? "../" : "";
|
|
323
|
-
relativeSchemasPath$1 += output.schemas ? __orval_core.upath.relativeSafe(dirname, (0, __orval_core.getFileInfo)(output.schemas).dirname) : `${filename}.schemas`;
|
|
324
|
-
return Promise.all(Object.entries(groupByTags).map(async ([tag, verbs]) => {
|
|
325
|
-
let content$1 = `${header}import type { Context, Env } from 'hono';\n\n`;
|
|
326
|
-
const contexts$1 = verbs.map((verb) => getContext(verb)).join("\n");
|
|
327
|
-
const imps$1 = verbs.flatMap((verb) => {
|
|
328
|
-
const imports = [];
|
|
329
|
-
if (verb.params.length > 0) imports.push(...verb.params.flatMap((param) => param.imports));
|
|
330
|
-
if (verb.queryParams) imports.push({ name: verb.queryParams.schema.name });
|
|
331
|
-
if (verb.body.definition) imports.push(...verb.body.imports);
|
|
332
|
-
return imports;
|
|
333
|
-
}).filter((imp) => contexts$1.includes(imp.name)).filter((imp, i, arr) => arr.findIndex((v) => v.name === imp.name) === i);
|
|
334
|
-
if (contexts$1.includes("NonReadonly<")) {
|
|
335
|
-
content$1 += (0, __orval_core.getOrvalGeneratedTypes)();
|
|
336
|
-
content$1 += "\n";
|
|
337
|
-
}
|
|
338
|
-
if (imps$1.length > 0) {
|
|
339
|
-
const importSchemas = imps$1.map((imp) => imp.name).join(",\n ");
|
|
340
|
-
content$1 += `import {\n ${importSchemas}\n} from '${relativeSchemasPath$1}';\n\n`;
|
|
341
|
-
}
|
|
342
|
-
content$1 += contexts$1;
|
|
343
|
-
const contextPath$1 = output.mode === "tags" ? __orval_core.upath.join(dirname, `${(0, __orval_core.kebab)(tag)}.context${extension}`) : __orval_core.upath.join(dirname, tag, tag + ".context" + extension);
|
|
344
|
-
return {
|
|
345
|
-
content: content$1,
|
|
346
|
-
path: contextPath$1
|
|
347
|
-
};
|
|
348
|
-
}));
|
|
349
|
-
}
|
|
350
|
-
let content = `${header}import type { Context, Env } from 'hono';\n\n`;
|
|
351
|
-
const contextPath = __orval_core.upath.join(dirname, `${filename}.context${extension}`);
|
|
352
|
-
const contexts = Object.values(verbOptions).map((verbOption) => getContext(verbOption)).join("\n");
|
|
353
|
-
const imps = Object.values(verbOptions).flatMap((verb) => {
|
|
268
|
+
const generateContextFile = ({ path, verbs, schemaModule }) => {
|
|
269
|
+
let content = `import type { Context, Env } from 'hono';\n\n`;
|
|
270
|
+
const contexts = verbs.map((verb) => getContext(verb));
|
|
271
|
+
const imps = new Set(verbs.flatMap((verb) => {
|
|
354
272
|
const imports = [];
|
|
355
273
|
if (verb.params.length > 0) imports.push(...verb.params.flatMap((param) => param.imports));
|
|
356
274
|
if (verb.queryParams) imports.push({ name: verb.queryParams.schema.name });
|
|
357
275
|
if (verb.body.definition) imports.push(...verb.body.imports);
|
|
358
276
|
return imports;
|
|
359
|
-
}).
|
|
360
|
-
if (contexts.includes("NonReadonly<")) {
|
|
277
|
+
}).map((imp) => imp.name).filter((imp) => contexts.some((context) => context.includes(imp))));
|
|
278
|
+
if (contexts.some((context) => context.includes("NonReadonly<"))) {
|
|
361
279
|
content += (0, __orval_core.getOrvalGeneratedTypes)();
|
|
362
280
|
content += "\n";
|
|
363
281
|
}
|
|
364
|
-
|
|
365
|
-
content +=
|
|
366
|
-
content
|
|
282
|
+
if (imps.size > 0) content += `import type {\n${[...imps].toSorted().join(",\n ")}\n} from '${generateModuleSpecifier(path, schemaModule)}';\n\n`;
|
|
283
|
+
content += contexts.join("\n");
|
|
284
|
+
return content;
|
|
285
|
+
};
|
|
286
|
+
const generateContextFiles = (verbOptions, output, context, schemaModule) => {
|
|
287
|
+
const header = getHeader(output.override.header, context.specs[context.specKey].info);
|
|
288
|
+
const { extension, dirname, filename } = (0, __orval_core.getFileInfo)(output.target);
|
|
289
|
+
if (output.mode === "tags" || output.mode === "tags-split") {
|
|
290
|
+
const groupByTags = getVerbOptionGroupByTag(verbOptions);
|
|
291
|
+
return Object.entries(groupByTags).map(([tag, verbs]) => {
|
|
292
|
+
const path$1 = output.mode === "tags" ? __orval_core.upath.join(dirname, `${(0, __orval_core.kebab)(tag)}.context${extension}`) : __orval_core.upath.join(dirname, tag, tag + ".context" + extension);
|
|
293
|
+
const code$1 = generateContextFile({
|
|
294
|
+
verbs,
|
|
295
|
+
path: path$1,
|
|
296
|
+
schemaModule
|
|
297
|
+
});
|
|
298
|
+
return {
|
|
299
|
+
content: `${header}${code$1}`,
|
|
300
|
+
path: path$1
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
const path = __orval_core.upath.join(dirname, `${filename}.context${extension}`);
|
|
305
|
+
const code = generateContextFile({
|
|
306
|
+
verbs: Object.values(verbOptions),
|
|
307
|
+
path,
|
|
308
|
+
schemaModule
|
|
309
|
+
});
|
|
367
310
|
return [{
|
|
368
|
-
content
|
|
369
|
-
path
|
|
311
|
+
content: `${header}${code}`,
|
|
312
|
+
path
|
|
370
313
|
}];
|
|
371
314
|
};
|
|
372
315
|
const generateZodFiles = async (verbOptions, output, context) => {
|
|
@@ -425,154 +368,13 @@ const generateZodFiles = async (verbOptions, output, context) => {
|
|
|
425
368
|
};
|
|
426
369
|
const generateZvalidator = (output, context) => {
|
|
427
370
|
const header = getHeader(output.override.header, context.specs[context.specKey].info);
|
|
428
|
-
const content = `
|
|
429
|
-
// based on https://github.com/honojs/middleware/blob/main/packages/zod-validator/src/index.ts
|
|
430
|
-
import type { z, ZodSchema, ZodError } from 'zod';
|
|
431
|
-
import {
|
|
432
|
-
Context,
|
|
433
|
-
Env,
|
|
434
|
-
Input,
|
|
435
|
-
MiddlewareHandler,
|
|
436
|
-
TypedResponse,
|
|
437
|
-
ValidationTargets,
|
|
438
|
-
} from 'hono';
|
|
439
|
-
|
|
440
|
-
type HasUndefined<T> = undefined extends T ? true : false;
|
|
441
|
-
|
|
442
|
-
type Hook<T, E extends Env, P extends string, O = {}> = (
|
|
443
|
-
result:
|
|
444
|
-
| { success: true; data: T }
|
|
445
|
-
| { success: false; error: ZodError; data: T },
|
|
446
|
-
c: Context<E, P>,
|
|
447
|
-
) =>
|
|
448
|
-
| Response
|
|
449
|
-
| Promise<Response>
|
|
450
|
-
| void
|
|
451
|
-
| Promise<Response | void>
|
|
452
|
-
| TypedResponse<O>;
|
|
453
|
-
import { zValidator as zValidatorBase } from '@hono/zod-validator';
|
|
454
|
-
|
|
455
|
-
type ValidationTargetsWithResponse = ValidationTargets & { response: any };
|
|
456
|
-
|
|
457
|
-
export const zValidator =
|
|
458
|
-
<
|
|
459
|
-
T extends ZodSchema,
|
|
460
|
-
Target extends keyof ValidationTargetsWithResponse,
|
|
461
|
-
E extends Env,
|
|
462
|
-
P extends string,
|
|
463
|
-
In = z.input<T>,
|
|
464
|
-
Out = z.output<T>,
|
|
465
|
-
I extends Input = {
|
|
466
|
-
in: HasUndefined<In> extends true
|
|
467
|
-
? {
|
|
468
|
-
[K in Target]?: K extends 'json'
|
|
469
|
-
? In
|
|
470
|
-
: HasUndefined<
|
|
471
|
-
keyof ValidationTargetsWithResponse[K]
|
|
472
|
-
> extends true
|
|
473
|
-
? { [K2 in keyof In]?: ValidationTargetsWithResponse[K][K2] }
|
|
474
|
-
: { [K2 in keyof In]: ValidationTargetsWithResponse[K][K2] };
|
|
475
|
-
}
|
|
476
|
-
: {
|
|
477
|
-
[K in Target]: K extends 'json'
|
|
478
|
-
? In
|
|
479
|
-
: HasUndefined<
|
|
480
|
-
keyof ValidationTargetsWithResponse[K]
|
|
481
|
-
> extends true
|
|
482
|
-
? { [K2 in keyof In]?: ValidationTargetsWithResponse[K][K2] }
|
|
483
|
-
: { [K2 in keyof In]: ValidationTargetsWithResponse[K][K2] };
|
|
484
|
-
};
|
|
485
|
-
out: { [K in Target]: Out };
|
|
486
|
-
},
|
|
487
|
-
V extends I = I,
|
|
488
|
-
>(
|
|
489
|
-
target: Target,
|
|
490
|
-
schema: T,
|
|
491
|
-
hook?: Hook<z.infer<T>, E, P>,
|
|
492
|
-
): MiddlewareHandler<E, P, V> =>
|
|
493
|
-
async (c, next) => {
|
|
494
|
-
if (target !== 'response') {
|
|
495
|
-
const value = await zValidatorBase<
|
|
496
|
-
T,
|
|
497
|
-
keyof ValidationTargets,
|
|
498
|
-
E,
|
|
499
|
-
P,
|
|
500
|
-
In,
|
|
501
|
-
Out,
|
|
502
|
-
I,
|
|
503
|
-
V
|
|
504
|
-
>(
|
|
505
|
-
target,
|
|
506
|
-
schema,
|
|
507
|
-
hook,
|
|
508
|
-
)(c, next);
|
|
509
|
-
|
|
510
|
-
if (value instanceof Response) {
|
|
511
|
-
return value;
|
|
512
|
-
}
|
|
513
|
-
} else {
|
|
514
|
-
await next();
|
|
515
|
-
|
|
516
|
-
if (
|
|
517
|
-
c.res.status !== 200 ||
|
|
518
|
-
!c.res.headers.get('Content-Type')?.includes('application/json')
|
|
519
|
-
) {
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
let value: unknown;
|
|
524
|
-
try {
|
|
525
|
-
value = await c.res.json();
|
|
526
|
-
} catch {
|
|
527
|
-
const message = 'Malformed JSON in response';
|
|
528
|
-
c.res = new Response(message, { status: 400 });
|
|
529
|
-
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
const result = await schema.safeParseAsync(value);
|
|
534
|
-
|
|
535
|
-
if (hook) {
|
|
536
|
-
const hookResult = hook({ data: value, ...result }, c);
|
|
537
|
-
if (hookResult) {
|
|
538
|
-
if (hookResult instanceof Response || hookResult instanceof Promise) {
|
|
539
|
-
const hookResponse = await hookResult;
|
|
540
|
-
|
|
541
|
-
if (hookResponse instanceof Response) {
|
|
542
|
-
c.res = new Response(hookResponse.body, hookResponse);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
if (
|
|
546
|
-
'response' in hookResult &&
|
|
547
|
-
hookResult.response instanceof Response
|
|
548
|
-
) {
|
|
549
|
-
c.res = new Response(hookResult.response.body, hookResult.response);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (!result.success) {
|
|
555
|
-
c.res = new Response(JSON.stringify(result), {
|
|
556
|
-
status: 400,
|
|
557
|
-
headers: {
|
|
558
|
-
'Content-Type': 'application/json',
|
|
559
|
-
},
|
|
560
|
-
});
|
|
561
|
-
} else {
|
|
562
|
-
c.res = new Response(JSON.stringify(result.data), c.res);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
return;
|
|
567
|
-
};
|
|
568
|
-
`;
|
|
569
371
|
let validatorPath = output.override.hono.validatorOutputPath;
|
|
570
372
|
if (!output.override.hono.validatorOutputPath) {
|
|
571
373
|
const { extension, dirname, filename } = (0, __orval_core.getFileInfo)(output.target);
|
|
572
374
|
validatorPath = __orval_core.upath.join(dirname, `${filename}.validator${extension}`);
|
|
573
375
|
}
|
|
574
376
|
return {
|
|
575
|
-
content: `${header}${
|
|
377
|
+
content: `${header}${ZVALIDATOR_SOURCE}`,
|
|
576
378
|
path: validatorPath
|
|
577
379
|
};
|
|
578
380
|
};
|
|
@@ -584,19 +386,19 @@ const generateCompositeRoutes = async (verbOptions, output, context) => {
|
|
|
584
386
|
return generateHonoRoute(verbOption, verbOption.pathRoute);
|
|
585
387
|
}).join(";");
|
|
586
388
|
const importHandlers = Object.values(verbOptions);
|
|
587
|
-
let ImportHandlersImplementation
|
|
389
|
+
let ImportHandlersImplementation;
|
|
588
390
|
if (output.override.hono.handlers) {
|
|
589
391
|
const handlerFileInfo = (0, __orval_core.getFileInfo)(output.override.hono.handlers);
|
|
590
392
|
ImportHandlersImplementation = importHandlers.map((verbOption) => verbOption.operationName).map((operationName) => {
|
|
591
393
|
const importHandlerName = `${operationName}Handlers`;
|
|
592
|
-
const handlersPath =
|
|
394
|
+
const handlersPath = generateModuleSpecifier(compositeRouteInfo.path, __orval_core.upath.join(handlerFileInfo.dirname ?? "", `./${operationName}`));
|
|
593
395
|
return `import { ${importHandlerName} } from '${handlersPath}';`;
|
|
594
396
|
}).join("\n");
|
|
595
397
|
} else {
|
|
596
398
|
const tags = importHandlers.map((verbOption) => (0, __orval_core.kebab)(verbOption.tags[0] ?? "default"));
|
|
597
399
|
ImportHandlersImplementation = tags.filter((t, i) => tags.indexOf(t) === i).map((tag) => {
|
|
598
400
|
const importHandlerNames = importHandlers.filter((verbOption) => verbOption.tags[0] === tag).map((verbOption) => ` ${verbOption.operationName}Handlers`).join(`, \n`);
|
|
599
|
-
const handlersPath =
|
|
401
|
+
const handlersPath = generateModuleSpecifier(compositeRouteInfo.path, __orval_core.upath.join(targetInfo.dirname ?? "", tag));
|
|
600
402
|
return `import {\n${importHandlerNames}\n} from '${handlersPath}/${tag}.handlers';`;
|
|
601
403
|
}).join("\n");
|
|
602
404
|
}
|
|
@@ -613,11 +415,16 @@ export default app
|
|
|
613
415
|
}];
|
|
614
416
|
};
|
|
615
417
|
const generateExtraFiles = async (verbOptions, output, context) => {
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
|
|
418
|
+
const { path, pathWithoutExtension } = (0, __orval_core.getFileInfo)(output.target);
|
|
419
|
+
const validator = generateZvalidator(output, context);
|
|
420
|
+
let schemaModule;
|
|
421
|
+
if (output.schemas != null) schemaModule = (0, __orval_core.getFileInfo)(output.schemas).dirname;
|
|
422
|
+
else if (output.mode === "single") schemaModule = path;
|
|
423
|
+
else schemaModule = `${pathWithoutExtension}.schemas`;
|
|
424
|
+
const [handlers, contexts, zods, compositeRoutes] = await Promise.all([
|
|
425
|
+
generateHandlerFiles(verbOptions, output, validator.path),
|
|
426
|
+
generateContextFiles(verbOptions, output, context, schemaModule),
|
|
619
427
|
generateZodFiles(verbOptions, output, context),
|
|
620
|
-
generateZvalidator(output, context),
|
|
621
428
|
output.override.hono.compositeRoute ? generateCompositeRoutes(verbOptions, output, context) : []
|
|
622
429
|
]);
|
|
623
430
|
return [
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["HONO_DEPENDENCIES: GeneratorDependency[]","getHonoHeader: ClientHeaderBuilder","tag","upath","getHonoFooter: ClientFooterBuilder","generateHono: ClientBuilder","handlerPath","hasZValidator","fs","content","validatorImport","zodImports","outputRelativePath","relativeSchemasPath","contexts","imps","imports: GeneratorImport[]","contextPath","zods","allMutators","mutatorsImports","zodPath","context","generateExtraFiles: ClientExtraFilesBuilder","honoClientBuilder: ClientGeneratorsBuilder"],"sources":["../src/route.ts","../src/index.ts"],"sourcesContent":["import { sanitize } from '@orval/core';\n\nconst hasParam = (path: string): boolean => /[^{]*{[\\w*_-]*}.*/.test(path);\n\nconst getRoutePath = (path: string): string => {\n const matches = /([^{]*){?([\\w*_-]*)}?(.*)/.exec(path);\n if (!matches?.length) return path; // impossible due to regexp grouping here, but for TS\n\n const prev = matches[1];\n const param = sanitize(matches[2], {\n es5keyword: true,\n underscore: true,\n dash: true,\n dot: true,\n });\n const next = hasParam(matches[3]) ? getRoutePath(matches[3]) : matches[3];\n\n return hasParam(path) ? `${prev}\\:${param}${next}` : `${prev}${param}${next}`;\n};\n\nexport const getRoute = (route: string) => {\n const splittedRoute = route.split('/');\n\n return splittedRoute.reduce((acc, path, i) => {\n if (!path && !i) {\n return acc;\n }\n\n if (!path.includes('{')) {\n return `${acc}/${path}`;\n }\n\n return `${acc}/${getRoutePath(path)}`;\n }, '');\n};\n","import {\n camel,\n ClientBuilder,\n ClientExtraFilesBuilder,\n ClientFooterBuilder,\n ClientGeneratorsBuilder,\n ClientHeaderBuilder,\n ContextSpecs,\n generateMutatorImports,\n GeneratorDependency,\n GeneratorImport,\n GeneratorMutator,\n GeneratorVerbOptions,\n getFileInfo,\n getOrvalGeneratedTypes,\n getParamsInPath,\n jsDoc,\n kebab,\n NormalizedMutator,\n NormalizedOutputOptions,\n pascal,\n sanitize,\n upath,\n} from '@orval/core';\nimport { generateZod } from '@orval/zod';\nimport fs from 'fs-extra';\nimport { InfoObject } from 'openapi3-ts/oas30';\n\nimport { getRoute } from './route';\n\nconst HONO_DEPENDENCIES: GeneratorDependency[] = [\n {\n exports: [\n {\n name: 'Hono',\n values: true,\n },\n {\n name: 'Context',\n },\n {\n name: 'Env',\n },\n ],\n dependency: 'hono',\n },\n];\n\nexport const getHonoDependencies = () => HONO_DEPENDENCIES;\n\nexport const getHonoHeader: ClientHeaderBuilder = ({\n verbOptions,\n output,\n tag,\n clientImplementation,\n}) => {\n const targetInfo = getFileInfo(output.target);\n\n let handlers = '';\n\n const importHandlers = Object.values(verbOptions).filter((verbOption) =>\n clientImplementation.includes(`${verbOption.operationName}Handlers`),\n );\n\n if (output.override.hono.handlers) {\n const handlerFileInfo = getFileInfo(output.override.hono.handlers);\n handlers = importHandlers\n .map((verbOption) => {\n const isTagMode =\n output.mode === 'tags' || output.mode === 'tags-split';\n const tag = kebab(verbOption.tags[0] ?? 'default');\n\n const handlersPath = upath.relativeSafe(\n upath.join(targetInfo.dirname ?? '', isTagMode ? tag : ''),\n upath.join(\n handlerFileInfo.dirname ?? '',\n `./${verbOption.operationName}`,\n ),\n );\n\n return `import { ${verbOption.operationName}Handlers } from '${handlersPath}';`;\n })\n .join('\\n');\n } else {\n const importHandlerNames = importHandlers\n .map((verbOption) => ` ${verbOption.operationName}Handlers`)\n .join(`, \\n`);\n\n handlers = `import {\\n${importHandlerNames}\\n} from './${tag ?? targetInfo.filename}.handlers';`;\n }\n\n return `${handlers}\\n\\n\nconst app = new Hono()\\n\\n`;\n};\n\nexport const getHonoFooter: ClientFooterBuilder = () => 'export default app';\n\nconst generateHonoRoute = (\n { operationName, verb }: GeneratorVerbOptions,\n pathRoute: string,\n) => {\n const path = getRoute(pathRoute);\n\n return `\napp.${verb.toLowerCase()}('${path}',...${operationName}Handlers)`;\n};\n\nexport const generateHono: ClientBuilder = async (verbOptions, options) => {\n if (options.override.hono.compositeRoute) {\n return {\n implementation: '',\n imports: [],\n };\n }\n\n const routeImplementation = generateHonoRoute(verbOptions, options.pathRoute);\n\n return {\n implementation: routeImplementation ? `${routeImplementation}\\n\\n` : '',\n imports: [\n ...verbOptions.params.flatMap((param) => param.imports),\n ...verbOptions.body.imports,\n ...(verbOptions.queryParams\n ? [\n {\n name: verbOptions.queryParams.schema.name,\n },\n ]\n : []),\n ],\n };\n};\n\nconst getHonoHandlers = ({\n handlerName,\n contextTypeName,\n verbOption,\n validator,\n}: {\n handlerName: string;\n contextTypeName: string;\n verbOption: GeneratorVerbOptions;\n validator: boolean | 'hono' | NormalizedMutator;\n}) => {\n let currentValidator = '';\n\n if (validator) {\n if (verbOption.headers) {\n currentValidator += `zValidator('header', ${verbOption.operationName}Header),\\n`;\n }\n if (verbOption.params.length > 0) {\n currentValidator += `zValidator('param', ${verbOption.operationName}Params),\\n`;\n }\n if (verbOption.queryParams) {\n currentValidator += `zValidator('query', ${verbOption.operationName}QueryParams),\\n`;\n }\n if (verbOption.body.definition) {\n currentValidator += `zValidator('json', ${verbOption.operationName}Body),\\n`;\n }\n if (\n validator !== 'hono' &&\n verbOption.response.originalSchema?.['200']?.content?.['application/json']\n ) {\n currentValidator += `zValidator('response', ${verbOption.operationName}Response),\\n`;\n }\n }\n\n return `\nexport const ${handlerName} = factory.createHandlers(\n${currentValidator}async (c: ${contextTypeName}) => {\n\n },\n);`;\n};\n\nconst getValidatorOutputRelativePath = (\n validatorOutputPath: string,\n handlerPath: string,\n) => {\n const { pathWithoutExtension } = getFileInfo(validatorOutputPath);\n\n return upath.relativeSafe(upath.dirname(handlerPath), pathWithoutExtension);\n};\n\nconst getZvalidatorImports = (\n verbOptions: GeneratorVerbOptions[],\n importPath: string,\n isHonoValidator: boolean,\n) => {\n const importImplementation = verbOptions\n .flatMap((verbOption) => {\n const imports = [];\n\n if (verbOption.headers) {\n imports.push(`${verbOption.operationName}Header`);\n }\n\n if (verbOption.params.length > 0) {\n imports.push(`${verbOption.operationName}Params`);\n }\n\n if (verbOption.queryParams) {\n imports.push(`${verbOption.operationName}QueryParams`);\n }\n\n if (verbOption.body.definition) {\n imports.push(`${verbOption.operationName}Body`);\n }\n\n if (\n !isHonoValidator &&\n !!verbOption.response.originalSchema?.['200']?.content?.[\n 'application/json'\n ]\n ) {\n imports.push(`${verbOption.operationName}Response`);\n }\n\n return imports.join(',\\n');\n })\n .join(',\\n');\n\n return importImplementation\n ? `import {\\n${importImplementation}\\n} from '${importPath}'`\n : '';\n};\n\nconst getVerbOptionGroupByTag = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n) => {\n return Object.values(verbOptions).reduce<\n Record<string, GeneratorVerbOptions[]>\n >((acc, value) => {\n const tag = value.tags[0];\n if (!acc[tag]) {\n acc[tag] = [];\n }\n acc[tag].push(value);\n return acc;\n }, {});\n};\n\nconst generateHandlers = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n) => {\n const { pathWithoutExtension, extension, dirname, filename } = getFileInfo(\n output.target,\n );\n\n if (output.override.hono.handlers) {\n return Promise.all(\n Object.values(verbOptions).map(async (verbOption) => {\n const isTagMode =\n output.mode === 'tags' || output.mode === 'tags-split';\n const tag = kebab(verbOption.tags[0] ?? 'default');\n const outputPath = upath.relativeSafe(\n output.override.hono.handlers ?? '',\n isTagMode ? `${dirname}/${tag}/${tag}` : pathWithoutExtension,\n );\n\n const handlerPath = upath.join(\n output.override.hono.handlers ?? '',\n `./${verbOption.operationName}` + extension,\n );\n\n const hasZValidator =\n !!verbOption.headers ||\n verbOption.params.length > 0 ||\n !!verbOption.queryParams ||\n !!verbOption.body.definition;\n\n const isExist = fs.existsSync(handlerPath);\n\n const handlerName = `${verbOption.operationName}Handlers`;\n const contextTypeName = `${pascal(verbOption.operationName)}Context`;\n\n if (isExist) {\n const rawFile = await fs.readFile(handlerPath, 'utf8');\n let content = rawFile;\n\n if (!rawFile.includes(handlerName)) {\n content += getHonoHandlers({\n handlerName,\n contextTypeName,\n verbOption,\n validator: output.override.hono.validator,\n });\n }\n\n return {\n content,\n path: handlerPath,\n };\n }\n\n let validatorImport = '';\n\n if (hasZValidator) {\n if (output.override.hono.validator === true) {\n const validatorPath = output.override.hono.validatorOutputPath\n ? getValidatorOutputRelativePath(\n output.override.hono.validatorOutputPath,\n handlerPath,\n )\n : `${outputPath}.validator`;\n\n validatorImport = `\\nimport { zValidator } from '${validatorPath}';`;\n } else if (output.override.hono.validator === 'hono') {\n validatorImport = `\\nimport { zValidator } from '@hono/zod-validator';`;\n }\n }\n\n const zodImports = output.override.hono.validator\n ? getZvalidatorImports(\n [verbOption],\n `${outputPath}.zod`,\n output.override.hono.validator === 'hono',\n )\n : '';\n\n const content = `import { createFactory } from 'hono/factory';${validatorImport}\nimport { ${contextTypeName} } from '${outputPath}.context';\n${zodImports}\n\nconst factory = createFactory();\n\n${getHonoHandlers({\n handlerName,\n contextTypeName,\n verbOption,\n validator: output.override.hono.validator,\n})}\n`;\n\n return {\n content,\n path: handlerPath,\n };\n }),\n );\n }\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n return Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n const handlerPath =\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.handlers${extension}`)\n : upath.join(dirname, tag, tag + '.handlers' + extension);\n\n const hasZValidator = verbs.some(\n (verb) =>\n !!verb.headers ||\n verb.params.length > 0 ||\n !!verb.queryParams ||\n !!verb.body.definition,\n );\n\n const isExist = fs.existsSync(handlerPath);\n\n if (isExist) {\n const rawFile = await fs.readFile(handlerPath, 'utf8');\n let content = rawFile;\n\n content += Object.values(verbs).reduce((acc, verbOption) => {\n const handlerName = `${verbOption.operationName}Handlers`;\n const contextTypeName = `${pascal(\n verbOption.operationName,\n )}Context`;\n\n if (!rawFile.includes(handlerName)) {\n acc += getHonoHandlers({\n handlerName,\n contextTypeName,\n verbOption,\n validator: output.override.hono.validator,\n });\n }\n\n return acc;\n }, '');\n\n return {\n content,\n path: handlerPath,\n };\n }\n\n let validatorImport = '';\n if (hasZValidator) {\n if (output.override.hono.validator === true) {\n const validatorOutputPath =\n output.override.hono.validatorOutputPath ||\n `${dirname}/${filename}.validator${extension}`;\n const validatorPath = getValidatorOutputRelativePath(\n validatorOutputPath,\n handlerPath,\n );\n\n validatorImport = `\\nimport { zValidator } from '${validatorPath}';`;\n } else if (output.override.hono.validator === 'hono') {\n validatorImport = `\\nimport { zValidator } from '@hono/zod-validator';`;\n }\n }\n\n const outputRelativePath = `./${kebab(tag)}`;\n\n const zodImports = output.override.hono.validator\n ? getZvalidatorImports(\n Object.values(verbs),\n `${outputRelativePath}.zod`,\n output.override.hono.validator === 'hono',\n )\n : '';\n\n let content = `import { createFactory } from 'hono/factory';${validatorImport}\nimport { ${Object.values(verbs)\n .map((verb) => `${pascal(verb.operationName)}Context`)\n .join(',\\n')} } from '${outputRelativePath}.context';\n${zodImports}\n\nconst factory = createFactory();`;\n\n content += Object.values(verbs).reduce((acc, verbOption) => {\n const handlerName = `${verbOption.operationName}Handlers`;\n const contextTypeName = `${pascal(verbOption.operationName)}Context`;\n\n acc += getHonoHandlers({\n handlerName,\n contextTypeName,\n verbOption,\n validator: output.override.hono.validator,\n });\n\n return acc;\n }, '');\n\n return {\n content,\n path: handlerPath,\n };\n }),\n );\n }\n\n const hasZValidator = Object.values(verbOptions).some(\n (verb) =>\n !!verb.headers ||\n verb.params.length > 0 ||\n !!verb.queryParams ||\n !!verb.body.definition ||\n (verb.response.contentTypes.length === 1 &&\n verb.response.contentTypes[0] === 'application/json'),\n );\n\n const handlerPath = upath.join(dirname, `${filename}.handlers${extension}`);\n\n const isExist = fs.existsSync(handlerPath);\n\n if (isExist) {\n const rawFile = await fs.readFile(handlerPath, 'utf8');\n let content = rawFile;\n\n content += Object.values(verbOptions).reduce((acc, verbOption) => {\n const handlerName = `${verbOption.operationName}Handlers`;\n const contextTypeName = `${pascal(verbOption.operationName)}Context`;\n\n if (!rawFile.includes(handlerName)) {\n acc += getHonoHandlers({\n handlerName,\n contextTypeName,\n verbOption,\n validator: output.override.hono.validator,\n });\n }\n\n return acc;\n }, '');\n\n return [\n {\n content,\n path: handlerPath,\n },\n ];\n }\n\n const outputRelativePath = `./${filename}`;\n\n let validatorImport = '';\n\n if (hasZValidator) {\n if (output.override.hono.validator === true) {\n const validatorPath = output.override.hono.validatorOutputPath\n ? getValidatorOutputRelativePath(\n output.override.hono.validatorOutputPath,\n handlerPath,\n )\n : `${outputRelativePath}.validator`;\n\n validatorImport = `\\nimport { zValidator } from '${validatorPath}';`;\n } else if (output.override.hono.validator === 'hono') {\n validatorImport = `\\nimport { zValidator } from '@hono/zod-validator';`;\n }\n }\n\n const zodImports = output.override.hono.validator\n ? getZvalidatorImports(\n Object.values(verbOptions),\n `${outputRelativePath}.zod`,\n output.override.hono.validator === 'hono',\n )\n : '';\n\n let content = `import { createFactory } from 'hono/factory';${validatorImport}\nimport { ${Object.values(verbOptions)\n .map((verb) => `${pascal(verb.operationName)}Context`)\n .join(',\\n')} } from '${outputRelativePath}.context';\n${zodImports}\n\nconst factory = createFactory();`;\n\n content += Object.values(verbOptions).reduce((acc, verbOption) => {\n const handlerName = `${verbOption.operationName}Handlers`;\n const contextTypeName = `${pascal(verbOption.operationName)}Context`;\n\n acc += getHonoHandlers({\n handlerName,\n contextTypeName,\n verbOption,\n validator: output.override.hono.validator,\n });\n\n return acc;\n }, '');\n\n return [\n {\n content,\n path: handlerPath,\n },\n ];\n};\n\nconst getContext = (verbOption: GeneratorVerbOptions) => {\n let paramType = '';\n if (verbOption.params.length > 0) {\n const params = getParamsInPath(verbOption.pathRoute).map((name) => {\n const param = verbOption.params.find(\n (p) => p.name === sanitize(camel(name), { es5keyword: true }),\n );\n const definition = param?.definition.split(':')[1];\n const required = param?.required ?? false;\n return {\n definition: `${name}${required ? '' : '?'}:${definition}`,\n };\n });\n paramType = `param: {\\n ${params\n .map((property) => property.definition)\n .join(',\\n ')},\\n },`;\n }\n\n const queryType = verbOption.queryParams\n ? `query: ${verbOption.queryParams?.schema.name},`\n : '';\n const bodyType = verbOption.body.definition\n ? `json: ${verbOption.body.definition},`\n : '';\n const hasIn = !!paramType || !!queryType || !!bodyType;\n\n return `export type ${pascal(\n verbOption.operationName,\n )}Context<E extends Env = any> = Context<E, '${getRoute(\n verbOption.pathRoute,\n )}'${\n hasIn\n ? `, { in: { ${paramType}${queryType}${bodyType} }, out: { ${paramType}${queryType}${bodyType} } }`\n : ''\n }>`;\n};\n\nconst getHeader = (\n option: false | ((info: InfoObject) => string | string[]),\n info: InfoObject,\n): string => {\n if (!option) {\n return '';\n }\n\n const header = option(info);\n\n return Array.isArray(header) ? jsDoc({ description: header }) : header;\n};\n\nconst generateContext = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpecs,\n) => {\n const header = getHeader(\n output.override.header,\n context.specs[context.specKey].info,\n );\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n let relativeSchemasPath = output.mode === 'tags-split' ? '../' : '';\n\n relativeSchemasPath += output.schemas\n ? upath.relativeSafe(dirname, getFileInfo(output.schemas).dirname)\n : `${filename}.schemas`;\n\n return Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n let content = `${header}import type { Context, Env } from 'hono';\\n\\n`;\n\n const contexts = verbs.map((verb) => getContext(verb)).join('\\n');\n\n const imps = verbs\n .flatMap((verb) => {\n const imports: GeneratorImport[] = [];\n if (verb.params.length > 0) {\n imports.push(...verb.params.flatMap((param) => param.imports));\n }\n\n if (verb.queryParams) {\n imports.push({\n name: verb.queryParams.schema.name,\n });\n }\n\n if (verb.body.definition) {\n imports.push(...verb.body.imports);\n }\n\n return imports;\n })\n .filter((imp) => contexts.includes(imp.name))\n .filter(\n (imp, i, arr) => arr.findIndex((v) => v.name === imp.name) === i,\n );\n\n if (contexts.includes('NonReadonly<')) {\n content += getOrvalGeneratedTypes();\n content += '\\n';\n }\n\n if (imps.length > 0) {\n const importSchemas = imps.map((imp) => imp.name).join(',\\n ');\n\n content += `import {\\n ${importSchemas}\\n} from '${relativeSchemasPath}';\\n\\n`;\n }\n\n content += contexts;\n\n const contextPath =\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.context${extension}`)\n : upath.join(dirname, tag, tag + '.context' + extension);\n\n return {\n content,\n path: contextPath,\n };\n }),\n );\n }\n\n let content = `${header}import type { Context, Env } from 'hono';\\n\\n`;\n\n const contextPath = upath.join(dirname, `${filename}.context${extension}`);\n\n const contexts = Object.values(verbOptions)\n .map((verbOption) => getContext(verbOption))\n .join('\\n');\n\n const imps = Object.values(verbOptions)\n .flatMap((verb) => {\n const imports: GeneratorImport[] = [];\n if (verb.params.length > 0) {\n imports.push(...verb.params.flatMap((param) => param.imports));\n }\n\n if (verb.queryParams) {\n imports.push({\n name: verb.queryParams.schema.name,\n });\n }\n\n if (verb.body.definition) {\n imports.push(...verb.body.imports);\n }\n\n return imports;\n })\n .filter((imp) => contexts.includes(imp.name))\n .filter((imp, i, arr) => arr.findIndex((v) => v.name === imp.name) === i);\n\n if (contexts.includes('NonReadonly<')) {\n content += getOrvalGeneratedTypes();\n content += '\\n';\n }\n\n const relativeSchemasPath = output.schemas\n ? upath.relativeSafe(dirname, getFileInfo(output.schemas).dirname)\n : './' + filename + '.schemas';\n\n content += `import { ${imps\n .map((imp) => imp.name)\n .join(',\\n')} } from '${relativeSchemasPath}';\\n\\n`;\n\n content += contexts;\n\n return [\n {\n content,\n path: contextPath,\n },\n ];\n};\n\nconst generateZodFiles = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpecs,\n) => {\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n const header = getHeader(\n output.override.header,\n context.specs[context.specKey].info,\n );\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n const builderContexts = await Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n const zods = await Promise.all(\n verbs.map((verbOption) =>\n generateZod(\n verbOption,\n {\n route: verbOption.route,\n pathRoute: verbOption.pathRoute,\n override: output.override,\n context,\n mock: output.mock,\n output: output.target!,\n },\n output.client,\n ),\n ),\n );\n\n if (zods.every((z) => z.implementation === '')) {\n return {\n content: '',\n path: '',\n };\n }\n\n const allMutators = zods.reduce(\n (acc, z) => {\n for (const mutator of z.mutators ?? []) {\n acc[mutator.name] = mutator;\n }\n return acc;\n },\n {} as Record<string, GeneratorMutator>,\n );\n\n const mutatorsImports = generateMutatorImports({\n mutators: Object.values(allMutators),\n });\n\n let content = `${header}import { z as zod } from 'zod';\\n${mutatorsImports}\\n`;\n\n const zodPath =\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.zod${extension}`)\n : upath.join(dirname, tag, tag + '.zod' + extension);\n\n content += zods.map((zod) => zod.implementation).join('\\n');\n\n return {\n content,\n path: zodPath,\n };\n }),\n );\n\n return Promise.all(\n builderContexts.filter((context) => context.content !== ''),\n );\n }\n\n const zods = await Promise.all(\n Object.values(verbOptions).map((verbOption) =>\n generateZod(\n verbOption,\n {\n route: verbOption.route,\n pathRoute: verbOption.pathRoute,\n override: output.override,\n context,\n mock: output.mock,\n output: output.target!,\n },\n output.client,\n ),\n ),\n );\n\n const allMutators = zods.reduce(\n (acc, z) => {\n for (const mutator of z.mutators ?? []) {\n acc[mutator.name] = mutator;\n }\n return acc;\n },\n {} as Record<string, GeneratorMutator>,\n );\n\n const mutatorsImports = generateMutatorImports({\n mutators: Object.values(allMutators),\n });\n\n let content = `${header}import { z as zod } from 'zod';\\n${mutatorsImports}\\n`;\n\n const zodPath = upath.join(dirname, `${filename}.zod${extension}`);\n\n content += zods.map((zod) => zod.implementation).join('\\n');\n\n return [\n {\n content,\n path: zodPath,\n },\n ];\n};\n\nconst generateZvalidator = (\n output: NormalizedOutputOptions,\n context: ContextSpecs,\n) => {\n const header = getHeader(\n output.override.header,\n context.specs[context.specKey].info,\n );\n\n const content = `\n// based on https://github.com/honojs/middleware/blob/main/packages/zod-validator/src/index.ts\nimport type { z, ZodSchema, ZodError } from 'zod';\nimport {\n Context,\n Env,\n Input,\n MiddlewareHandler,\n TypedResponse,\n ValidationTargets,\n} from 'hono';\n\ntype HasUndefined<T> = undefined extends T ? true : false;\n\ntype Hook<T, E extends Env, P extends string, O = {}> = (\n result:\n | { success: true; data: T }\n | { success: false; error: ZodError; data: T },\n c: Context<E, P>,\n) =>\n | Response\n | Promise<Response>\n | void\n | Promise<Response | void>\n | TypedResponse<O>;\nimport { zValidator as zValidatorBase } from '@hono/zod-validator';\n\ntype ValidationTargetsWithResponse = ValidationTargets & { response: any };\n\nexport const zValidator =\n <\n T extends ZodSchema,\n Target extends keyof ValidationTargetsWithResponse,\n E extends Env,\n P extends string,\n In = z.input<T>,\n Out = z.output<T>,\n I extends Input = {\n in: HasUndefined<In> extends true\n ? {\n [K in Target]?: K extends 'json'\n ? In\n : HasUndefined<\n keyof ValidationTargetsWithResponse[K]\n > extends true\n ? { [K2 in keyof In]?: ValidationTargetsWithResponse[K][K2] }\n : { [K2 in keyof In]: ValidationTargetsWithResponse[K][K2] };\n }\n : {\n [K in Target]: K extends 'json'\n ? In\n : HasUndefined<\n keyof ValidationTargetsWithResponse[K]\n > extends true\n ? { [K2 in keyof In]?: ValidationTargetsWithResponse[K][K2] }\n : { [K2 in keyof In]: ValidationTargetsWithResponse[K][K2] };\n };\n out: { [K in Target]: Out };\n },\n V extends I = I,\n >(\n target: Target,\n schema: T,\n hook?: Hook<z.infer<T>, E, P>,\n ): MiddlewareHandler<E, P, V> =>\n async (c, next) => {\n if (target !== 'response') {\n const value = await zValidatorBase<\n T,\n keyof ValidationTargets,\n E,\n P,\n In,\n Out,\n I,\n V\n >(\n target,\n schema,\n hook,\n )(c, next);\n\n if (value instanceof Response) {\n return value;\n }\n } else {\n await next();\n\n if (\n c.res.status !== 200 ||\n !c.res.headers.get('Content-Type')?.includes('application/json')\n ) {\n return;\n }\n\n let value: unknown;\n try {\n value = await c.res.json();\n } catch {\n const message = 'Malformed JSON in response';\n c.res = new Response(message, { status: 400 });\n\n return;\n }\n\n const result = await schema.safeParseAsync(value);\n\n if (hook) {\n const hookResult = hook({ data: value, ...result }, c);\n if (hookResult) {\n if (hookResult instanceof Response || hookResult instanceof Promise) {\n const hookResponse = await hookResult;\n\n if (hookResponse instanceof Response) {\n c.res = new Response(hookResponse.body, hookResponse);\n }\n }\n if (\n 'response' in hookResult &&\n hookResult.response instanceof Response\n ) {\n c.res = new Response(hookResult.response.body, hookResult.response);\n }\n }\n }\n\n if (!result.success) {\n c.res = new Response(JSON.stringify(result), {\n status: 400,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n } else {\n c.res = new Response(JSON.stringify(result.data), c.res);\n }\n }\n \n return;\n };\n`;\n\n let validatorPath = output.override.hono.validatorOutputPath;\n if (!output.override.hono.validatorOutputPath) {\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n validatorPath = upath.join(dirname, `${filename}.validator${extension}`);\n }\n\n return {\n content: `${header}${content}`,\n path: validatorPath,\n };\n};\n\nconst generateCompositeRoutes = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpecs,\n) => {\n const targetInfo = getFileInfo(output.target);\n const compositeRouteInfo = getFileInfo(output.override.hono.compositeRoute);\n\n const header = getHeader(\n output.override.header,\n context.specs[context.specKey].info,\n );\n\n const routes = Object.values(verbOptions)\n .map((verbOption) => {\n return generateHonoRoute(verbOption, verbOption.pathRoute);\n })\n .join(';');\n\n const importHandlers = Object.values(verbOptions);\n\n let ImportHandlersImplementation = '';\n if (output.override.hono.handlers) {\n const handlerFileInfo = getFileInfo(output.override.hono.handlers);\n const operationNames = importHandlers.map(\n (verbOption) => verbOption.operationName,\n );\n\n ImportHandlersImplementation = operationNames\n .map((operationName) => {\n const importHandlerName = `${operationName}Handlers`;\n\n const handlersPath = upath.relativeSafe(\n compositeRouteInfo.dirname,\n upath.join(handlerFileInfo.dirname ?? '', `./${operationName}`),\n );\n\n return `import { ${importHandlerName} } from '${handlersPath}';`;\n })\n .join('\\n');\n } else {\n const tags = importHandlers.map((verbOption) =>\n kebab(verbOption.tags[0] ?? 'default'),\n );\n const uniqueTags = tags.filter((t, i) => tags.indexOf(t) === i);\n\n ImportHandlersImplementation = uniqueTags\n .map((tag) => {\n const importHandlerNames = importHandlers\n .filter((verbOption) => verbOption.tags[0] === tag)\n .map((verbOption) => ` ${verbOption.operationName}Handlers`)\n .join(`, \\n`);\n\n const handlersPath = upath.relativeSafe(\n compositeRouteInfo.dirname,\n upath.join(targetInfo.dirname ?? '', tag),\n );\n\n return `import {\\n${importHandlerNames}\\n} from '${handlersPath}/${tag}.handlers';`;\n })\n .join('\\n');\n }\n\n const honoImport = `import { Hono } from 'hono';`;\n const honoInitialization = `\\nconst app = new Hono()`;\n const honoAppExport = `\\nexport default app`;\n\n const content = `${header}${honoImport}\n${ImportHandlersImplementation}\n${honoInitialization}\n${routes}\n${honoAppExport}\n`;\n\n return [\n {\n content,\n path: output.override.hono.compositeRoute || '',\n },\n ];\n};\n\nexport const generateExtraFiles: ClientExtraFilesBuilder = async (\n verbOptions,\n output,\n context,\n) => {\n const [handlers, contexts, zods, validator, compositeRoutes] =\n await Promise.all([\n generateHandlers(verbOptions, output),\n generateContext(verbOptions, output, context),\n generateZodFiles(verbOptions, output, context),\n generateZvalidator(output, context),\n output.override.hono.compositeRoute\n ? generateCompositeRoutes(verbOptions, output, context)\n : [],\n ]);\n\n return [\n ...handlers,\n ...contexts,\n ...zods,\n ...(output.override.hono.validator &&\n output.override.hono.validator !== 'hono'\n ? [validator]\n : []),\n ...compositeRoutes,\n ];\n};\n\nconst honoClientBuilder: ClientGeneratorsBuilder = {\n client: generateHono,\n dependencies: getHonoDependencies,\n header: getHonoHeader,\n footer: getHonoFooter,\n extraFiles: generateExtraFiles,\n};\n\nexport const builder = () => () => honoClientBuilder;\n\nexport default builder;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["fs","upath","HONO_DEPENDENCIES: GeneratorDependency[]","ret: string","getHonoHeader: ClientHeaderBuilder","handlers: string","tag","getHonoFooter: ClientFooterBuilder","generateHono: ClientBuilder","opts","handlerPath","imports: GeneratorImport[]","path","code","zods","allMutators","mutatorsImports","content","zodPath","context","ImportHandlersImplementation: string","generateExtraFiles: ClientExtraFilesBuilder","schemaModule: string","honoClientBuilder: ClientGeneratorsBuilder"],"sources":["../src/route.ts","../src/index.ts"],"sourcesContent":["import { sanitize } from '@orval/core';\n\nconst hasParam = (path: string): boolean => /[^{]*{[\\w*_-]*}.*/.test(path);\n\nconst getRoutePath = (path: string): string => {\n const matches = /([^{]*){?([\\w*_-]*)}?(.*)/.exec(path);\n if (!matches?.length) return path; // impossible due to regexp grouping here, but for TS\n\n const prev = matches[1];\n const param = sanitize(matches[2], {\n es5keyword: true,\n underscore: true,\n dash: true,\n dot: true,\n });\n const next = hasParam(matches[3]) ? getRoutePath(matches[3]) : matches[3];\n\n return hasParam(path) ? `${prev}\\:${param}${next}` : `${prev}${param}${next}`;\n};\n\nexport const getRoute = (route: string) => {\n const splittedRoute = route.split('/');\n\n return splittedRoute.reduce((acc, path, i) => {\n if (!path && !i) {\n return acc;\n }\n\n if (!path.includes('{')) {\n return `${acc}/${path}`;\n }\n\n return `${acc}/${getRoutePath(path)}`;\n }, '');\n};\n","import {\n camel,\n type ClientBuilder,\n type ClientExtraFilesBuilder,\n type ClientFooterBuilder,\n type ClientGeneratorsBuilder,\n type ClientHeaderBuilder,\n type ContextSpecs,\n generateMutatorImports,\n type GeneratorDependency,\n type GeneratorImport,\n type GeneratorMutator,\n type GeneratorVerbOptions,\n getFileInfo,\n getOrvalGeneratedTypes,\n getParamsInPath,\n jsDoc,\n kebab,\n type NormalizedMutator,\n type NormalizedOutputOptions,\n pascal,\n sanitize,\n upath,\n} from '@orval/core';\nimport { generateZod } from '@orval/zod';\nimport fs from 'fs-extra';\nimport { type InfoObject } from 'openapi3-ts/oas30';\n\nimport { getRoute } from './route';\n\nconst ZVALIDATOR_SOURCE = fs\n .readFileSync(upath.join(__dirname, 'zValidator.ts'))\n .toString('utf8');\n\nconst HONO_DEPENDENCIES: GeneratorDependency[] = [\n {\n exports: [\n {\n name: 'Hono',\n values: true,\n },\n {\n name: 'Context',\n },\n {\n name: 'Env',\n },\n ],\n dependency: 'hono',\n },\n];\n\n/**\n * generateModuleSpecifier generates the specifier that _from_ would use to\n * import _to_. This is syntactical and does not validate the paths.\n *\n * @param from The filesystem path to the importer.\n * @param to If a filesystem path, it and _from_ must be use the same frame of\n * reference, such as process.cwd() or both be absolute. If only one is\n * absolute, the other must be relative to process.cwd().\n *\n * Otherwise, treated as a package name and returned directly.\n *\n * @return A module specifier that can be used at _from_ to import _to_. It is\n * extensionless to conform with the rest of orval.\n */\nconst generateModuleSpecifier = (from: string, to: string) => {\n if (to.startsWith('.') || upath.isAbsolute(to)) {\n // One of \"/foo/bar\", \"./foo/bar\", \"../foo/bar\", etc.\n let ret: string;\n ret = upath.relativeSafe(upath.dirname(from), to);\n ret = ret.replace(/\\.ts$/, '');\n ret = ret.replaceAll(upath.separator, '/');\n return ret;\n }\n\n // Not a relative or absolute file path. Import as-is.\n return to;\n};\n\nexport const getHonoDependencies = () => HONO_DEPENDENCIES;\n\nexport const getHonoHeader: ClientHeaderBuilder = ({\n verbOptions,\n output,\n tag,\n clientImplementation,\n}) => {\n const targetInfo = getFileInfo(output.target);\n\n let handlers: string;\n\n const importHandlers = Object.values(verbOptions).filter((verbOption) =>\n clientImplementation.includes(`${verbOption.operationName}Handlers`),\n );\n\n if (output.override.hono.handlers) {\n const handlerFileInfo = getFileInfo(output.override.hono.handlers);\n handlers = importHandlers\n .map((verbOption) => {\n const isTagMode =\n output.mode === 'tags' || output.mode === 'tags-split';\n const tag = kebab(verbOption.tags[0] ?? 'default');\n\n const handlersPath = upath.relativeSafe(\n upath.join(targetInfo.dirname, isTagMode ? tag : ''),\n upath.join(handlerFileInfo.dirname, `./${verbOption.operationName}`),\n );\n\n return `import { ${verbOption.operationName}Handlers } from '${handlersPath}';`;\n })\n .join('\\n');\n } else {\n const importHandlerNames = importHandlers\n .map((verbOption) => ` ${verbOption.operationName}Handlers`)\n .join(`, \\n`);\n\n handlers = `import {\\n${importHandlerNames}\\n} from './${tag ?? targetInfo.filename}.handlers';`;\n }\n\n return `${handlers}\\n\\n\nconst app = new Hono()\\n\\n`;\n};\n\nexport const getHonoFooter: ClientFooterBuilder = () => 'export default app';\n\nconst generateHonoRoute = (\n { operationName, verb }: GeneratorVerbOptions,\n pathRoute: string,\n) => {\n const path = getRoute(pathRoute);\n\n return `\napp.${verb.toLowerCase()}('${path}',...${operationName}Handlers)`;\n};\n\nexport const generateHono: ClientBuilder = (verbOptions, options) => {\n if (options.override.hono.compositeRoute) {\n return {\n implementation: '',\n imports: [],\n };\n }\n\n const routeImplementation = generateHonoRoute(verbOptions, options.pathRoute);\n\n return {\n implementation: routeImplementation ? `${routeImplementation}\\n\\n` : '',\n imports: [\n ...verbOptions.params.flatMap((param) => param.imports),\n ...verbOptions.body.imports,\n ...(verbOptions.queryParams\n ? [\n {\n name: verbOptions.queryParams.schema.name,\n },\n ]\n : []),\n ],\n };\n};\n\n/**\n * getHonoHandlers generates TypeScript code for the given verbs and reports\n * whether the code requires zValidator.\n */\nconst getHonoHandlers = (\n ...opts: Array<{\n handlerName: string;\n contextTypeName: string;\n verbOption: GeneratorVerbOptions;\n validator: boolean | 'hono' | NormalizedMutator;\n }>\n): [\n /** The combined TypeScript handler code snippets. */\n handlerCode: string,\n /** Whether any of the handler code snippets requires importing zValidator. */\n hasZValidator: boolean,\n] =>\n opts.reduce<[string, boolean]>(\n ([code, hasZValidator], opts) => {\n const { handlerName, contextTypeName, verbOption, validator } = opts;\n\n let currentValidator = '';\n\n if (validator) {\n if (verbOption.headers) {\n currentValidator += `zValidator('header', ${verbOption.operationName}Header),\\n`;\n }\n if (verbOption.params.length > 0) {\n currentValidator += `zValidator('param', ${verbOption.operationName}Params),\\n`;\n }\n if (verbOption.queryParams) {\n currentValidator += `zValidator('query', ${verbOption.operationName}QueryParams),\\n`;\n }\n if (verbOption.body.definition) {\n currentValidator += `zValidator('json', ${verbOption.operationName}Body),\\n`;\n }\n if (\n validator !== 'hono' &&\n verbOption.response.originalSchema?.['200']?.content?.[\n 'application/json'\n ]\n ) {\n currentValidator += `zValidator('response', ${verbOption.operationName}Response),\\n`;\n }\n }\n\n code += `\nexport const ${handlerName} = factory.createHandlers(\n${currentValidator}async (c: ${contextTypeName}) => {\n\n },\n);`;\n hasZValidator ||= currentValidator !== '';\n\n return [code, hasZValidator];\n },\n ['', false],\n );\n\nconst getZvalidatorImports = (\n verbOptions: GeneratorVerbOptions[],\n importPath: string,\n isHonoValidator: boolean,\n) => {\n const specifiers = [];\n\n for (const {\n operationName,\n headers,\n params,\n queryParams,\n body,\n response,\n } of verbOptions) {\n if (headers) {\n specifiers.push(`${operationName}Header`);\n }\n\n if (params.length > 0) {\n specifiers.push(`${operationName}Params`);\n }\n\n if (queryParams) {\n specifiers.push(`${operationName}QueryParams`);\n }\n\n if (body.definition) {\n specifiers.push(`${operationName}Body`);\n }\n\n if (\n !isHonoValidator &&\n response.originalSchema?.['200']?.content?.['application/json'] != null\n ) {\n specifiers.push(`${operationName}Response`);\n }\n }\n\n return specifiers.length === 0\n ? ''\n : `import {\\n${specifiers.join(',\\n')}\\n} from '${importPath}'`;\n};\n\nconst getVerbOptionGroupByTag = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n) => {\n return Object.values(verbOptions).reduce<\n Record<string, GeneratorVerbOptions[]>\n >((acc, value) => {\n const tag = value.tags[0];\n if (!acc[tag]) {\n acc[tag] = [];\n }\n acc[tag].push(value);\n return acc;\n }, {});\n};\n\nconst generateHandlerFile = async ({\n verbs,\n path,\n validatorModule,\n zodModule,\n contextModule,\n}: {\n verbs: GeneratorVerbOptions[];\n path: string;\n validatorModule?: string;\n zodModule: string;\n contextModule: string;\n}) => {\n const validator =\n validatorModule === '@hono/zod-validator'\n ? ('hono' as const)\n : validatorModule != null;\n\n const isExist = fs.existsSync(path);\n\n if (isExist) {\n const rawFile = await fs.readFile(path, 'utf8');\n let content = rawFile;\n\n content += Object.values(verbs).reduce((acc, verbOption) => {\n const handlerName = `${verbOption.operationName}Handlers`;\n const contextTypeName = `${pascal(verbOption.operationName)}Context`;\n\n if (!rawFile.includes(handlerName)) {\n acc += getHonoHandlers({\n handlerName,\n contextTypeName,\n verbOption,\n validator,\n })[0];\n }\n\n return acc;\n }, '');\n\n return content;\n }\n\n const [handlerCode, hasZValidator] = getHonoHandlers(\n ...Object.values(verbs).map((verbOption) => ({\n handlerName: `${verbOption.operationName}Handlers`,\n contextTypeName: `${pascal(verbOption.operationName)}Context`,\n verbOption,\n validator,\n })),\n );\n\n const imports = [\"import { createFactory } from 'hono/factory';\"];\n\n if (hasZValidator && validatorModule != null) {\n imports.push(\n `import { zValidator } from '${generateModuleSpecifier(path, validatorModule)}';`,\n );\n }\n\n imports.push(\n `import { ${Object.values(verbs)\n .map((verb) => `${pascal(verb.operationName)}Context`)\n .join(',\\n')} } from '${generateModuleSpecifier(path, contextModule)}';`,\n );\n\n if (hasZValidator) {\n imports.push(\n getZvalidatorImports(\n Object.values(verbs),\n generateModuleSpecifier(path, zodModule),\n validatorModule === '@hono/zod-validator',\n ),\n );\n }\n\n return `${imports.filter((imp) => imp !== '').join('\\n')}\n\nconst factory = createFactory();${handlerCode}`;\n};\n\nconst generateHandlerFiles = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n validatorModule: string,\n) => {\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n // This function _does not control_ where the .zod and .context modules land.\n // That determination is made elsewhere and this function must implement the\n // same conventions.\n\n if (output.override.hono.handlers) {\n // One file per operation in the user-provided directory.\n return Promise.all(\n Object.values(verbOptions).map(async (verbOption) => {\n const tag = kebab(verbOption.tags[0] ?? 'default');\n\n const path = upath.join(\n output.override.hono.handlers ?? '',\n `./${verbOption.operationName}` + extension,\n );\n\n return {\n content: await generateHandlerFile({\n path,\n verbs: [verbOption],\n validatorModule,\n zodModule:\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.zod`)\n : upath.join(dirname, tag, tag + '.zod'),\n contextModule:\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.context`)\n : upath.join(dirname, tag, tag + '.context'),\n }),\n path,\n };\n }),\n );\n }\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n // One file per operation _tag_ under dirname.\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n return Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n const handlerPath =\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.handlers${extension}`)\n : upath.join(dirname, tag, tag + '.handlers' + extension);\n\n return {\n content: await generateHandlerFile({\n path: handlerPath,\n verbs,\n validatorModule,\n zodModule:\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.zod`)\n : upath.join(dirname, tag, tag + '.zod'),\n contextModule:\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.context`)\n : upath.join(dirname, tag, tag + '.context'),\n }),\n path: handlerPath,\n };\n }),\n );\n }\n\n // One file with all operations.\n const handlerPath = upath.join(dirname, `${filename}.handlers${extension}`);\n\n return [\n {\n content: await generateHandlerFile({\n path: handlerPath,\n verbs: Object.values(verbOptions),\n validatorModule,\n zodModule: upath.join(dirname, `${filename}.zod`),\n contextModule: upath.join(dirname, `${filename}.context`),\n }),\n path: handlerPath,\n },\n ];\n};\n\nconst getContext = (verbOption: GeneratorVerbOptions) => {\n let paramType = '';\n if (verbOption.params.length > 0) {\n const params = getParamsInPath(verbOption.pathRoute).map((name) => {\n const param = verbOption.params.find(\n (p) => p.name === sanitize(camel(name), { es5keyword: true }),\n );\n const definition = param?.definition.split(':')[1];\n const required = param?.required ?? false;\n return {\n definition: `${name}${required ? '' : '?'}:${definition}`,\n };\n });\n paramType = `param: {\\n ${params\n .map((property) => property.definition)\n .join(',\\n ')},\\n },`;\n }\n\n const queryType = verbOption.queryParams\n ? `query: ${verbOption.queryParams?.schema.name},`\n : '';\n const bodyType = verbOption.body.definition\n ? `json: ${verbOption.body.definition},`\n : '';\n const hasIn = !!paramType || !!queryType || !!bodyType;\n\n return `export type ${pascal(\n verbOption.operationName,\n )}Context<E extends Env = any> = Context<E, '${getRoute(\n verbOption.pathRoute,\n )}'${\n hasIn\n ? `, { in: { ${paramType}${queryType}${bodyType} }, out: { ${paramType}${queryType}${bodyType} } }`\n : ''\n }>`;\n};\n\nconst getHeader = (\n option: false | ((info: InfoObject) => string | string[]),\n info: InfoObject,\n): string => {\n if (!option) {\n return '';\n }\n\n const header = option(info);\n\n return Array.isArray(header) ? jsDoc({ description: header }) : header;\n};\n\nconst generateContextFile = ({\n path,\n verbs,\n schemaModule,\n}: {\n path: string;\n verbs: GeneratorVerbOptions[];\n schemaModule: string;\n}) => {\n let content = `import type { Context, Env } from 'hono';\\n\\n`;\n\n const contexts = verbs.map((verb) => getContext(verb));\n\n const imps = new Set(\n verbs\n .flatMap((verb) => {\n const imports: GeneratorImport[] = [];\n if (verb.params.length > 0) {\n imports.push(...verb.params.flatMap((param) => param.imports));\n }\n\n if (verb.queryParams) {\n imports.push({\n name: verb.queryParams.schema.name,\n });\n }\n\n if (verb.body.definition) {\n imports.push(...verb.body.imports);\n }\n\n return imports;\n })\n .map((imp) => imp.name)\n .filter((imp) => contexts.some((context) => context.includes(imp))),\n );\n\n if (contexts.some((context) => context.includes('NonReadonly<'))) {\n content += getOrvalGeneratedTypes();\n content += '\\n';\n }\n\n if (imps.size > 0) {\n content += `import type {\\n${[...imps]\n .toSorted()\n .join(\n ',\\n ',\n )}\\n} from '${generateModuleSpecifier(path, schemaModule)}';\\n\\n`;\n }\n\n content += contexts.join('\\n');\n\n return content;\n};\n\nconst generateContextFiles = (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpecs,\n schemaModule: string,\n) => {\n const header = getHeader(\n output.override.header,\n context.specs[context.specKey].info,\n );\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n return Object.entries(groupByTags).map(([tag, verbs]) => {\n const path =\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.context${extension}`)\n : upath.join(dirname, tag, tag + '.context' + extension);\n const code = generateContextFile({\n verbs,\n path,\n schemaModule: schemaModule,\n });\n return { content: `${header}${code}`, path };\n });\n }\n\n const path = upath.join(dirname, `${filename}.context${extension}`);\n const code = generateContextFile({\n verbs: Object.values(verbOptions),\n path,\n schemaModule: schemaModule,\n });\n\n return [\n {\n content: `${header}${code}`,\n path,\n },\n ];\n};\n\nconst generateZodFiles = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpecs,\n) => {\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n const header = getHeader(\n output.override.header,\n context.specs[context.specKey].info,\n );\n\n if (output.mode === 'tags' || output.mode === 'tags-split') {\n const groupByTags = getVerbOptionGroupByTag(verbOptions);\n\n const builderContexts = await Promise.all(\n Object.entries(groupByTags).map(async ([tag, verbs]) => {\n const zods = await Promise.all(\n verbs.map((verbOption) =>\n generateZod(\n verbOption,\n {\n route: verbOption.route,\n pathRoute: verbOption.pathRoute,\n override: output.override,\n context,\n mock: output.mock,\n output: output.target!,\n },\n output.client,\n ),\n ),\n );\n\n if (zods.every((z) => z.implementation === '')) {\n return {\n content: '',\n path: '',\n };\n }\n\n const allMutators = zods.reduce(\n (acc, z) => {\n for (const mutator of z.mutators ?? []) {\n acc[mutator.name] = mutator;\n }\n return acc;\n },\n {} as Record<string, GeneratorMutator>,\n );\n\n const mutatorsImports = generateMutatorImports({\n mutators: Object.values(allMutators),\n });\n\n let content = `${header}import { z as zod } from 'zod';\\n${mutatorsImports}\\n`;\n\n const zodPath =\n output.mode === 'tags'\n ? upath.join(dirname, `${kebab(tag)}.zod${extension}`)\n : upath.join(dirname, tag, tag + '.zod' + extension);\n\n content += zods.map((zod) => zod.implementation).join('\\n');\n\n return {\n content,\n path: zodPath,\n };\n }),\n );\n\n return Promise.all(\n builderContexts.filter((context) => context.content !== ''),\n );\n }\n\n const zods = await Promise.all(\n Object.values(verbOptions).map((verbOption) =>\n generateZod(\n verbOption,\n {\n route: verbOption.route,\n pathRoute: verbOption.pathRoute,\n override: output.override,\n context,\n mock: output.mock,\n output: output.target!,\n },\n output.client,\n ),\n ),\n );\n\n const allMutators = zods.reduce(\n (acc, z) => {\n for (const mutator of z.mutators ?? []) {\n acc[mutator.name] = mutator;\n }\n return acc;\n },\n {} as Record<string, GeneratorMutator>,\n );\n\n const mutatorsImports = generateMutatorImports({\n mutators: Object.values(allMutators),\n });\n\n let content = `${header}import { z as zod } from 'zod';\\n${mutatorsImports}\\n`;\n\n const zodPath = upath.join(dirname, `${filename}.zod${extension}`);\n\n content += zods.map((zod) => zod.implementation).join('\\n');\n\n return [\n {\n content,\n path: zodPath,\n },\n ];\n};\n\nconst generateZvalidator = (\n output: NormalizedOutputOptions,\n context: ContextSpecs,\n) => {\n const header = getHeader(\n output.override.header,\n context.specs[context.specKey].info,\n );\n\n let validatorPath = output.override.hono.validatorOutputPath;\n if (!output.override.hono.validatorOutputPath) {\n const { extension, dirname, filename } = getFileInfo(output.target);\n\n validatorPath = upath.join(dirname, `${filename}.validator${extension}`);\n }\n\n return {\n content: `${header}${ZVALIDATOR_SOURCE}`,\n path: validatorPath,\n };\n};\n\nconst generateCompositeRoutes = async (\n verbOptions: Record<string, GeneratorVerbOptions>,\n output: NormalizedOutputOptions,\n context: ContextSpecs,\n) => {\n const targetInfo = getFileInfo(output.target);\n const compositeRouteInfo = getFileInfo(output.override.hono.compositeRoute);\n\n const header = getHeader(\n output.override.header,\n context.specs[context.specKey].info,\n );\n\n const routes = Object.values(verbOptions)\n .map((verbOption) => {\n return generateHonoRoute(verbOption, verbOption.pathRoute);\n })\n .join(';');\n\n const importHandlers = Object.values(verbOptions);\n\n let ImportHandlersImplementation: string;\n if (output.override.hono.handlers) {\n const handlerFileInfo = getFileInfo(output.override.hono.handlers);\n const operationNames = importHandlers.map(\n (verbOption) => verbOption.operationName,\n );\n\n ImportHandlersImplementation = operationNames\n .map((operationName) => {\n const importHandlerName = `${operationName}Handlers`;\n\n const handlersPath = generateModuleSpecifier(\n compositeRouteInfo.path,\n upath.join(handlerFileInfo.dirname ?? '', `./${operationName}`),\n );\n\n return `import { ${importHandlerName} } from '${handlersPath}';`;\n })\n .join('\\n');\n } else {\n const tags = importHandlers.map((verbOption) =>\n kebab(verbOption.tags[0] ?? 'default'),\n );\n const uniqueTags = tags.filter((t, i) => tags.indexOf(t) === i);\n\n ImportHandlersImplementation = uniqueTags\n .map((tag) => {\n const importHandlerNames = importHandlers\n .filter((verbOption) => verbOption.tags[0] === tag)\n .map((verbOption) => ` ${verbOption.operationName}Handlers`)\n .join(`, \\n`);\n\n const handlersPath = generateModuleSpecifier(\n compositeRouteInfo.path,\n upath.join(targetInfo.dirname ?? '', tag),\n );\n\n return `import {\\n${importHandlerNames}\\n} from '${handlersPath}/${tag}.handlers';`;\n })\n .join('\\n');\n }\n\n const honoImport = `import { Hono } from 'hono';`;\n const honoInitialization = `\\nconst app = new Hono()`;\n const honoAppExport = `\\nexport default app`;\n\n const content = `${header}${honoImport}\n${ImportHandlersImplementation}\n${honoInitialization}\n${routes}\n${honoAppExport}\n`;\n\n return [\n {\n content,\n path: output.override.hono.compositeRoute || '',\n },\n ];\n};\n\nexport const generateExtraFiles: ClientExtraFilesBuilder = async (\n verbOptions,\n output,\n context,\n) => {\n const { path, pathWithoutExtension } = getFileInfo(output.target);\n const validator = generateZvalidator(output, context);\n let schemaModule: string;\n\n if (output.schemas != null) {\n schemaModule = getFileInfo(output.schemas).dirname;\n } else if (output.mode === 'single') {\n schemaModule = path;\n } else {\n schemaModule = `${pathWithoutExtension}.schemas`;\n }\n\n const [handlers, contexts, zods, compositeRoutes] = await Promise.all([\n generateHandlerFiles(verbOptions, output, validator.path),\n generateContextFiles(verbOptions, output, context, schemaModule),\n generateZodFiles(verbOptions, output, context),\n output.override.hono.compositeRoute\n ? generateCompositeRoutes(verbOptions, output, context)\n : [],\n ]);\n\n return [\n ...handlers,\n ...contexts,\n ...zods,\n ...(output.override.hono.validator &&\n output.override.hono.validator !== 'hono'\n ? [validator]\n : []),\n ...compositeRoutes,\n ];\n};\n\nconst honoClientBuilder: ClientGeneratorsBuilder = {\n client: generateHono,\n dependencies: getHonoDependencies,\n header: getHonoHeader,\n footer: getHonoFooter,\n extraFiles: generateExtraFiles,\n};\n\nexport const builder = () => () => honoClientBuilder;\n\nexport default builder;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// based on https://github.com/honojs/middleware/blob/main/packages/zod-validator/src/index.ts
|
|
2
|
+
import type { ZodSafeParseResult as ZodSafeParseResult$1 } from 'zod/v4'
|
|
3
|
+
import type { Context, Env, Input, MiddlewareHandler, TypedResponse, ValidationTargets } from 'hono'
|
|
4
|
+
import { zValidator as zValidatorBase } from '@hono/zod-validator'
|
|
5
|
+
import * as v3 from 'zod/v3'
|
|
6
|
+
import * as v4 from 'zod/v4/core'
|
|
7
|
+
|
|
8
|
+
type Awaitable<T> = T | Promise<T>
|
|
9
|
+
type HasUndefined<T> = undefined extends T ? true : false
|
|
10
|
+
|
|
11
|
+
type ZodSchema = v3.ZodType | v4.$ZodType
|
|
12
|
+
type ZodError<T extends ZodSchema> = T extends v4.$ZodType ? v4.$ZodError<v4.output<T>> : v3.ZodError
|
|
13
|
+
type ZodSafeParseResult<T, T2, T3 extends ZodSchema> = T3 extends v4.$ZodType ? ZodSafeParseResult$1<T> : v3.SafeParseReturnType<T, T2>
|
|
14
|
+
type zInput<T> = T extends v3.ZodType ? v3.input<T> : T extends v4.$ZodType ? v4.input<T> : never
|
|
15
|
+
type zOutput<T> = T extends v3.ZodType ? v3.output<T> : T extends v4.$ZodType ? v4.output<T> : never
|
|
16
|
+
type zInfer<T> = T extends v3.ZodType ? v3.infer<T> : T extends v4.$ZodType ? v4.infer<T> : never
|
|
17
|
+
type Hook<T, E extends Env, P extends string, Target extends keyof ValidationTargetsWithResponse = keyof ValidationTargetsWithResponse, O = {}, Schema extends ZodSchema = any> = (result: ({
|
|
18
|
+
success: true
|
|
19
|
+
data: T
|
|
20
|
+
} | {
|
|
21
|
+
success: false
|
|
22
|
+
error: ZodError<Schema>
|
|
23
|
+
data: T
|
|
24
|
+
}) & {
|
|
25
|
+
target: Target
|
|
26
|
+
}, c: Context<E, P>) => Awaitable<Response | void | TypedResponse<O>>
|
|
27
|
+
|
|
28
|
+
type ValidationTargetsWithResponse = ValidationTargets & { response: any }
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* zValidator wraps `zValidator` from `@hono/zod-validator` and extends it to support response validation. It forwards
|
|
32
|
+
* query parameter, path parameter, and request body validation to `@hono/zod-validator`.
|
|
33
|
+
*/
|
|
34
|
+
export const zValidator =
|
|
35
|
+
<
|
|
36
|
+
T extends ZodSchema,
|
|
37
|
+
Target extends keyof ValidationTargetsWithResponse,
|
|
38
|
+
E extends Env,
|
|
39
|
+
P extends string,
|
|
40
|
+
In = zInput<T>,
|
|
41
|
+
Out = zOutput<T>,
|
|
42
|
+
I extends Input = {
|
|
43
|
+
in: HasUndefined<In> extends true
|
|
44
|
+
? {
|
|
45
|
+
[K in Target]?: In extends ValidationTargetsWithResponse[K]
|
|
46
|
+
? In
|
|
47
|
+
: {
|
|
48
|
+
[K2 in keyof In]?: In[K2] extends ValidationTargetsWithResponse[K][K2]
|
|
49
|
+
? In[K2]
|
|
50
|
+
: ValidationTargetsWithResponse[K][K2]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
: {
|
|
54
|
+
[K in Target]: In extends ValidationTargetsWithResponse[K]
|
|
55
|
+
? In
|
|
56
|
+
: {
|
|
57
|
+
[K2 in keyof In]: In[K2] extends ValidationTargetsWithResponse[K][K2]
|
|
58
|
+
? In[K2]
|
|
59
|
+
: ValidationTargetsWithResponse[K][K2]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
out: { [K in Target]: Out }
|
|
63
|
+
},
|
|
64
|
+
V extends I = I,
|
|
65
|
+
InferredValue = zInfer<T>
|
|
66
|
+
> (
|
|
67
|
+
target: Target,
|
|
68
|
+
schema: T,
|
|
69
|
+
hook?: Hook<InferredValue, E, P, Target, {}, T>
|
|
70
|
+
): MiddlewareHandler<E, P, V> =>
|
|
71
|
+
async (c, next) => {
|
|
72
|
+
if (target !== 'response'){
|
|
73
|
+
return zValidatorBase<
|
|
74
|
+
T,
|
|
75
|
+
keyof ValidationTargets,
|
|
76
|
+
E,
|
|
77
|
+
P,
|
|
78
|
+
In,
|
|
79
|
+
Out,
|
|
80
|
+
I,
|
|
81
|
+
V,
|
|
82
|
+
InferredValue
|
|
83
|
+
>(
|
|
84
|
+
target,
|
|
85
|
+
schema,
|
|
86
|
+
hook as Hook<InferredValue, E, P, keyof ValidationTargets, {}, T>
|
|
87
|
+
)(c, next)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
await next()
|
|
91
|
+
|
|
92
|
+
if (
|
|
93
|
+
c.res.status !== 200 ||
|
|
94
|
+
!c.res.headers.get('Content-Type')?.includes('application/json')
|
|
95
|
+
) {
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let value: unknown
|
|
100
|
+
try {
|
|
101
|
+
value = await c.res.json()
|
|
102
|
+
} catch {
|
|
103
|
+
const message = 'Malformed JSON in response'
|
|
104
|
+
c.res = new Response(message, { status: 400 })
|
|
105
|
+
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const { success, data, error } = await (schema as v3.ZodType).safeParseAsync(value) as ZodSafeParseResult<InferredValue, Out, T>
|
|
110
|
+
|
|
111
|
+
if (hook) {
|
|
112
|
+
const hookResult = await hook({
|
|
113
|
+
target, success,
|
|
114
|
+
data: data as InferredValue,
|
|
115
|
+
error: error as ZodError<T>
|
|
116
|
+
}, c)
|
|
117
|
+
|
|
118
|
+
if (typeof hookResult === 'object' && hookResult != null) {
|
|
119
|
+
if (hookResult instanceof Response) {
|
|
120
|
+
c.res = new Response(hookResult.body, hookResult)
|
|
121
|
+
} else if ('response' in hookResult && hookResult.response instanceof Response) {
|
|
122
|
+
c.res = new Response(hookResult.response.body, hookResult.response)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!success) {
|
|
128
|
+
c.res = new Response(JSON.stringify({ success, data, error }), {
|
|
129
|
+
status: 400,
|
|
130
|
+
headers: {
|
|
131
|
+
'Content-Type': 'application/json'
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
} else {
|
|
135
|
+
c.res = new Response(JSON.stringify(data), c.res)
|
|
136
|
+
}
|
|
137
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orval/hono",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.15.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -15,23 +15,24 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "tsdown --config-loader unconfig",
|
|
17
17
|
"dev": "tsdown --config-loader unconfig --watch src",
|
|
18
|
-
"lint": "eslint .",
|
|
18
|
+
"lint": "tsc --noEmit src/zValidator.ts && eslint .",
|
|
19
19
|
"clean": "rimraf .turbo dist",
|
|
20
20
|
"nuke": "rimraf .turbo dist node_modules"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@orval/core": "7.
|
|
24
|
-
"@orval/zod": "7.
|
|
25
|
-
"fs-extra": "^11.3.
|
|
23
|
+
"@orval/core": "7.15.0",
|
|
24
|
+
"@orval/zod": "7.15.0",
|
|
25
|
+
"fs-extra": "^11.3.2",
|
|
26
26
|
"lodash.uniq": "^4.5.0",
|
|
27
27
|
"openapi3-ts": "4.5.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
+
"@hono/zod-validator": "^0.7.4",
|
|
30
31
|
"@types/fs-extra": "^11.0.4",
|
|
31
32
|
"@types/lodash.uniq": "^4.5.9",
|
|
32
|
-
"eslint": "^9.
|
|
33
|
+
"eslint": "^9.38.0",
|
|
33
34
|
"rimraf": "^6.0.1",
|
|
34
|
-
"tsdown": "^0.15.
|
|
35
|
-
"typescript": "^5.9.
|
|
35
|
+
"tsdown": "^0.15.8",
|
|
36
|
+
"typescript": "^5.9.3"
|
|
36
37
|
}
|
|
37
38
|
}
|