@orpc/openapi 0.0.0-next.9b9ade5 → 0.0.0-next.9d7bfaa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -17
- package/dist/adapters/fetch/index.d.mts +12 -8
- package/dist/adapters/fetch/index.d.ts +12 -8
- package/dist/adapters/fetch/index.mjs +13 -7
- package/dist/adapters/node/index.d.mts +12 -8
- package/dist/adapters/node/index.d.ts +12 -8
- package/dist/adapters/node/index.mjs +8 -24
- package/dist/adapters/standard/index.d.mts +7 -7
- package/dist/adapters/standard/index.d.ts +7 -7
- package/dist/adapters/standard/index.mjs +4 -3
- package/dist/index.d.mts +26 -14
- package/dist/index.d.ts +26 -14
- package/dist/index.mjs +271 -29
- package/dist/shared/openapi.D3j94c9n.d.mts +12 -0
- package/dist/shared/openapi.D3j94c9n.d.ts +12 -0
- package/dist/shared/{openapi.CJTe38Ya.mjs → openapi.p5tsmBXx.mjs} +19 -6
- package/package.json +7 -19
- package/dist/adapters/hono/index.d.mts +0 -6
- package/dist/adapters/hono/index.d.ts +0 -6
- package/dist/adapters/hono/index.mjs +0 -11
- package/dist/adapters/next/index.d.mts +0 -6
- package/dist/adapters/next/index.d.ts +0 -6
- package/dist/adapters/next/index.mjs +0 -11
- package/dist/shared/openapi.CbzTVvGL.mjs +0 -31
- package/dist/shared/openapi.DZzpQAb-.mjs +0 -231
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { isProcedure, resolveContractProcedures
|
|
1
|
+
import { isProcedure, resolveContractProcedures } from '@orpc/server';
|
|
2
2
|
import { fallbackORPCErrorStatus, fallbackORPCErrorMessage } from '@orpc/client';
|
|
3
|
+
import { toHttpPath } from '@orpc/client/standard';
|
|
3
4
|
import { fallbackContractConfig, getEventIteratorSchemaDetails } from '@orpc/contract';
|
|
4
|
-
import {
|
|
5
|
-
import { clone } from '@orpc/shared';
|
|
6
|
-
import { t as toOpenAPIMethod, a as toOpenAPIPath, b as toOpenAPIEventIteratorContent, g as getDynamicParams, i as isAnySchema, c as isObjectSchema, d as separateObjectSchema, e as checkParamsSchema, f as toOpenAPIParameters, h as toOpenAPIContent, j as toOpenAPISchema } from './shared/openapi.DZzpQAb-.mjs';
|
|
7
|
-
export { L as LOGIC_KEYWORDS, l as filterSchemaBranches, k as isFileSchema, s as standardizeHTTPPath } from './shared/openapi.DZzpQAb-.mjs';
|
|
5
|
+
import { standardizeHTTPPath, StandardOpenAPIJsonSerializer, getDynamicParams } from '@orpc/openapi-client/standard';
|
|
6
|
+
import { isObject, findDeepMatches, toArray, clone } from '@orpc/shared';
|
|
8
7
|
export { Format as JSONSchemaFormat } from 'json-schema-typed/draft-2020-12';
|
|
9
8
|
|
|
10
9
|
const OPERATION_EXTENDER_SYMBOL = Symbol("ORPC_OPERATION_EXTENDER");
|
|
@@ -51,14 +50,246 @@ function applyCustomOpenAPIOperation(operation, contract) {
|
|
|
51
50
|
return currentOperation;
|
|
52
51
|
}
|
|
53
52
|
|
|
53
|
+
const LOGIC_KEYWORDS = [
|
|
54
|
+
"$dynamicRef",
|
|
55
|
+
"$ref",
|
|
56
|
+
"additionalItems",
|
|
57
|
+
"additionalProperties",
|
|
58
|
+
"allOf",
|
|
59
|
+
"anyOf",
|
|
60
|
+
"const",
|
|
61
|
+
"contains",
|
|
62
|
+
"contentEncoding",
|
|
63
|
+
"contentMediaType",
|
|
64
|
+
"contentSchema",
|
|
65
|
+
"dependencies",
|
|
66
|
+
"dependentRequired",
|
|
67
|
+
"dependentSchemas",
|
|
68
|
+
"else",
|
|
69
|
+
"enum",
|
|
70
|
+
"exclusiveMaximum",
|
|
71
|
+
"exclusiveMinimum",
|
|
72
|
+
"format",
|
|
73
|
+
"if",
|
|
74
|
+
"items",
|
|
75
|
+
"maxContains",
|
|
76
|
+
"maximum",
|
|
77
|
+
"maxItems",
|
|
78
|
+
"maxLength",
|
|
79
|
+
"maxProperties",
|
|
80
|
+
"minContains",
|
|
81
|
+
"minimum",
|
|
82
|
+
"minItems",
|
|
83
|
+
"minLength",
|
|
84
|
+
"minProperties",
|
|
85
|
+
"multipleOf",
|
|
86
|
+
"not",
|
|
87
|
+
"oneOf",
|
|
88
|
+
"pattern",
|
|
89
|
+
"patternProperties",
|
|
90
|
+
"prefixItems",
|
|
91
|
+
"properties",
|
|
92
|
+
"propertyNames",
|
|
93
|
+
"required",
|
|
94
|
+
"then",
|
|
95
|
+
"type",
|
|
96
|
+
"unevaluatedItems",
|
|
97
|
+
"unevaluatedProperties",
|
|
98
|
+
"uniqueItems"
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
function isFileSchema(schema) {
|
|
102
|
+
return isObject(schema) && schema.type === "string" && typeof schema.contentMediaType === "string";
|
|
103
|
+
}
|
|
104
|
+
function isObjectSchema(schema) {
|
|
105
|
+
return isObject(schema) && schema.type === "object";
|
|
106
|
+
}
|
|
107
|
+
function isAnySchema(schema) {
|
|
108
|
+
if (schema === true) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (Object.keys(schema).every((k) => !LOGIC_KEYWORDS.includes(k))) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
function separateObjectSchema(schema, separatedProperties) {
|
|
117
|
+
if (Object.keys(schema).some((k) => k !== "type" && k !== "properties" && k !== "required" && LOGIC_KEYWORDS.includes(k))) {
|
|
118
|
+
return [{ type: "object" }, schema];
|
|
119
|
+
}
|
|
120
|
+
const matched = { ...schema };
|
|
121
|
+
const rest = { ...schema };
|
|
122
|
+
matched.properties = schema.properties && Object.entries(schema.properties).filter(([key]) => separatedProperties.includes(key)).reduce((acc, [key, value]) => {
|
|
123
|
+
acc[key] = value;
|
|
124
|
+
return acc;
|
|
125
|
+
}, {});
|
|
126
|
+
matched.required = schema.required?.filter((key) => separatedProperties.includes(key));
|
|
127
|
+
matched.examples = schema.examples?.map((example) => {
|
|
128
|
+
if (!isObject(example)) {
|
|
129
|
+
return example;
|
|
130
|
+
}
|
|
131
|
+
return Object.entries(example).reduce((acc, [key, value]) => {
|
|
132
|
+
if (separatedProperties.includes(key)) {
|
|
133
|
+
acc[key] = value;
|
|
134
|
+
}
|
|
135
|
+
return acc;
|
|
136
|
+
}, {});
|
|
137
|
+
});
|
|
138
|
+
rest.properties = schema.properties && Object.entries(schema.properties).filter(([key]) => !separatedProperties.includes(key)).reduce((acc, [key, value]) => {
|
|
139
|
+
acc[key] = value;
|
|
140
|
+
return acc;
|
|
141
|
+
}, {});
|
|
142
|
+
rest.required = schema.required?.filter((key) => !separatedProperties.includes(key));
|
|
143
|
+
rest.examples = schema.examples?.map((example) => {
|
|
144
|
+
if (!isObject(example)) {
|
|
145
|
+
return example;
|
|
146
|
+
}
|
|
147
|
+
return Object.entries(example).reduce((acc, [key, value]) => {
|
|
148
|
+
if (!separatedProperties.includes(key)) {
|
|
149
|
+
acc[key] = value;
|
|
150
|
+
}
|
|
151
|
+
return acc;
|
|
152
|
+
}, {});
|
|
153
|
+
});
|
|
154
|
+
return [matched, rest];
|
|
155
|
+
}
|
|
156
|
+
function filterSchemaBranches(schema, check, matches = []) {
|
|
157
|
+
if (check(schema)) {
|
|
158
|
+
matches.push(schema);
|
|
159
|
+
return [matches, void 0];
|
|
160
|
+
}
|
|
161
|
+
if (isObject(schema)) {
|
|
162
|
+
for (const keyword of ["anyOf", "oneOf"]) {
|
|
163
|
+
if (schema[keyword] && Object.keys(schema).every(
|
|
164
|
+
(k) => k === keyword || !LOGIC_KEYWORDS.includes(k)
|
|
165
|
+
)) {
|
|
166
|
+
const rest = schema[keyword].map((s) => filterSchemaBranches(s, check, matches)[1]).filter((v) => !!v);
|
|
167
|
+
if (rest.length === 1 && typeof rest[0] === "object") {
|
|
168
|
+
return [matches, { ...schema, [keyword]: void 0, ...rest[0] }];
|
|
169
|
+
}
|
|
170
|
+
return [matches, { ...schema, [keyword]: rest }];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return [matches, schema];
|
|
175
|
+
}
|
|
176
|
+
function applySchemaOptionality(required, schema) {
|
|
177
|
+
if (required) {
|
|
178
|
+
return schema;
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
anyOf: [
|
|
182
|
+
schema,
|
|
183
|
+
{ not: {} }
|
|
184
|
+
]
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function toOpenAPIPath(path) {
|
|
189
|
+
return standardizeHTTPPath(path).replace(/\/\{\+([^}]+)\}/g, "/{$1}");
|
|
190
|
+
}
|
|
191
|
+
function toOpenAPIMethod(method) {
|
|
192
|
+
return method.toLocaleLowerCase();
|
|
193
|
+
}
|
|
194
|
+
function toOpenAPIContent(schema) {
|
|
195
|
+
const content = {};
|
|
196
|
+
const [matches, restSchema] = filterSchemaBranches(schema, isFileSchema);
|
|
197
|
+
for (const file of matches) {
|
|
198
|
+
content[file.contentMediaType] = {
|
|
199
|
+
schema: toOpenAPISchema(file)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
if (restSchema !== void 0) {
|
|
203
|
+
content["application/json"] = {
|
|
204
|
+
schema: toOpenAPISchema(restSchema)
|
|
205
|
+
};
|
|
206
|
+
const isStillHasFileSchema = findDeepMatches((v) => isObject(v) && isFileSchema(v), restSchema).values.length > 0;
|
|
207
|
+
if (isStillHasFileSchema) {
|
|
208
|
+
content["multipart/form-data"] = {
|
|
209
|
+
schema: toOpenAPISchema(restSchema)
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return content;
|
|
214
|
+
}
|
|
215
|
+
function toOpenAPIEventIteratorContent([yieldsRequired, yieldsSchema], [returnsRequired, returnsSchema]) {
|
|
216
|
+
return {
|
|
217
|
+
"text/event-stream": {
|
|
218
|
+
schema: toOpenAPISchema({
|
|
219
|
+
oneOf: [
|
|
220
|
+
{
|
|
221
|
+
type: "object",
|
|
222
|
+
properties: {
|
|
223
|
+
event: { const: "message" },
|
|
224
|
+
data: yieldsSchema,
|
|
225
|
+
id: { type: "string" },
|
|
226
|
+
retry: { type: "number" }
|
|
227
|
+
},
|
|
228
|
+
required: yieldsRequired ? ["event", "data"] : ["event"]
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
type: "object",
|
|
232
|
+
properties: {
|
|
233
|
+
event: { const: "done" },
|
|
234
|
+
data: returnsSchema,
|
|
235
|
+
id: { type: "string" },
|
|
236
|
+
retry: { type: "number" }
|
|
237
|
+
},
|
|
238
|
+
required: returnsRequired ? ["event", "data"] : ["event"]
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
type: "object",
|
|
242
|
+
properties: {
|
|
243
|
+
event: { const: "error" },
|
|
244
|
+
data: {},
|
|
245
|
+
id: { type: "string" },
|
|
246
|
+
retry: { type: "number" }
|
|
247
|
+
},
|
|
248
|
+
required: ["event"]
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
})
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function toOpenAPIParameters(schema, parameterIn) {
|
|
256
|
+
const parameters = [];
|
|
257
|
+
for (const key in schema.properties) {
|
|
258
|
+
const keySchema = schema.properties[key];
|
|
259
|
+
parameters.push({
|
|
260
|
+
name: key,
|
|
261
|
+
in: parameterIn,
|
|
262
|
+
required: schema.required?.includes(key),
|
|
263
|
+
style: parameterIn === "query" ? "deepObject" : void 0,
|
|
264
|
+
explode: parameterIn === "query" ? true : void 0,
|
|
265
|
+
schema: toOpenAPISchema(keySchema)
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
return parameters;
|
|
269
|
+
}
|
|
270
|
+
function checkParamsSchema(schema, params) {
|
|
271
|
+
const properties = Object.keys(schema.properties ?? {});
|
|
272
|
+
const required = schema.required ?? [];
|
|
273
|
+
if (properties.length !== params.length || properties.some((v) => !params.includes(v))) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
if (required.length !== params.length || required.some((v) => !params.includes(v))) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
function toOpenAPISchema(schema) {
|
|
282
|
+
return schema === true ? {} : schema === false ? { not: {} } : schema;
|
|
283
|
+
}
|
|
284
|
+
|
|
54
285
|
class CompositeSchemaConverter {
|
|
55
286
|
converters;
|
|
56
287
|
constructor(converters) {
|
|
57
288
|
this.converters = converters;
|
|
58
289
|
}
|
|
59
|
-
convert(schema, options) {
|
|
290
|
+
async convert(schema, options) {
|
|
60
291
|
for (const converter of this.converters) {
|
|
61
|
-
if (converter.condition(schema, options)) {
|
|
292
|
+
if (await converter.condition(schema, options)) {
|
|
62
293
|
return converter.convert(schema, options);
|
|
63
294
|
}
|
|
64
295
|
}
|
|
@@ -72,14 +303,23 @@ class OpenAPIGenerator {
|
|
|
72
303
|
serializer;
|
|
73
304
|
converter;
|
|
74
305
|
constructor(options = {}) {
|
|
75
|
-
this.serializer = new
|
|
76
|
-
this.converter = new CompositeSchemaConverter(options.schemaConverters
|
|
306
|
+
this.serializer = new StandardOpenAPIJsonSerializer(options);
|
|
307
|
+
this.converter = new CompositeSchemaConverter(toArray(options.schemaConverters));
|
|
77
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* Generates OpenAPI specifications from oRPC routers/contracts.
|
|
311
|
+
*
|
|
312
|
+
* @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification OpenAPI Specification Docs}
|
|
313
|
+
*/
|
|
78
314
|
async generate(router, base) {
|
|
79
315
|
const doc = clone(base);
|
|
80
316
|
doc.openapi = "3.1.1";
|
|
81
|
-
const
|
|
317
|
+
const contracts = [];
|
|
82
318
|
await resolveContractProcedures({ path: [], router }, ({ contract, path }) => {
|
|
319
|
+
contracts.push({ contract, path });
|
|
320
|
+
});
|
|
321
|
+
const errors = [];
|
|
322
|
+
for (const { contract, path } of contracts) {
|
|
83
323
|
const operationId = path.join(".");
|
|
84
324
|
try {
|
|
85
325
|
const def = contract["~orpc"];
|
|
@@ -92,9 +332,9 @@ class OpenAPIGenerator {
|
|
|
92
332
|
deprecated: def.route.deprecated,
|
|
93
333
|
tags: def.route.tags?.map((tag) => tag)
|
|
94
334
|
};
|
|
95
|
-
this.#request(operationObjectRef, def);
|
|
96
|
-
this.#successResponse(operationObjectRef, def);
|
|
97
|
-
this.#errorResponse(operationObjectRef, def);
|
|
335
|
+
await this.#request(operationObjectRef, def);
|
|
336
|
+
await this.#successResponse(operationObjectRef, def);
|
|
337
|
+
await this.#errorResponse(operationObjectRef, def);
|
|
98
338
|
doc.paths ??= {};
|
|
99
339
|
doc.paths[httpPath] ??= {};
|
|
100
340
|
doc.paths[httpPath][method] = applyCustomOpenAPIOperation(operationObjectRef, contract);
|
|
@@ -107,7 +347,7 @@ class OpenAPIGenerator {
|
|
|
107
347
|
${e.message}`
|
|
108
348
|
);
|
|
109
349
|
}
|
|
110
|
-
}
|
|
350
|
+
}
|
|
111
351
|
if (errors.length) {
|
|
112
352
|
throw new OpenAPIGeneratorError(
|
|
113
353
|
`Some error occurred during OpenAPI generation:
|
|
@@ -115,24 +355,24 @@ ${e.message}`
|
|
|
115
355
|
${errors.join("\n\n")}`
|
|
116
356
|
);
|
|
117
357
|
}
|
|
118
|
-
return this.serializer.serialize(doc);
|
|
358
|
+
return this.serializer.serialize(doc)[0];
|
|
119
359
|
}
|
|
120
|
-
#request(ref, def) {
|
|
360
|
+
async #request(ref, def) {
|
|
121
361
|
const method = fallbackContractConfig("defaultMethod", def.route.method);
|
|
122
362
|
const details = getEventIteratorSchemaDetails(def.inputSchema);
|
|
123
363
|
if (details) {
|
|
124
364
|
ref.requestBody = {
|
|
125
365
|
required: true,
|
|
126
366
|
content: toOpenAPIEventIteratorContent(
|
|
127
|
-
this.converter.convert(details.yields, { strategy: "input" }),
|
|
128
|
-
this.converter.convert(details.returns, { strategy: "input" })
|
|
367
|
+
await this.converter.convert(details.yields, { strategy: "input" }),
|
|
368
|
+
await this.converter.convert(details.returns, { strategy: "input" })
|
|
129
369
|
)
|
|
130
370
|
};
|
|
131
371
|
return;
|
|
132
372
|
}
|
|
133
|
-
const dynamicParams = getDynamicParams(def.route.path);
|
|
373
|
+
const dynamicParams = getDynamicParams(def.route.path)?.map((v) => v.name);
|
|
134
374
|
const inputStructure = fallbackContractConfig("defaultInputStructure", def.route.inputStructure);
|
|
135
|
-
let [required, schema] = this.converter.convert(def.inputSchema, { strategy: "input" });
|
|
375
|
+
let [required, schema] = await this.converter.convert(def.inputSchema, { strategy: "input" });
|
|
136
376
|
if (isAnySchema(schema) && !dynamicParams?.length) {
|
|
137
377
|
return;
|
|
138
378
|
}
|
|
@@ -198,7 +438,7 @@ ${errors.join("\n\n")}`
|
|
|
198
438
|
};
|
|
199
439
|
}
|
|
200
440
|
}
|
|
201
|
-
#successResponse(ref, def) {
|
|
441
|
+
async #successResponse(ref, def) {
|
|
202
442
|
const outputSchema = def.outputSchema;
|
|
203
443
|
const status = fallbackContractConfig("defaultSuccessStatus", def.route.successStatus);
|
|
204
444
|
const description = fallbackContractConfig("defaultSuccessDescription", def.route?.successDescription);
|
|
@@ -209,19 +449,19 @@ ${errors.join("\n\n")}`
|
|
|
209
449
|
ref.responses[status] = {
|
|
210
450
|
description,
|
|
211
451
|
content: toOpenAPIEventIteratorContent(
|
|
212
|
-
this.converter.convert(eventIteratorSchemaDetails.yields, { strategy: "output" }),
|
|
213
|
-
this.converter.convert(eventIteratorSchemaDetails.returns, { strategy: "output" })
|
|
452
|
+
await this.converter.convert(eventIteratorSchemaDetails.yields, { strategy: "output" }),
|
|
453
|
+
await this.converter.convert(eventIteratorSchemaDetails.returns, { strategy: "output" })
|
|
214
454
|
)
|
|
215
455
|
};
|
|
216
456
|
return;
|
|
217
457
|
}
|
|
218
|
-
const [
|
|
458
|
+
const [required, json] = await this.converter.convert(outputSchema, { strategy: "output" });
|
|
219
459
|
ref.responses ??= {};
|
|
220
460
|
ref.responses[status] = {
|
|
221
461
|
description
|
|
222
462
|
};
|
|
223
463
|
if (outputStructure === "compact") {
|
|
224
|
-
ref.responses[status].content = toOpenAPIContent(json);
|
|
464
|
+
ref.responses[status].content = toOpenAPIContent(applySchemaOptionality(required, json));
|
|
225
465
|
return;
|
|
226
466
|
}
|
|
227
467
|
const error = new OpenAPIGeneratorError(
|
|
@@ -243,10 +483,12 @@ ${errors.join("\n\n")}`
|
|
|
243
483
|
}
|
|
244
484
|
}
|
|
245
485
|
if (json.properties?.body !== void 0) {
|
|
246
|
-
ref.responses[status].content = toOpenAPIContent(
|
|
486
|
+
ref.responses[status].content = toOpenAPIContent(
|
|
487
|
+
applySchemaOptionality(json.required?.includes("body") ?? false, json.properties.body)
|
|
488
|
+
);
|
|
247
489
|
}
|
|
248
490
|
}
|
|
249
|
-
#errorResponse(ref, def) {
|
|
491
|
+
async #errorResponse(ref, def) {
|
|
250
492
|
const errorMap = def.errorMap;
|
|
251
493
|
const errors = {};
|
|
252
494
|
for (const code in errorMap) {
|
|
@@ -256,7 +498,7 @@ ${errors.join("\n\n")}`
|
|
|
256
498
|
}
|
|
257
499
|
const status = fallbackORPCErrorStatus(code, config.status);
|
|
258
500
|
const message = fallbackORPCErrorMessage(code, config.message);
|
|
259
|
-
const [dataRequired, dataSchema] = this.converter.convert(config.data, { strategy: "output" });
|
|
501
|
+
const [dataRequired, dataSchema] = await this.converter.convert(config.data, { strategy: "output" });
|
|
260
502
|
errors[status] ??= [];
|
|
261
503
|
errors[status].push({
|
|
262
504
|
type: "object",
|
|
@@ -300,4 +542,4 @@ const oo = {
|
|
|
300
542
|
spec: customOpenAPIOperation
|
|
301
543
|
};
|
|
302
544
|
|
|
303
|
-
export { CompositeSchemaConverter, OpenAPIGenerator, applyCustomOpenAPIOperation, checkParamsSchema, customOpenAPIOperation,
|
|
545
|
+
export { CompositeSchemaConverter, LOGIC_KEYWORDS, OpenAPIGenerator, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, customOpenAPIOperation, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, oo, separateObjectSchema, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StandardOpenAPIJsonSerializerOptions } from '@orpc/openapi-client/standard';
|
|
2
|
+
import { Context, Router } from '@orpc/server';
|
|
3
|
+
import { StandardHandlerOptions, StandardHandler } from '@orpc/server/standard';
|
|
4
|
+
|
|
5
|
+
interface StandardOpenAPIHandlerOptions<T extends Context> extends StandardHandlerOptions<T>, StandardOpenAPIJsonSerializerOptions {
|
|
6
|
+
}
|
|
7
|
+
declare class StandardOpenAPIHandler<T extends Context> extends StandardHandler<T> {
|
|
8
|
+
constructor(router: Router<any, T>, options: NoInfer<StandardOpenAPIHandlerOptions<T>>);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { StandardOpenAPIHandler as a };
|
|
12
|
+
export type { StandardOpenAPIHandlerOptions as S };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StandardOpenAPIJsonSerializerOptions } from '@orpc/openapi-client/standard';
|
|
2
|
+
import { Context, Router } from '@orpc/server';
|
|
3
|
+
import { StandardHandlerOptions, StandardHandler } from '@orpc/server/standard';
|
|
4
|
+
|
|
5
|
+
interface StandardOpenAPIHandlerOptions<T extends Context> extends StandardHandlerOptions<T>, StandardOpenAPIJsonSerializerOptions {
|
|
6
|
+
}
|
|
7
|
+
declare class StandardOpenAPIHandler<T extends Context> extends StandardHandler<T> {
|
|
8
|
+
constructor(router: Router<any, T>, options: NoInfer<StandardOpenAPIHandlerOptions<T>>);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { StandardOpenAPIHandler as a };
|
|
12
|
+
export type { StandardOpenAPIHandlerOptions as S };
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { standardizeHTTPPath, StandardOpenAPIJsonSerializer, StandardBracketNotationSerializer, StandardOpenAPISerializer } from '@orpc/openapi-client/standard';
|
|
2
|
+
import { StandardHandler } from '@orpc/server/standard';
|
|
1
3
|
import { fallbackContractConfig } from '@orpc/contract';
|
|
2
4
|
import { isObject } from '@orpc/shared';
|
|
3
|
-
import {
|
|
5
|
+
import { toHttpPath } from '@orpc/client/standard';
|
|
6
|
+
import { traverseContractProcedures, isProcedure, getLazyMeta, unlazy, getRouter, createContractedProcedure } from '@orpc/server';
|
|
4
7
|
import { createRouter, addRoute, findRoute } from 'rou3';
|
|
5
|
-
import { s as standardizeHTTPPath } from './openapi.DZzpQAb-.mjs';
|
|
6
8
|
|
|
7
|
-
class
|
|
9
|
+
class StandardOpenAPICodec {
|
|
8
10
|
constructor(serializer) {
|
|
9
11
|
this.serializer = serializer;
|
|
10
12
|
}
|
|
@@ -65,7 +67,7 @@ class OpenAPICodec {
|
|
|
65
67
|
return {
|
|
66
68
|
status: error.status,
|
|
67
69
|
headers: {},
|
|
68
|
-
body: this.serializer.serialize(error.toJSON())
|
|
70
|
+
body: this.serializer.serialize(error.toJSON(), { outputFormat: "plain" })
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
73
|
}
|
|
@@ -77,7 +79,7 @@ function decodeParams(params) {
|
|
|
77
79
|
return Object.fromEntries(Object.entries(params).map(([key, value]) => [key, decodeURIComponent(value)]));
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
class
|
|
82
|
+
class StandardOpenAPIMatcher {
|
|
81
83
|
tree = createRouter();
|
|
82
84
|
pendingRouters = [];
|
|
83
85
|
init(router, path = []) {
|
|
@@ -142,4 +144,15 @@ class OpenAPIMatcher {
|
|
|
142
144
|
}
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
|
|
147
|
+
class StandardOpenAPIHandler extends StandardHandler {
|
|
148
|
+
constructor(router, options) {
|
|
149
|
+
const jsonSerializer = new StandardOpenAPIJsonSerializer(options);
|
|
150
|
+
const bracketNotationSerializer = new StandardBracketNotationSerializer();
|
|
151
|
+
const serializer = new StandardOpenAPISerializer(jsonSerializer, bracketNotationSerializer);
|
|
152
|
+
const matcher = new StandardOpenAPIMatcher();
|
|
153
|
+
const codec = new StandardOpenAPICodec(serializer);
|
|
154
|
+
super(router, matcher, codec, options);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { StandardOpenAPICodec as S, StandardOpenAPIHandler as a, StandardOpenAPIMatcher as b, decodeParams as d, toRou3Pattern as t };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/openapi",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.0-next.
|
|
4
|
+
"version": "0.0.0-next.9d7bfaa",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://orpc.unnoq.com",
|
|
7
7
|
"repository": {
|
|
@@ -29,16 +29,6 @@
|
|
|
29
29
|
"import": "./dist/adapters/fetch/index.mjs",
|
|
30
30
|
"default": "./dist/adapters/fetch/index.mjs"
|
|
31
31
|
},
|
|
32
|
-
"./hono": {
|
|
33
|
-
"types": "./dist/adapters/hono/index.d.mts",
|
|
34
|
-
"import": "./dist/adapters/hono/index.mjs",
|
|
35
|
-
"default": "./dist/adapters/hono/index.mjs"
|
|
36
|
-
},
|
|
37
|
-
"./next": {
|
|
38
|
-
"types": "./dist/adapters/next/index.d.mts",
|
|
39
|
-
"import": "./dist/adapters/next/index.mjs",
|
|
40
|
-
"default": "./dist/adapters/next/index.mjs"
|
|
41
|
-
},
|
|
42
32
|
"./node": {
|
|
43
33
|
"types": "./dist/adapters/node/index.d.mts",
|
|
44
34
|
"import": "./dist/adapters/node/index.mjs",
|
|
@@ -52,14 +42,12 @@
|
|
|
52
42
|
"json-schema-typed": "^8.0.1",
|
|
53
43
|
"openapi-types": "^12.1.3",
|
|
54
44
|
"rou3": "^0.5.1",
|
|
55
|
-
"@orpc/client": "0.0.0-next.
|
|
56
|
-
"@orpc/contract": "0.0.0-next.
|
|
57
|
-
"@orpc/server": "0.0.0-next.
|
|
58
|
-
"@orpc/openapi-client": "0.0.0-next.
|
|
59
|
-
"@orpc/
|
|
60
|
-
"@orpc/standard-server
|
|
61
|
-
"@orpc/standard-server-fetch": "0.0.0-next.9b9ade5",
|
|
62
|
-
"@orpc/shared": "0.0.0-next.9b9ade5"
|
|
45
|
+
"@orpc/client": "0.0.0-next.9d7bfaa",
|
|
46
|
+
"@orpc/contract": "0.0.0-next.9d7bfaa",
|
|
47
|
+
"@orpc/server": "0.0.0-next.9d7bfaa",
|
|
48
|
+
"@orpc/openapi-client": "0.0.0-next.9d7bfaa",
|
|
49
|
+
"@orpc/shared": "0.0.0-next.9d7bfaa",
|
|
50
|
+
"@orpc/standard-server": "0.0.0-next.9d7bfaa"
|
|
63
51
|
},
|
|
64
52
|
"devDependencies": {
|
|
65
53
|
"zod": "^3.24.2"
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { O as OpenAPIHandler } from '../../shared/openapi.CbzTVvGL.mjs';
|
|
2
|
-
import '@orpc/openapi-client/standard';
|
|
3
|
-
import '@orpc/server/standard';
|
|
4
|
-
import '@orpc/standard-server-fetch';
|
|
5
|
-
import '../../shared/openapi.CJTe38Ya.mjs';
|
|
6
|
-
import '@orpc/contract';
|
|
7
|
-
import '@orpc/shared';
|
|
8
|
-
import '@orpc/server';
|
|
9
|
-
import 'rou3';
|
|
10
|
-
import '../../shared/openapi.DZzpQAb-.mjs';
|
|
11
|
-
import 'json-schema-typed/draft-2020-12';
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { O as OpenAPIHandler } from '../../shared/openapi.CbzTVvGL.mjs';
|
|
2
|
-
import '@orpc/openapi-client/standard';
|
|
3
|
-
import '@orpc/server/standard';
|
|
4
|
-
import '@orpc/standard-server-fetch';
|
|
5
|
-
import '../../shared/openapi.CJTe38Ya.mjs';
|
|
6
|
-
import '@orpc/contract';
|
|
7
|
-
import '@orpc/shared';
|
|
8
|
-
import '@orpc/server';
|
|
9
|
-
import 'rou3';
|
|
10
|
-
import '../../shared/openapi.DZzpQAb-.mjs';
|
|
11
|
-
import 'json-schema-typed/draft-2020-12';
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { OpenAPISerializer } from '@orpc/openapi-client/standard';
|
|
2
|
-
import { StandardHandler } from '@orpc/server/standard';
|
|
3
|
-
import { toStandardLazyRequest, toFetchResponse } from '@orpc/standard-server-fetch';
|
|
4
|
-
import { a as OpenAPIMatcher, O as OpenAPICodec } from './openapi.CJTe38Ya.mjs';
|
|
5
|
-
import '@orpc/shared';
|
|
6
|
-
import 'json-schema-typed/draft-2020-12';
|
|
7
|
-
|
|
8
|
-
class OpenAPIHandler {
|
|
9
|
-
standardHandler;
|
|
10
|
-
constructor(router, options = {}) {
|
|
11
|
-
const serializer = new OpenAPISerializer();
|
|
12
|
-
const matcher = new OpenAPIMatcher();
|
|
13
|
-
const codec = new OpenAPICodec(serializer);
|
|
14
|
-
this.standardHandler = new StandardHandler(router, matcher, codec, options);
|
|
15
|
-
}
|
|
16
|
-
async handle(request, ...[
|
|
17
|
-
options = {}
|
|
18
|
-
]) {
|
|
19
|
-
const standardRequest = toStandardLazyRequest(request);
|
|
20
|
-
const result = await this.standardHandler.handle(standardRequest, options);
|
|
21
|
-
if (!result.matched) {
|
|
22
|
-
return result;
|
|
23
|
-
}
|
|
24
|
-
return {
|
|
25
|
-
matched: true,
|
|
26
|
-
response: toFetchResponse(result.response, options)
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export { OpenAPIHandler as O };
|