@orpc/openapi 0.0.0-next.eb37cbe → 0.0.0-next.ed15210
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/chunk-7MA7YRRY.js +25 -0
- package/dist/chunk-BUMQYADN.js +653 -0
- package/dist/{chunk-KNYXLM77.js → chunk-DSYVLQK3.js} +3 -15
- package/dist/fetch.js +19 -579
- package/dist/hono.js +34 -0
- package/dist/index.js +291 -103
- package/dist/next.js +34 -0
- package/dist/node.js +46 -0
- package/dist/src/{fetch → adapters/fetch}/index.d.ts +2 -2
- package/dist/src/adapters/fetch/input-structure-compact.d.ts +6 -0
- package/dist/src/{fetch/input-builder-full.d.ts → adapters/fetch/input-structure-detailed.d.ts} +3 -3
- package/dist/src/{fetch → adapters/fetch}/openapi-handler.d.ts +15 -13
- package/dist/src/{fetch → adapters/fetch}/openapi-payload-codec.d.ts +2 -2
- package/dist/src/adapters/hono/index.d.ts +2 -0
- package/dist/src/adapters/next/index.d.ts +2 -0
- package/dist/src/adapters/node/index.d.ts +5 -0
- package/dist/src/adapters/node/openapi-handler-server.d.ts +7 -0
- package/dist/src/adapters/node/openapi-handler-serverless.d.ts +7 -0
- package/dist/src/adapters/node/openapi-handler.d.ts +11 -0
- package/dist/src/adapters/node/types.d.ts +2 -0
- package/dist/src/openapi-error.d.ts +3 -0
- package/dist/src/openapi-generator.d.ts +24 -8
- package/dist/src/openapi-input-structure-parser.d.ts +22 -0
- package/dist/src/openapi-output-structure-parser.d.ts +18 -0
- package/dist/src/openapi-parameters-builder.d.ts +3 -0
- package/dist/src/schema.d.ts +1 -1
- package/dist/src/utils.d.ts +3 -3
- package/package.json +21 -6
- package/dist/src/fetch/input-builder-simple.d.ts +0 -6
- /package/dist/src/{fetch → adapters/fetch}/bracket-notation.d.ts +0 -0
- /package/dist/src/{fetch → adapters/fetch}/openapi-handler-server.d.ts +0 -0
- /package/dist/src/{fetch → adapters/fetch}/openapi-handler-serverless.d.ts +0 -0
- /package/dist/src/{fetch → adapters/fetch}/openapi-procedure-matcher.d.ts +0 -0
- /package/dist/src/{fetch → adapters/fetch}/schema-coercer.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
forEachAllContractProcedure,
|
|
4
4
|
forEachContractProcedure,
|
|
5
5
|
standardizeHTTPPath
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DSYVLQK3.js";
|
|
7
7
|
|
|
8
8
|
// src/openapi.ts
|
|
9
9
|
import { OpenApiBuilder } from "openapi3-ts/oas31";
|
|
@@ -35,8 +35,156 @@ var OpenAPIContentBuilder = class {
|
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
// src/openapi-generator.ts
|
|
39
|
+
import { fallbackContractConfig as fallbackContractConfig2, fallbackORPCErrorStatus } from "@orpc/contract";
|
|
40
|
+
import { group } from "@orpc/shared";
|
|
41
|
+
|
|
42
|
+
// src/openapi-error.ts
|
|
43
|
+
var OpenAPIError = class extends Error {
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// src/openapi-input-structure-parser.ts
|
|
47
|
+
import { fallbackContractConfig } from "@orpc/contract";
|
|
48
|
+
var OpenAPIInputStructureParser = class {
|
|
49
|
+
constructor(schemaConverter, schemaUtils, pathParser) {
|
|
50
|
+
this.schemaConverter = schemaConverter;
|
|
51
|
+
this.schemaUtils = schemaUtils;
|
|
52
|
+
this.pathParser = pathParser;
|
|
53
|
+
}
|
|
54
|
+
parse(contract, structure) {
|
|
55
|
+
const inputSchema = this.schemaConverter.convert(contract["~orpc"].InputSchema, { strategy: "input" });
|
|
56
|
+
const method = fallbackContractConfig("defaultMethod", contract["~orpc"].route?.method);
|
|
57
|
+
const httpPath = contract["~orpc"].route?.path;
|
|
58
|
+
if (this.schemaUtils.isAnySchema(inputSchema)) {
|
|
59
|
+
return {
|
|
60
|
+
paramsSchema: void 0,
|
|
61
|
+
querySchema: void 0,
|
|
62
|
+
headersSchema: void 0,
|
|
63
|
+
bodySchema: void 0
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (structure === "detailed") {
|
|
67
|
+
return this.parseDetailedSchema(inputSchema);
|
|
68
|
+
} else {
|
|
69
|
+
return this.parseCompactSchema(inputSchema, method, httpPath);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
parseDetailedSchema(inputSchema) {
|
|
73
|
+
if (!this.schemaUtils.isObjectSchema(inputSchema)) {
|
|
74
|
+
throw new OpenAPIError(`When input structure is 'detailed', input schema must be an object.`);
|
|
75
|
+
}
|
|
76
|
+
if (inputSchema.properties && Object.keys(inputSchema.properties).some((key) => !["params", "query", "headers", "body"].includes(key))) {
|
|
77
|
+
throw new OpenAPIError(`When input structure is 'detailed', input schema must be only can contain 'params', 'query', 'headers' and 'body' properties.`);
|
|
78
|
+
}
|
|
79
|
+
let paramsSchema = inputSchema.properties?.params;
|
|
80
|
+
let querySchema = inputSchema.properties?.query;
|
|
81
|
+
let headersSchema = inputSchema.properties?.headers;
|
|
82
|
+
const bodySchema = inputSchema.properties?.body;
|
|
83
|
+
if (paramsSchema !== void 0 && this.schemaUtils.isAnySchema(paramsSchema)) {
|
|
84
|
+
paramsSchema = void 0;
|
|
85
|
+
}
|
|
86
|
+
if (paramsSchema !== void 0 && !this.schemaUtils.isObjectSchema(paramsSchema)) {
|
|
87
|
+
throw new OpenAPIError(`When input structure is 'detailed', params schema in input schema must be an object.`);
|
|
88
|
+
}
|
|
89
|
+
if (querySchema !== void 0 && this.schemaUtils.isAnySchema(querySchema)) {
|
|
90
|
+
querySchema = void 0;
|
|
91
|
+
}
|
|
92
|
+
if (querySchema !== void 0 && !this.schemaUtils.isObjectSchema(querySchema)) {
|
|
93
|
+
throw new OpenAPIError(`When input structure is 'detailed', query schema in input schema must be an object.`);
|
|
94
|
+
}
|
|
95
|
+
if (headersSchema !== void 0 && this.schemaUtils.isAnySchema(headersSchema)) {
|
|
96
|
+
headersSchema = void 0;
|
|
97
|
+
}
|
|
98
|
+
if (headersSchema !== void 0 && !this.schemaUtils.isObjectSchema(headersSchema)) {
|
|
99
|
+
throw new OpenAPIError(`When input structure is 'detailed', headers schema in input schema must be an object.`);
|
|
100
|
+
}
|
|
101
|
+
return { paramsSchema, querySchema, headersSchema, bodySchema };
|
|
102
|
+
}
|
|
103
|
+
parseCompactSchema(inputSchema, method, httpPath) {
|
|
104
|
+
const dynamic = httpPath ? this.pathParser.parseDynamicParams(httpPath) : [];
|
|
105
|
+
if (dynamic.length === 0) {
|
|
106
|
+
if (method === "GET") {
|
|
107
|
+
let querySchema = inputSchema;
|
|
108
|
+
if (querySchema !== void 0 && this.schemaUtils.isAnySchema(querySchema)) {
|
|
109
|
+
querySchema = void 0;
|
|
110
|
+
}
|
|
111
|
+
if (querySchema !== void 0 && !this.schemaUtils.isObjectSchema(querySchema)) {
|
|
112
|
+
throw new OpenAPIError(`When input structure is 'compact' and method is 'GET', input schema must be an object.`);
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
paramsSchema: void 0,
|
|
116
|
+
querySchema,
|
|
117
|
+
headersSchema: void 0,
|
|
118
|
+
bodySchema: void 0
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
paramsSchema: void 0,
|
|
123
|
+
querySchema: void 0,
|
|
124
|
+
headersSchema: void 0,
|
|
125
|
+
bodySchema: inputSchema
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (!this.schemaUtils.isObjectSchema(inputSchema)) {
|
|
129
|
+
throw new OpenAPIError(`When input structure is 'compact' and path has dynamic parameters, input schema must be an object.`);
|
|
130
|
+
}
|
|
131
|
+
const [params, rest] = this.schemaUtils.separateObjectSchema(inputSchema, dynamic.map((v) => v.name));
|
|
132
|
+
return {
|
|
133
|
+
paramsSchema: params,
|
|
134
|
+
querySchema: method === "GET" ? rest : void 0,
|
|
135
|
+
headersSchema: void 0,
|
|
136
|
+
bodySchema: method !== "GET" ? rest : void 0
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// src/openapi-output-structure-parser.ts
|
|
142
|
+
var OpenAPIOutputStructureParser = class {
|
|
143
|
+
constructor(schemaConverter, schemaUtils) {
|
|
144
|
+
this.schemaConverter = schemaConverter;
|
|
145
|
+
this.schemaUtils = schemaUtils;
|
|
146
|
+
}
|
|
147
|
+
parse(contract, structure) {
|
|
148
|
+
const outputSchema = this.schemaConverter.convert(contract["~orpc"].OutputSchema, { strategy: "output" });
|
|
149
|
+
if (this.schemaUtils.isAnySchema(outputSchema)) {
|
|
150
|
+
return {
|
|
151
|
+
headersSchema: void 0,
|
|
152
|
+
bodySchema: void 0
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (structure === "detailed") {
|
|
156
|
+
return this.parseDetailedSchema(outputSchema);
|
|
157
|
+
} else {
|
|
158
|
+
return this.parseCompactSchema(outputSchema);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
parseDetailedSchema(outputSchema) {
|
|
162
|
+
if (!this.schemaUtils.isObjectSchema(outputSchema)) {
|
|
163
|
+
throw new OpenAPIError(`When output structure is 'detailed', output schema must be an object.`);
|
|
164
|
+
}
|
|
165
|
+
if (outputSchema.properties && Object.keys(outputSchema.properties).some((key) => !["headers", "body"].includes(key))) {
|
|
166
|
+
throw new OpenAPIError(`When output structure is 'detailed', output schema must be only can contain 'headers' and 'body' properties.`);
|
|
167
|
+
}
|
|
168
|
+
let headersSchema = outputSchema.properties?.headers;
|
|
169
|
+
const bodySchema = outputSchema.properties?.body;
|
|
170
|
+
if (headersSchema !== void 0 && this.schemaUtils.isAnySchema(headersSchema)) {
|
|
171
|
+
headersSchema = void 0;
|
|
172
|
+
}
|
|
173
|
+
if (headersSchema !== void 0 && !this.schemaUtils.isObjectSchema(headersSchema)) {
|
|
174
|
+
throw new OpenAPIError(`When output structure is 'detailed', headers schema in output schema must be an object.`);
|
|
175
|
+
}
|
|
176
|
+
return { headersSchema, bodySchema };
|
|
177
|
+
}
|
|
178
|
+
parseCompactSchema(outputSchema) {
|
|
179
|
+
return {
|
|
180
|
+
headersSchema: void 0,
|
|
181
|
+
bodySchema: outputSchema
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
38
186
|
// src/openapi-parameters-builder.ts
|
|
39
|
-
import { get, isPlainObject } from "@orpc/shared";
|
|
187
|
+
import { get, isPlainObject, omit } from "@orpc/shared";
|
|
40
188
|
var OpenAPIParametersBuilder = class {
|
|
41
189
|
build(paramIn, jsonSchema, options) {
|
|
42
190
|
const parameters = [];
|
|
@@ -63,6 +211,14 @@ var OpenAPIParametersBuilder = class {
|
|
|
63
211
|
}
|
|
64
212
|
return parameters;
|
|
65
213
|
}
|
|
214
|
+
buildHeadersObject(jsonSchema, options) {
|
|
215
|
+
const parameters = this.build("header", jsonSchema, options);
|
|
216
|
+
const headersObject = {};
|
|
217
|
+
for (const param of parameters) {
|
|
218
|
+
headersObject[param.name] = omit(param, ["name", "in"]);
|
|
219
|
+
}
|
|
220
|
+
return headersObject;
|
|
221
|
+
}
|
|
66
222
|
};
|
|
67
223
|
|
|
68
224
|
// src/openapi-path-parser.ts
|
|
@@ -138,14 +294,14 @@ var SchemaUtils = class {
|
|
|
138
294
|
return typeof schema === "object" && schema.type === "object";
|
|
139
295
|
}
|
|
140
296
|
isAnySchema(schema) {
|
|
141
|
-
return schema === true || Object.keys(schema).length === 0;
|
|
297
|
+
return schema === true || Object.keys(schema).filter((key) => !NON_LOGIC_KEYWORDS.includes(key)).length === 0;
|
|
142
298
|
}
|
|
143
299
|
isUndefinableSchema(schema) {
|
|
144
300
|
const [matches] = this.filterSchemaBranches(schema, (schema2) => {
|
|
145
301
|
if (typeof schema2 === "boolean") {
|
|
146
302
|
return schema2;
|
|
147
303
|
}
|
|
148
|
-
return Object.keys(schema2).length === 0;
|
|
304
|
+
return Object.keys(schema2).filter((key) => !NON_LOGIC_KEYWORDS.includes(key)).length === 0;
|
|
149
305
|
});
|
|
150
306
|
return matches.length > 0;
|
|
151
307
|
}
|
|
@@ -218,21 +374,32 @@ var SchemaUtils = class {
|
|
|
218
374
|
|
|
219
375
|
// src/openapi-generator.ts
|
|
220
376
|
var OpenAPIGenerator = class {
|
|
377
|
+
contentBuilder;
|
|
378
|
+
parametersBuilder;
|
|
379
|
+
schemaConverter;
|
|
380
|
+
schemaUtils;
|
|
381
|
+
jsonSerializer;
|
|
382
|
+
pathParser;
|
|
383
|
+
inputStructureParser;
|
|
384
|
+
outputStructureParser;
|
|
385
|
+
errorHandlerStrategy;
|
|
386
|
+
ignoreUndefinedPathProcedures;
|
|
387
|
+
considerMissingTagDefinitionAsError;
|
|
388
|
+
strictErrorResponses;
|
|
221
389
|
constructor(options) {
|
|
222
|
-
this.options = options;
|
|
223
390
|
this.parametersBuilder = options?.parametersBuilder ?? new OpenAPIParametersBuilder();
|
|
224
391
|
this.schemaConverter = new CompositeSchemaConverter(options?.schemaConverters ?? []);
|
|
225
392
|
this.schemaUtils = options?.schemaUtils ?? new SchemaUtils();
|
|
226
393
|
this.jsonSerializer = options?.jsonSerializer ?? new JSONSerializer();
|
|
227
394
|
this.contentBuilder = options?.contentBuilder ?? new OpenAPIContentBuilder(this.schemaUtils);
|
|
228
395
|
this.pathParser = new OpenAPIPathParser();
|
|
396
|
+
this.inputStructureParser = options?.inputStructureParser ?? new OpenAPIInputStructureParser(this.schemaConverter, this.schemaUtils, this.pathParser);
|
|
397
|
+
this.outputStructureParser = options?.outputStructureParser ?? new OpenAPIOutputStructureParser(this.schemaConverter, this.schemaUtils);
|
|
398
|
+
this.errorHandlerStrategy = options?.errorHandlerStrategy ?? "throw";
|
|
399
|
+
this.ignoreUndefinedPathProcedures = options?.ignoreUndefinedPathProcedures ?? false;
|
|
400
|
+
this.considerMissingTagDefinitionAsError = options?.considerMissingTagDefinitionAsError ?? false;
|
|
401
|
+
this.strictErrorResponses = options?.strictErrorResponses ?? true;
|
|
229
402
|
}
|
|
230
|
-
contentBuilder;
|
|
231
|
-
parametersBuilder;
|
|
232
|
-
schemaConverter;
|
|
233
|
-
schemaUtils;
|
|
234
|
-
jsonSerializer;
|
|
235
|
-
pathParser;
|
|
236
403
|
async generate(router, doc) {
|
|
237
404
|
const builder = new OpenApiBuilder({
|
|
238
405
|
...doc,
|
|
@@ -240,108 +407,129 @@ var OpenAPIGenerator = class {
|
|
|
240
407
|
});
|
|
241
408
|
const rootTags = doc.tags?.map((tag) => tag.name) ?? [];
|
|
242
409
|
await forEachAllContractProcedure(router, ({ contract, path }) => {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const method = def.route?.method ?? "POST";
|
|
248
|
-
const httpPath = def.route?.path ? standardizeHTTPPath(def.route?.path) : `/${path.map(encodeURIComponent).join("/")}`;
|
|
249
|
-
let inputSchema = this.schemaConverter.convert(def.InputSchema, { strategy: "input" });
|
|
250
|
-
const outputSchema = this.schemaConverter.convert(def.OutputSchema, { strategy: "output" });
|
|
251
|
-
const params = (() => {
|
|
252
|
-
const dynamic = this.pathParser.parseDynamicParams(httpPath);
|
|
253
|
-
if (!dynamic.length) {
|
|
254
|
-
return void 0;
|
|
255
|
-
}
|
|
256
|
-
if (this.schemaUtils.isAnySchema(inputSchema)) {
|
|
257
|
-
return void 0;
|
|
258
|
-
}
|
|
259
|
-
if (!this.schemaUtils.isObjectSchema(inputSchema)) {
|
|
260
|
-
this.handleError(
|
|
261
|
-
new Error(
|
|
262
|
-
`When path has parameters, input schema must be an object [${path.join(".")}]`
|
|
263
|
-
)
|
|
264
|
-
);
|
|
265
|
-
return void 0;
|
|
410
|
+
try {
|
|
411
|
+
const def = contract["~orpc"];
|
|
412
|
+
if (this.ignoreUndefinedPathProcedures && def.route?.path === void 0) {
|
|
413
|
+
return;
|
|
266
414
|
}
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
415
|
+
const method = fallbackContractConfig2("defaultMethod", def.route?.method);
|
|
416
|
+
const httpPath = def.route?.path ? standardizeHTTPPath(def.route?.path) : `/${path.map(encodeURIComponent).join("/")}`;
|
|
417
|
+
const inputStructure = fallbackContractConfig2("defaultInputStructure", def.route?.inputStructure);
|
|
418
|
+
const outputStructure = fallbackContractConfig2("defaultOutputStructure", def.route?.outputStructure);
|
|
419
|
+
const { paramsSchema, querySchema, headersSchema, bodySchema } = this.inputStructureParser.parse(contract, inputStructure);
|
|
420
|
+
const { headersSchema: resHeadersSchema, bodySchema: resBodySchema } = this.outputStructureParser.parse(contract, outputStructure);
|
|
421
|
+
const params = paramsSchema ? this.parametersBuilder.build("path", paramsSchema, {
|
|
271
422
|
required: true
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
423
|
+
}) : [];
|
|
424
|
+
const query = querySchema ? this.parametersBuilder.build("query", querySchema) : [];
|
|
425
|
+
const headers = headersSchema ? this.parametersBuilder.build("header", headersSchema) : [];
|
|
426
|
+
const parameters = [...params, ...query, ...headers];
|
|
427
|
+
const requestBody = bodySchema !== void 0 ? {
|
|
428
|
+
required: this.schemaUtils.isUndefinableSchema(bodySchema),
|
|
429
|
+
content: this.contentBuilder.build(bodySchema)
|
|
430
|
+
} : void 0;
|
|
431
|
+
const responses = {};
|
|
432
|
+
responses[fallbackContractConfig2("defaultSuccessStatus", def.route?.successStatus)] = {
|
|
433
|
+
description: fallbackContractConfig2("defaultSuccessDescription", def.route?.successDescription),
|
|
434
|
+
content: resBodySchema !== void 0 ? this.contentBuilder.build(resBodySchema, {
|
|
435
|
+
example: def.outputExample
|
|
436
|
+
}) : void 0,
|
|
437
|
+
headers: resHeadersSchema !== void 0 ? this.parametersBuilder.buildHeadersObject(resHeadersSchema, {
|
|
438
|
+
example: def.outputExample
|
|
439
|
+
}) : void 0
|
|
440
|
+
};
|
|
441
|
+
const errors = group(Object.entries(def.errorMap ?? {}).filter(([_, config]) => config).map(([code, config]) => ({
|
|
442
|
+
...config,
|
|
443
|
+
code,
|
|
444
|
+
status: fallbackORPCErrorStatus(code, config?.status)
|
|
445
|
+
})), (error) => error.status);
|
|
446
|
+
for (const status in errors) {
|
|
447
|
+
const configs = errors[status];
|
|
448
|
+
if (!configs || configs.length === 0) {
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
const schemas = configs.map(({ data, code, message }) => {
|
|
452
|
+
const json = {
|
|
453
|
+
type: "object",
|
|
454
|
+
properties: {
|
|
455
|
+
defined: { const: true },
|
|
456
|
+
code: { const: code },
|
|
457
|
+
status: { const: Number(status) },
|
|
458
|
+
message: { type: "string", default: message },
|
|
459
|
+
data: {}
|
|
460
|
+
},
|
|
461
|
+
required: ["defined", "code", "status", "message"]
|
|
462
|
+
};
|
|
463
|
+
if (data) {
|
|
464
|
+
const dataJson = this.schemaConverter.convert(data, { strategy: "output" });
|
|
465
|
+
json.properties.data = dataJson;
|
|
466
|
+
if (!this.schemaUtils.isUndefinableSchema(dataJson)) {
|
|
467
|
+
json.required.push("data");
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return json;
|
|
471
|
+
});
|
|
472
|
+
if (this.strictErrorResponses) {
|
|
473
|
+
schemas.push({
|
|
474
|
+
type: "object",
|
|
475
|
+
properties: {
|
|
476
|
+
defined: { const: false },
|
|
477
|
+
code: { type: "string" },
|
|
478
|
+
status: { type: "number" },
|
|
479
|
+
message: { type: "string" },
|
|
480
|
+
data: {}
|
|
481
|
+
},
|
|
482
|
+
required: ["defined", "code", "status", "message"]
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
const contentSchema = schemas.length === 1 ? schemas[0] : {
|
|
486
|
+
oneOf: schemas
|
|
487
|
+
};
|
|
488
|
+
responses[status] = {
|
|
489
|
+
description: status,
|
|
490
|
+
content: this.contentBuilder.build(contentSchema)
|
|
491
|
+
};
|
|
288
492
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
return void 0;
|
|
493
|
+
if (this.considerMissingTagDefinitionAsError && def.route?.tags) {
|
|
494
|
+
const missingTag = def.route?.tags.find((tag) => !rootTags.includes(tag));
|
|
495
|
+
if (missingTag !== void 0) {
|
|
496
|
+
throw new OpenAPIError(
|
|
497
|
+
`Tag "${missingTag}" is missing definition. Please define it in OpenAPI root tags object`
|
|
498
|
+
);
|
|
499
|
+
}
|
|
297
500
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
501
|
+
const operation = {
|
|
502
|
+
summary: def.route?.summary,
|
|
503
|
+
description: def.route?.description,
|
|
504
|
+
deprecated: def.route?.deprecated,
|
|
505
|
+
tags: def.route?.tags ? [...def.route.tags] : void 0,
|
|
506
|
+
operationId: path.join("."),
|
|
507
|
+
parameters: parameters.length ? parameters : void 0,
|
|
508
|
+
requestBody,
|
|
509
|
+
responses
|
|
303
510
|
};
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
)
|
|
318
|
-
|
|
511
|
+
builder.addPath(httpPath, {
|
|
512
|
+
[method.toLocaleLowerCase()]: operation
|
|
513
|
+
});
|
|
514
|
+
} catch (e) {
|
|
515
|
+
if (e instanceof OpenAPIError) {
|
|
516
|
+
const error = new OpenAPIError(`
|
|
517
|
+
Generate OpenAPI Error: ${e.message}
|
|
518
|
+
Happened at path: ${path.join(".")}
|
|
519
|
+
`, { cause: e });
|
|
520
|
+
if (this.errorHandlerStrategy === "throw") {
|
|
521
|
+
throw error;
|
|
522
|
+
}
|
|
523
|
+
if (this.errorHandlerStrategy === "log") {
|
|
524
|
+
console.error(error);
|
|
525
|
+
}
|
|
526
|
+
} else {
|
|
527
|
+
throw e;
|
|
319
528
|
}
|
|
320
529
|
}
|
|
321
|
-
const operation = {
|
|
322
|
-
summary: def.route?.summary,
|
|
323
|
-
description: def.route?.description,
|
|
324
|
-
deprecated: def.route?.deprecated,
|
|
325
|
-
tags: def.route?.tags ? [...def.route.tags] : void 0,
|
|
326
|
-
operationId: path.join("."),
|
|
327
|
-
parameters: parameters.length ? parameters : void 0,
|
|
328
|
-
requestBody,
|
|
329
|
-
responses: {
|
|
330
|
-
[def.route?.successStatus ?? 200]: successResponse
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
builder.addPath(httpPath, {
|
|
334
|
-
[method.toLocaleLowerCase()]: operation
|
|
335
|
-
});
|
|
336
530
|
});
|
|
337
531
|
return this.jsonSerializer.serialize(builder.getSpec());
|
|
338
532
|
}
|
|
339
|
-
handleError(error) {
|
|
340
|
-
if (this.options?.throwOnError) {
|
|
341
|
-
throw error;
|
|
342
|
-
}
|
|
343
|
-
console.error(error);
|
|
344
|
-
}
|
|
345
533
|
};
|
|
346
534
|
export {
|
|
347
535
|
CompositeSchemaConverter,
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OpenAPIServerHandler,
|
|
3
|
+
OpenAPIServerlessHandler
|
|
4
|
+
} from "./chunk-7MA7YRRY.js";
|
|
5
|
+
import {
|
|
6
|
+
CompositeSchemaCoercer,
|
|
7
|
+
InputStructureCompact,
|
|
8
|
+
InputStructureDetailed,
|
|
9
|
+
OpenAPIHandler,
|
|
10
|
+
OpenAPIPayloadCodec,
|
|
11
|
+
OpenAPIProcedureMatcher,
|
|
12
|
+
deserialize,
|
|
13
|
+
escapeSegment,
|
|
14
|
+
parsePath,
|
|
15
|
+
serialize,
|
|
16
|
+
stringifyPath
|
|
17
|
+
} from "./chunk-BUMQYADN.js";
|
|
18
|
+
import "./chunk-DSYVLQK3.js";
|
|
19
|
+
export {
|
|
20
|
+
CompositeSchemaCoercer,
|
|
21
|
+
InputStructureCompact,
|
|
22
|
+
InputStructureDetailed,
|
|
23
|
+
OpenAPIHandler,
|
|
24
|
+
OpenAPIPayloadCodec,
|
|
25
|
+
OpenAPIProcedureMatcher,
|
|
26
|
+
OpenAPIServerHandler,
|
|
27
|
+
OpenAPIServerlessHandler,
|
|
28
|
+
deserialize,
|
|
29
|
+
escapeSegment,
|
|
30
|
+
parsePath,
|
|
31
|
+
serialize,
|
|
32
|
+
stringifyPath
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=next.js.map
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OpenAPIHandler
|
|
3
|
+
} from "./chunk-BUMQYADN.js";
|
|
4
|
+
import "./chunk-DSYVLQK3.js";
|
|
5
|
+
|
|
6
|
+
// src/adapters/node/openapi-handler.ts
|
|
7
|
+
import { createRequest, sendResponse } from "@orpc/server/node";
|
|
8
|
+
var OpenAPIHandler2 = class {
|
|
9
|
+
openapiFetchHandler;
|
|
10
|
+
constructor(hono, router, options) {
|
|
11
|
+
this.openapiFetchHandler = new OpenAPIHandler(hono, router, options);
|
|
12
|
+
}
|
|
13
|
+
async handle(req, res, ...[options]) {
|
|
14
|
+
const request = createRequest(req, res);
|
|
15
|
+
const castedOptions = options ?? {};
|
|
16
|
+
const result = await this.openapiFetchHandler.handle(request, castedOptions);
|
|
17
|
+
if (result.matched === false) {
|
|
18
|
+
return { matched: false };
|
|
19
|
+
}
|
|
20
|
+
await options?.beforeSend?.(result.response, castedOptions.context);
|
|
21
|
+
await sendResponse(res, result.response);
|
|
22
|
+
return { matched: true };
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// src/adapters/node/openapi-handler-server.ts
|
|
27
|
+
import { TrieRouter } from "hono/router/trie-router";
|
|
28
|
+
var OpenAPIServerHandler = class extends OpenAPIHandler2 {
|
|
29
|
+
constructor(router, options) {
|
|
30
|
+
super(new TrieRouter(), router, options);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// src/adapters/node/openapi-handler-serverless.ts
|
|
35
|
+
import { LinearRouter } from "hono/router/linear-router";
|
|
36
|
+
var OpenAPIServerlessHandler = class extends OpenAPIHandler2 {
|
|
37
|
+
constructor(router, options) {
|
|
38
|
+
super(new LinearRouter(), router, options);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
export {
|
|
42
|
+
OpenAPIHandler2 as OpenAPIHandler,
|
|
43
|
+
OpenAPIServerHandler,
|
|
44
|
+
OpenAPIServerlessHandler
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=node.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from './bracket-notation';
|
|
2
|
-
export * from './input-
|
|
3
|
-
export * from './input-
|
|
2
|
+
export * from './input-structure-compact';
|
|
3
|
+
export * from './input-structure-detailed';
|
|
4
4
|
export * from './openapi-handler';
|
|
5
5
|
export * from './openapi-handler-server';
|
|
6
6
|
export * from './openapi-handler-serverless';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Params } from 'hono/router';
|
|
2
|
+
export declare class InputStructureCompact {
|
|
3
|
+
build(params: Params, payload: unknown): unknown;
|
|
4
|
+
}
|
|
5
|
+
export type PublicInputStructureCompact = Pick<InputStructureCompact, keyof InputStructureCompact>;
|
|
6
|
+
//# sourceMappingURL=input-structure-compact.d.ts.map
|
package/dist/src/{fetch/input-builder-full.d.ts → adapters/fetch/input-structure-detailed.d.ts}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Params } from 'hono/router';
|
|
2
|
-
export declare class
|
|
2
|
+
export declare class InputStructureDetailed {
|
|
3
3
|
build(params: Params, query: unknown, headers: unknown, body: unknown): {
|
|
4
4
|
params: Params;
|
|
5
5
|
query: unknown;
|
|
@@ -7,5 +7,5 @@ export declare class InputBuilderFull {
|
|
|
7
7
|
body: unknown;
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
|
-
export type
|
|
11
|
-
//# sourceMappingURL=input-
|
|
10
|
+
export type PublicInputStructureDetailed = Pick<InputStructureDetailed, keyof InputStructureDetailed>;
|
|
11
|
+
//# sourceMappingURL=input-structure-detailed.d.ts.map
|
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
1
|
+
import type { Context, Router, WithSignal } from '@orpc/server';
|
|
2
|
+
import type { FetchHandler, FetchHandleRest, FetchHandleResult } from '@orpc/server/fetch';
|
|
3
|
+
import type { PublicInputStructureCompact } from './input-structure-compact';
|
|
4
4
|
import { type Hooks } from '@orpc/shared';
|
|
5
|
-
import { type PublicJSONSerializer } from '
|
|
6
|
-
import { type
|
|
5
|
+
import { type PublicJSONSerializer } from '../../json-serializer';
|
|
6
|
+
import { type PublicInputStructureDetailed } from './input-structure-detailed';
|
|
7
7
|
import { type PublicOpenAPIPayloadCodec } from './openapi-payload-codec';
|
|
8
8
|
import { type Hono, type PublicOpenAPIProcedureMatcher } from './openapi-procedure-matcher';
|
|
9
9
|
import { type SchemaCoercer } from './schema-coercer';
|
|
10
|
-
export type OpenAPIHandlerOptions<T extends Context> = Hooks<Request,
|
|
10
|
+
export type OpenAPIHandlerOptions<T extends Context> = Hooks<Request, FetchHandleResult, T, WithSignal> & {
|
|
11
11
|
jsonSerializer?: PublicJSONSerializer;
|
|
12
12
|
procedureMatcher?: PublicOpenAPIProcedureMatcher;
|
|
13
13
|
payloadCodec?: PublicOpenAPIPayloadCodec;
|
|
14
|
-
inputBuilderSimple?:
|
|
15
|
-
inputBuilderFull?:
|
|
14
|
+
inputBuilderSimple?: PublicInputStructureCompact;
|
|
15
|
+
inputBuilderFull?: PublicInputStructureDetailed;
|
|
16
16
|
schemaCoercers?: SchemaCoercer[];
|
|
17
17
|
};
|
|
18
|
-
export declare class OpenAPIHandler<T extends Context> implements
|
|
18
|
+
export declare class OpenAPIHandler<T extends Context> implements FetchHandler<T> {
|
|
19
19
|
private readonly options?;
|
|
20
20
|
private readonly procedureMatcher;
|
|
21
21
|
private readonly payloadCodec;
|
|
22
|
-
private readonly
|
|
23
|
-
private readonly
|
|
22
|
+
private readonly inputStructureCompact;
|
|
23
|
+
private readonly inputStructureDetailed;
|
|
24
24
|
private readonly compositeSchemaCoercer;
|
|
25
25
|
constructor(hono: Hono, router: Router<T, any>, options?: NoInfer<OpenAPIHandlerOptions<T>> | undefined);
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
handle(request: Request, ...[options]: FetchHandleRest<T>): Promise<FetchHandleResult>;
|
|
27
|
+
private decodeInput;
|
|
28
|
+
private encodeOutput;
|
|
29
|
+
private assertDetailedOutput;
|
|
28
30
|
private convertToORPCError;
|
|
29
31
|
}
|
|
30
32
|
//# sourceMappingURL=openapi-handler.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { PublicJSONSerializer } from '
|
|
1
|
+
import type { PublicJSONSerializer } from '../../json-serializer';
|
|
2
2
|
export declare class OpenAPIPayloadCodec {
|
|
3
3
|
private readonly jsonSerializer;
|
|
4
4
|
constructor(jsonSerializer: PublicJSONSerializer);
|
|
5
|
-
encode(payload: unknown, accept
|
|
5
|
+
encode(payload: unknown, accept: string | undefined): {
|
|
6
6
|
body: FormData | Blob | string | undefined;
|
|
7
7
|
headers?: Headers;
|
|
8
8
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Context, Router } from '@orpc/server';
|
|
2
|
+
import type { OpenAPIHandlerOptions } from '../fetch/openapi-handler';
|
|
3
|
+
import { OpenAPIHandler } from './openapi-handler';
|
|
4
|
+
export declare class OpenAPIServerHandler<T extends Context> extends OpenAPIHandler<T> {
|
|
5
|
+
constructor(router: Router<T, any>, options?: NoInfer<OpenAPIHandlerOptions<T>>);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=openapi-handler-server.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Context, Router } from '@orpc/server';
|
|
2
|
+
import type { OpenAPIHandlerOptions } from '../fetch/openapi-handler';
|
|
3
|
+
import { OpenAPIHandler } from './openapi-handler';
|
|
4
|
+
export declare class OpenAPIServerlessHandler<T extends Context> extends OpenAPIHandler<T> {
|
|
5
|
+
constructor(router: Router<T, any>, options?: NoInfer<OpenAPIHandlerOptions<T>>);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=openapi-handler-serverless.d.ts.map
|