@orpc/openapi 0.0.0-next.ccd4e42 → 0.0.0-next.cd121e3
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 +91 -0
- package/dist/adapters/fetch/index.d.mts +14 -0
- package/dist/adapters/fetch/index.d.ts +14 -0
- package/dist/adapters/fetch/index.mjs +10 -0
- package/dist/adapters/hono/index.d.mts +7 -0
- package/dist/adapters/hono/index.d.ts +7 -0
- package/dist/adapters/hono/index.mjs +10 -0
- package/dist/adapters/next/index.d.mts +7 -0
- package/dist/adapters/next/index.d.ts +7 -0
- package/dist/adapters/next/index.mjs +10 -0
- package/dist/adapters/node/index.d.mts +14 -0
- package/dist/adapters/node/index.d.ts +14 -0
- package/dist/adapters/node/index.mjs +29 -0
- package/dist/adapters/standard/index.d.mts +24 -0
- package/dist/adapters/standard/index.d.ts +24 -0
- package/dist/adapters/standard/index.mjs +7 -0
- package/dist/index.d.mts +169 -0
- package/dist/index.d.ts +169 -0
- package/dist/{index.js → index.mjs} +207 -92
- package/dist/shared/openapi.BHG_gu5Z.mjs +8 -0
- package/dist/shared/openapi.CDsfPHgw.mjs +148 -0
- package/dist/shared/openapi.D0VMNR6V.mjs +25 -0
- package/dist/shared/openapi.Dz_6xooR.d.mts +7 -0
- package/dist/shared/openapi.Dz_6xooR.d.ts +7 -0
- package/package.json +28 -35
- package/dist/chunk-BHJYKXQL.js +0 -52
- package/dist/chunk-HQ34JZI7.js +0 -32
- package/dist/chunk-M5HOHBLW.js +0 -432
- package/dist/fetch.js +0 -9
- package/dist/hono.js +0 -9
- package/dist/next.js +0 -9
- package/dist/node.js +0 -30
- package/dist/src/adapters/fetch/index.d.ts +0 -2
- package/dist/src/adapters/fetch/openapi-handler.d.ts +0 -10
- package/dist/src/adapters/hono/index.d.ts +0 -2
- package/dist/src/adapters/next/index.d.ts +0 -2
- package/dist/src/adapters/node/index.d.ts +0 -2
- package/dist/src/adapters/node/openapi-handler.d.ts +0 -10
- package/dist/src/adapters/standard/bracket-notation.d.ts +0 -84
- package/dist/src/adapters/standard/index.d.ts +0 -7
- package/dist/src/adapters/standard/openapi-codec.d.ts +0 -18
- package/dist/src/adapters/standard/openapi-handler.d.ts +0 -7
- package/dist/src/adapters/standard/openapi-matcher.d.ts +0 -20
- package/dist/src/adapters/standard/openapi-serializer.d.ts +0 -11
- package/dist/src/adapters/standard/schema-coercer.d.ts +0 -10
- package/dist/src/index.d.ts +0 -12
- package/dist/src/json-serializer.d.ts +0 -5
- package/dist/src/openapi-content-builder.d.ts +0 -10
- package/dist/src/openapi-error.d.ts +0 -3
- package/dist/src/openapi-generator.d.ts +0 -67
- package/dist/src/openapi-input-structure-parser.d.ts +0 -22
- package/dist/src/openapi-output-structure-parser.d.ts +0 -18
- package/dist/src/openapi-parameters-builder.d.ts +0 -12
- package/dist/src/openapi-path-parser.d.ts +0 -8
- package/dist/src/openapi.d.ts +0 -3
- package/dist/src/schema-converter.d.ts +0 -16
- package/dist/src/schema-utils.d.ts +0 -11
- package/dist/src/schema.d.ts +0 -12
- package/dist/src/utils.d.ts +0 -3
- package/dist/standard.js +0 -16
|
@@ -1,14 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from
|
|
1
|
+
import { isProcedure, eachAllContractProcedure } from '@orpc/server';
|
|
2
|
+
import { OpenApiBuilder } from 'openapi3-ts/oas31';
|
|
3
|
+
export { OpenApiBuilder } from 'openapi3-ts/oas31';
|
|
4
|
+
import { findDeepMatches, isObject, get, omit, group } from '@orpc/shared';
|
|
5
|
+
import { fallbackORPCErrorStatus } from '@orpc/client';
|
|
6
|
+
import { fallbackContractConfig, getEventIteratorSchemaDetails } from '@orpc/contract';
|
|
7
|
+
import { OpenAPIJsonSerializer } from '@orpc/openapi-client/standard';
|
|
8
|
+
import * as draft202012 from 'json-schema-typed/draft-2020-12';
|
|
9
|
+
export { draft202012 as JSONSchema };
|
|
10
|
+
export { Format as JSONSchemaFormat } from 'json-schema-typed/draft-2020-12';
|
|
11
|
+
import { t as toOpenAPI31RoutePattern } from './shared/openapi.BHG_gu5Z.mjs';
|
|
12
|
+
export { s as standardizeHTTPPath } from './shared/openapi.BHG_gu5Z.mjs';
|
|
5
13
|
|
|
6
|
-
|
|
7
|
-
|
|
14
|
+
const OPERATION_EXTENDER_SYMBOL = Symbol("ORPC_OPERATION_EXTENDER");
|
|
15
|
+
function setOperationExtender(o, extend) {
|
|
16
|
+
return new Proxy(o, {
|
|
17
|
+
get(target, prop, receiver) {
|
|
18
|
+
if (prop === OPERATION_EXTENDER_SYMBOL) {
|
|
19
|
+
return extend;
|
|
20
|
+
}
|
|
21
|
+
return Reflect.get(target, prop, receiver);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function getOperationExtender(o) {
|
|
26
|
+
return o[OPERATION_EXTENDER_SYMBOL];
|
|
27
|
+
}
|
|
28
|
+
function extendOperation(operation, procedure) {
|
|
29
|
+
const operationExtenders = [];
|
|
30
|
+
for (const errorItem of Object.values(procedure["~orpc"].errorMap)) {
|
|
31
|
+
const maybeExtender = getOperationExtender(errorItem);
|
|
32
|
+
if (maybeExtender) {
|
|
33
|
+
operationExtenders.push(maybeExtender);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (isProcedure(procedure)) {
|
|
37
|
+
for (const middleware of procedure["~orpc"].middlewares) {
|
|
38
|
+
const maybeExtender = getOperationExtender(middleware);
|
|
39
|
+
if (maybeExtender) {
|
|
40
|
+
operationExtenders.push(maybeExtender);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
let currentOperation = operation;
|
|
45
|
+
for (const extender of operationExtenders) {
|
|
46
|
+
if (typeof extender === "function") {
|
|
47
|
+
currentOperation = extender(currentOperation, procedure);
|
|
48
|
+
} else {
|
|
49
|
+
currentOperation = {
|
|
50
|
+
...currentOperation,
|
|
51
|
+
...extender
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return currentOperation;
|
|
56
|
+
}
|
|
8
57
|
|
|
9
|
-
|
|
10
|
-
import { findDeepMatches } from "@orpc/shared";
|
|
11
|
-
var OpenAPIContentBuilder = class {
|
|
58
|
+
class OpenAPIContentBuilder {
|
|
12
59
|
constructor(schemaUtils) {
|
|
13
60
|
this.schemaUtils = schemaUtils;
|
|
14
61
|
}
|
|
@@ -31,20 +78,12 @@ var OpenAPIContentBuilder = class {
|
|
|
31
78
|
}
|
|
32
79
|
return content;
|
|
33
80
|
}
|
|
34
|
-
}
|
|
81
|
+
}
|
|
35
82
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
import { eachAllContractProcedure } from "@orpc/server";
|
|
39
|
-
import { group } from "@orpc/shared";
|
|
83
|
+
class OpenAPIError extends Error {
|
|
84
|
+
}
|
|
40
85
|
|
|
41
|
-
|
|
42
|
-
var OpenAPIError = class extends Error {
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// src/openapi-input-structure-parser.ts
|
|
46
|
-
import { fallbackContractConfig } from "@orpc/contract";
|
|
47
|
-
var OpenAPIInputStructureParser = class {
|
|
86
|
+
class OpenAPIInputStructureParser {
|
|
48
87
|
constructor(schemaConverter, schemaUtils, pathParser) {
|
|
49
88
|
this.schemaConverter = schemaConverter;
|
|
50
89
|
this.schemaUtils = schemaUtils;
|
|
@@ -135,10 +174,9 @@ var OpenAPIInputStructureParser = class {
|
|
|
135
174
|
bodySchema: method !== "GET" ? rest : void 0
|
|
136
175
|
};
|
|
137
176
|
}
|
|
138
|
-
}
|
|
177
|
+
}
|
|
139
178
|
|
|
140
|
-
|
|
141
|
-
var OpenAPIOutputStructureParser = class {
|
|
179
|
+
class OpenAPIOutputStructureParser {
|
|
142
180
|
constructor(schemaConverter, schemaUtils) {
|
|
143
181
|
this.schemaConverter = schemaConverter;
|
|
144
182
|
this.schemaUtils = schemaUtils;
|
|
@@ -180,17 +218,15 @@ var OpenAPIOutputStructureParser = class {
|
|
|
180
218
|
bodySchema: outputSchema
|
|
181
219
|
};
|
|
182
220
|
}
|
|
183
|
-
}
|
|
221
|
+
}
|
|
184
222
|
|
|
185
|
-
|
|
186
|
-
import { get, isPlainObject, omit } from "@orpc/shared";
|
|
187
|
-
var OpenAPIParametersBuilder = class {
|
|
223
|
+
class OpenAPIParametersBuilder {
|
|
188
224
|
build(paramIn, jsonSchema, options) {
|
|
189
225
|
const parameters = [];
|
|
190
226
|
for (const name in jsonSchema.properties) {
|
|
191
227
|
const schema = jsonSchema.properties[name];
|
|
192
228
|
const paramExamples = jsonSchema.examples?.filter((example) => {
|
|
193
|
-
return
|
|
229
|
+
return isObject(example) && name in example;
|
|
194
230
|
}).map((example) => {
|
|
195
231
|
return example[name];
|
|
196
232
|
});
|
|
@@ -218,10 +254,9 @@ var OpenAPIParametersBuilder = class {
|
|
|
218
254
|
}
|
|
219
255
|
return headersObject;
|
|
220
256
|
}
|
|
221
|
-
}
|
|
257
|
+
}
|
|
222
258
|
|
|
223
|
-
|
|
224
|
-
var OpenAPIPathParser = class {
|
|
259
|
+
class OpenAPIPathParser {
|
|
225
260
|
parseDynamicParams(path) {
|
|
226
261
|
const raws = path.match(/\{([^}]+)\}/g) ?? [];
|
|
227
262
|
return raws.map((raw) => {
|
|
@@ -229,10 +264,9 @@ var OpenAPIPathParser = class {
|
|
|
229
264
|
return { name, raw };
|
|
230
265
|
});
|
|
231
266
|
}
|
|
232
|
-
}
|
|
267
|
+
}
|
|
233
268
|
|
|
234
|
-
|
|
235
|
-
var CompositeSchemaConverter = class {
|
|
269
|
+
class CompositeSchemaConverter {
|
|
236
270
|
converters;
|
|
237
271
|
constructor(converters) {
|
|
238
272
|
this.converters = converters;
|
|
@@ -248,15 +282,9 @@ var CompositeSchemaConverter = class {
|
|
|
248
282
|
}
|
|
249
283
|
return {};
|
|
250
284
|
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// src/schema-utils.ts
|
|
254
|
-
import { isPlainObject as isPlainObject2 } from "@orpc/shared";
|
|
285
|
+
}
|
|
255
286
|
|
|
256
|
-
|
|
257
|
-
import * as JSONSchema from "json-schema-typed/draft-2020-12";
|
|
258
|
-
import { Format } from "json-schema-typed/draft-2020-12";
|
|
259
|
-
var NON_LOGIC_KEYWORDS = [
|
|
287
|
+
const NON_LOGIC_KEYWORDS = [
|
|
260
288
|
// Core Documentation Keywords
|
|
261
289
|
"$anchor",
|
|
262
290
|
"$comment",
|
|
@@ -284,13 +312,12 @@ var NON_LOGIC_KEYWORDS = [
|
|
|
284
312
|
"$dynamicRef"
|
|
285
313
|
];
|
|
286
314
|
|
|
287
|
-
|
|
288
|
-
var SchemaUtils = class {
|
|
315
|
+
class SchemaUtils {
|
|
289
316
|
isFileSchema(schema) {
|
|
290
|
-
return
|
|
317
|
+
return isObject(schema) && schema.type === "string" && typeof schema.contentMediaType === "string";
|
|
291
318
|
}
|
|
292
319
|
isObjectSchema(schema) {
|
|
293
|
-
return
|
|
320
|
+
return isObject(schema) && schema.type === "object";
|
|
294
321
|
}
|
|
295
322
|
isAnySchema(schema) {
|
|
296
323
|
return schema === true || Object.keys(schema).filter((key) => !NON_LOGIC_KEYWORDS.includes(key)).length === 0;
|
|
@@ -313,7 +340,7 @@ var SchemaUtils = class {
|
|
|
313
340
|
}, {});
|
|
314
341
|
matched.required = schema.required?.filter((key) => separatedProperties.includes(key));
|
|
315
342
|
matched.examples = schema.examples?.map((example) => {
|
|
316
|
-
if (!
|
|
343
|
+
if (!isObject(example)) {
|
|
317
344
|
return example;
|
|
318
345
|
}
|
|
319
346
|
return Object.entries(example).reduce((acc, [key, value]) => {
|
|
@@ -329,7 +356,7 @@ var SchemaUtils = class {
|
|
|
329
356
|
}, {});
|
|
330
357
|
rest.required = schema.required?.filter((key) => !separatedProperties.includes(key));
|
|
331
358
|
rest.examples = schema.examples?.map((example) => {
|
|
332
|
-
if (!
|
|
359
|
+
if (!isObject(example)) {
|
|
333
360
|
return example;
|
|
334
361
|
}
|
|
335
362
|
return Object.entries(example).reduce((acc, [key, value]) => {
|
|
@@ -369,10 +396,9 @@ var SchemaUtils = class {
|
|
|
369
396
|
}
|
|
370
397
|
return [matches, schema];
|
|
371
398
|
}
|
|
372
|
-
}
|
|
399
|
+
}
|
|
373
400
|
|
|
374
|
-
|
|
375
|
-
var OpenAPIGenerator = class {
|
|
401
|
+
class OpenAPIGenerator {
|
|
376
402
|
contentBuilder;
|
|
377
403
|
parametersBuilder;
|
|
378
404
|
schemaConverter;
|
|
@@ -389,7 +415,7 @@ var OpenAPIGenerator = class {
|
|
|
389
415
|
this.parametersBuilder = options?.parametersBuilder ?? new OpenAPIParametersBuilder();
|
|
390
416
|
this.schemaConverter = new CompositeSchemaConverter(options?.schemaConverters ?? []);
|
|
391
417
|
this.schemaUtils = options?.schemaUtils ?? new SchemaUtils();
|
|
392
|
-
this.jsonSerializer = options?.jsonSerializer ?? new
|
|
418
|
+
this.jsonSerializer = options?.jsonSerializer ?? new OpenAPIJsonSerializer();
|
|
393
419
|
this.contentBuilder = options?.contentBuilder ?? new OpenAPIContentBuilder(this.schemaUtils);
|
|
394
420
|
this.pathParser = new OpenAPIPathParser();
|
|
395
421
|
this.inputStructureParser = options?.inputStructureParser ?? new OpenAPIInputStructureParser(this.schemaConverter, this.schemaUtils, this.pathParser);
|
|
@@ -414,28 +440,125 @@ var OpenAPIGenerator = class {
|
|
|
414
440
|
if (this.ignoreUndefinedPathProcedures && def.route?.path === void 0) {
|
|
415
441
|
return;
|
|
416
442
|
}
|
|
417
|
-
const method =
|
|
418
|
-
const httpPath = def.route?.path ?
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
443
|
+
const method = fallbackContractConfig("defaultMethod", def.route?.method);
|
|
444
|
+
const httpPath = def.route?.path ? toOpenAPI31RoutePattern(def.route?.path) : `/${path.map(encodeURIComponent).join("/")}`;
|
|
445
|
+
const { parameters, requestBody } = (() => {
|
|
446
|
+
const eventIteratorSchemaDetails = getEventIteratorSchemaDetails(def.inputSchema);
|
|
447
|
+
if (eventIteratorSchemaDetails) {
|
|
448
|
+
const requestBody3 = {
|
|
449
|
+
required: true,
|
|
450
|
+
content: {
|
|
451
|
+
"text/event-stream": {
|
|
452
|
+
schema: {
|
|
453
|
+
oneOf: [
|
|
454
|
+
{
|
|
455
|
+
type: "object",
|
|
456
|
+
properties: {
|
|
457
|
+
event: { type: "string", const: "message" },
|
|
458
|
+
data: this.schemaConverter.convert(eventIteratorSchemaDetails.yields, { strategy: "input" }),
|
|
459
|
+
id: { type: "string" },
|
|
460
|
+
retry: { type: "number" }
|
|
461
|
+
},
|
|
462
|
+
required: ["event", "data"]
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
type: "object",
|
|
466
|
+
properties: {
|
|
467
|
+
event: { type: "string", const: "done" },
|
|
468
|
+
data: this.schemaConverter.convert(eventIteratorSchemaDetails.returns, { strategy: "input" }),
|
|
469
|
+
id: { type: "string" },
|
|
470
|
+
retry: { type: "number" }
|
|
471
|
+
},
|
|
472
|
+
required: ["event", "data"]
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
type: "object",
|
|
476
|
+
properties: {
|
|
477
|
+
event: { type: "string", const: "error" },
|
|
478
|
+
data: {},
|
|
479
|
+
id: { type: "string" },
|
|
480
|
+
retry: { type: "number" }
|
|
481
|
+
},
|
|
482
|
+
required: ["event", "data"]
|
|
483
|
+
}
|
|
484
|
+
]
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
return { requestBody: requestBody3, parameters: [] };
|
|
490
|
+
}
|
|
491
|
+
const inputStructure = fallbackContractConfig("defaultInputStructure", def.route?.inputStructure);
|
|
492
|
+
const { paramsSchema, querySchema, headersSchema, bodySchema } = this.inputStructureParser.parse(contract, inputStructure);
|
|
493
|
+
const params = paramsSchema ? this.parametersBuilder.build("path", paramsSchema, {
|
|
494
|
+
required: true
|
|
495
|
+
}) : [];
|
|
496
|
+
const query = querySchema ? this.parametersBuilder.build("query", querySchema) : [];
|
|
497
|
+
const headers = headersSchema ? this.parametersBuilder.build("header", headersSchema) : [];
|
|
498
|
+
const parameters2 = [...params, ...query, ...headers];
|
|
499
|
+
const requestBody2 = bodySchema !== void 0 ? {
|
|
500
|
+
required: this.schemaUtils.isUndefinableSchema(bodySchema),
|
|
501
|
+
content: this.contentBuilder.build(bodySchema)
|
|
502
|
+
} : void 0;
|
|
503
|
+
return { parameters: parameters2, requestBody: requestBody2 };
|
|
504
|
+
})();
|
|
505
|
+
const { responses } = (() => {
|
|
506
|
+
const eventIteratorSchemaDetails = getEventIteratorSchemaDetails(def.outputSchema);
|
|
507
|
+
if (eventIteratorSchemaDetails) {
|
|
508
|
+
const responses3 = {};
|
|
509
|
+
responses3[fallbackContractConfig("defaultSuccessStatus", def.route?.successStatus)] = {
|
|
510
|
+
description: fallbackContractConfig("defaultSuccessDescription", def.route?.successDescription),
|
|
511
|
+
content: {
|
|
512
|
+
"text/event-stream": {
|
|
513
|
+
schema: {
|
|
514
|
+
oneOf: [
|
|
515
|
+
{
|
|
516
|
+
type: "object",
|
|
517
|
+
properties: {
|
|
518
|
+
event: { type: "string", const: "message" },
|
|
519
|
+
data: this.schemaConverter.convert(eventIteratorSchemaDetails.yields, { strategy: "input" }),
|
|
520
|
+
id: { type: "string" },
|
|
521
|
+
retry: { type: "number" }
|
|
522
|
+
},
|
|
523
|
+
required: ["event", "data"]
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
type: "object",
|
|
527
|
+
properties: {
|
|
528
|
+
event: { type: "string", const: "done" },
|
|
529
|
+
data: this.schemaConverter.convert(eventIteratorSchemaDetails.returns, { strategy: "input" }),
|
|
530
|
+
id: { type: "string" },
|
|
531
|
+
retry: { type: "number" }
|
|
532
|
+
},
|
|
533
|
+
required: ["event", "data"]
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
type: "object",
|
|
537
|
+
properties: {
|
|
538
|
+
event: { type: "string", const: "error" },
|
|
539
|
+
data: {},
|
|
540
|
+
id: { type: "string" },
|
|
541
|
+
retry: { type: "number" }
|
|
542
|
+
},
|
|
543
|
+
required: ["event", "data"]
|
|
544
|
+
}
|
|
545
|
+
]
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
return { responses: responses3 };
|
|
551
|
+
}
|
|
552
|
+
const outputStructure = fallbackContractConfig("defaultOutputStructure", def.route?.outputStructure);
|
|
553
|
+
const { headersSchema: resHeadersSchema, bodySchema: resBodySchema } = this.outputStructureParser.parse(contract, outputStructure);
|
|
554
|
+
const responses2 = {};
|
|
555
|
+
responses2[fallbackContractConfig("defaultSuccessStatus", def.route?.successStatus)] = {
|
|
556
|
+
description: fallbackContractConfig("defaultSuccessDescription", def.route?.successDescription),
|
|
557
|
+
content: resBodySchema !== void 0 ? this.contentBuilder.build(resBodySchema) : void 0,
|
|
558
|
+
headers: resHeadersSchema !== void 0 ? this.parametersBuilder.buildHeadersObject(resHeadersSchema) : void 0
|
|
559
|
+
};
|
|
560
|
+
return { responses: responses2 };
|
|
561
|
+
})();
|
|
439
562
|
const errors = group(Object.entries(def.errorMap ?? {}).filter(([_, config]) => config).map(([code, config]) => ({
|
|
440
563
|
...config,
|
|
441
564
|
code,
|
|
@@ -506,8 +629,9 @@ var OpenAPIGenerator = class {
|
|
|
506
629
|
requestBody,
|
|
507
630
|
responses
|
|
508
631
|
};
|
|
632
|
+
const extendedOperation = extendOperation(operation, contract);
|
|
509
633
|
builder.addPath(httpPath, {
|
|
510
|
-
[method.toLocaleLowerCase()]:
|
|
634
|
+
[method.toLocaleLowerCase()]: extendedOperation
|
|
511
635
|
});
|
|
512
636
|
} catch (e) {
|
|
513
637
|
if (e instanceof OpenAPIError) {
|
|
@@ -526,21 +650,12 @@ var OpenAPIGenerator = class {
|
|
|
526
650
|
}
|
|
527
651
|
}
|
|
528
652
|
});
|
|
529
|
-
return this.jsonSerializer.serialize(builder.getSpec());
|
|
653
|
+
return this.jsonSerializer.serialize(builder.getSpec())[0];
|
|
530
654
|
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
const oo = {
|
|
658
|
+
spec: setOperationExtender
|
|
531
659
|
};
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
JSONSchema,
|
|
535
|
-
Format as JSONSchemaFormat,
|
|
536
|
-
JSONSerializer,
|
|
537
|
-
NON_LOGIC_KEYWORDS,
|
|
538
|
-
OpenAPIContentBuilder,
|
|
539
|
-
OpenAPIGenerator,
|
|
540
|
-
OpenAPIParametersBuilder,
|
|
541
|
-
OpenAPIPathParser,
|
|
542
|
-
OpenApiBuilder,
|
|
543
|
-
SchemaUtils,
|
|
544
|
-
standardizeHTTPPath
|
|
545
|
-
};
|
|
546
|
-
//# sourceMappingURL=index.js.map
|
|
660
|
+
|
|
661
|
+
export { CompositeSchemaConverter, NON_LOGIC_KEYWORDS, OpenAPIContentBuilder, OpenAPIGenerator, OpenAPIParametersBuilder, OpenAPIPathParser, SchemaUtils, extendOperation, getOperationExtender, oo, setOperationExtender, toOpenAPI31RoutePattern };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
function standardizeHTTPPath(path) {
|
|
2
|
+
return `/${path.replace(/\/{2,}/g, "/").replace(/^\/|\/$/g, "")}`;
|
|
3
|
+
}
|
|
4
|
+
function toOpenAPI31RoutePattern(path) {
|
|
5
|
+
return standardizeHTTPPath(path).replace(/\{\+([^}]+)\}/g, "{$1}");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export { standardizeHTTPPath as s, toOpenAPI31RoutePattern as t };
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { fallbackContractConfig } from '@orpc/contract';
|
|
2
|
+
import { OpenAPISerializer } from '@orpc/openapi-client/standard';
|
|
3
|
+
import { isObject } from '@orpc/shared';
|
|
4
|
+
import { eachContractProcedure, convertPathToHttpPath, isProcedure, getLazyRouterPrefix, unlazy, getRouterChild, createContractedProcedure } from '@orpc/server';
|
|
5
|
+
import { createRouter, addRoute, findRoute } from 'rou3';
|
|
6
|
+
import { s as standardizeHTTPPath } from './openapi.BHG_gu5Z.mjs';
|
|
7
|
+
|
|
8
|
+
class OpenAPICodec {
|
|
9
|
+
constructor(serializer = new OpenAPISerializer()) {
|
|
10
|
+
this.serializer = serializer;
|
|
11
|
+
}
|
|
12
|
+
async decode(request, params, procedure) {
|
|
13
|
+
const inputStructure = fallbackContractConfig("defaultInputStructure", procedure["~orpc"].route.inputStructure);
|
|
14
|
+
if (inputStructure === "compact") {
|
|
15
|
+
const data = request.method === "GET" ? this.serializer.deserialize(request.url.searchParams) : this.serializer.deserialize(await request.body());
|
|
16
|
+
if (data === void 0) {
|
|
17
|
+
return params;
|
|
18
|
+
}
|
|
19
|
+
if (isObject(data)) {
|
|
20
|
+
return {
|
|
21
|
+
...params,
|
|
22
|
+
...data
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return data;
|
|
26
|
+
}
|
|
27
|
+
const deserializeSearchParams = () => {
|
|
28
|
+
return this.serializer.deserialize(request.url.searchParams);
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
params,
|
|
32
|
+
get query() {
|
|
33
|
+
const value = deserializeSearchParams();
|
|
34
|
+
Object.defineProperty(this, "query", { value, writable: true });
|
|
35
|
+
return value;
|
|
36
|
+
},
|
|
37
|
+
set query(value) {
|
|
38
|
+
Object.defineProperty(this, "query", { value, writable: true });
|
|
39
|
+
},
|
|
40
|
+
headers: request.headers,
|
|
41
|
+
body: this.serializer.deserialize(await request.body())
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
encode(output, procedure) {
|
|
45
|
+
const successStatus = fallbackContractConfig("defaultSuccessStatus", procedure["~orpc"].route.successStatus);
|
|
46
|
+
const outputStructure = fallbackContractConfig("defaultOutputStructure", procedure["~orpc"].route.outputStructure);
|
|
47
|
+
if (outputStructure === "compact") {
|
|
48
|
+
return {
|
|
49
|
+
status: successStatus,
|
|
50
|
+
headers: {},
|
|
51
|
+
body: this.serializer.serialize(output)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (!isObject(output)) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
'Invalid output structure for "detailed" output. Expected format: { body: any, headers?: Record<string, string | string[] | undefined> }'
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
status: successStatus,
|
|
61
|
+
headers: output.headers ?? {},
|
|
62
|
+
body: this.serializer.serialize(output.body)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
encodeError(error) {
|
|
66
|
+
return {
|
|
67
|
+
status: error.status,
|
|
68
|
+
headers: {},
|
|
69
|
+
body: this.serializer.serialize(error.toJSON())
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
class OpenAPIMatcher {
|
|
75
|
+
tree = createRouter();
|
|
76
|
+
pendingRouters = [];
|
|
77
|
+
init(router, path = []) {
|
|
78
|
+
const laziedOptions = eachContractProcedure({
|
|
79
|
+
router,
|
|
80
|
+
path
|
|
81
|
+
}, ({ path: path2, contract }) => {
|
|
82
|
+
const method = fallbackContractConfig("defaultMethod", contract["~orpc"].route.method);
|
|
83
|
+
const httpPath = contract["~orpc"].route.path ? toRou3Pattern(contract["~orpc"].route.path) : convertPathToHttpPath(path2);
|
|
84
|
+
if (isProcedure(contract)) {
|
|
85
|
+
addRoute(this.tree, method, httpPath, {
|
|
86
|
+
path: path2,
|
|
87
|
+
contract,
|
|
88
|
+
procedure: contract,
|
|
89
|
+
// this mean dev not used contract-first so we can used contract as procedure directly
|
|
90
|
+
router
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
addRoute(this.tree, method, httpPath, {
|
|
94
|
+
path: path2,
|
|
95
|
+
contract,
|
|
96
|
+
procedure: void 0,
|
|
97
|
+
router
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
this.pendingRouters.push(...laziedOptions.map((option) => ({
|
|
102
|
+
...option,
|
|
103
|
+
httpPathPrefix: convertPathToHttpPath(option.path),
|
|
104
|
+
laziedPrefix: getLazyRouterPrefix(option.lazied)
|
|
105
|
+
})));
|
|
106
|
+
}
|
|
107
|
+
async match(method, pathname) {
|
|
108
|
+
if (this.pendingRouters.length) {
|
|
109
|
+
const newPendingRouters = [];
|
|
110
|
+
for (const pendingRouter of this.pendingRouters) {
|
|
111
|
+
if (!pendingRouter.laziedPrefix || pathname.startsWith(pendingRouter.laziedPrefix) || pathname.startsWith(pendingRouter.httpPathPrefix)) {
|
|
112
|
+
const { default: router } = await unlazy(pendingRouter.lazied);
|
|
113
|
+
this.init(router, pendingRouter.path);
|
|
114
|
+
} else {
|
|
115
|
+
newPendingRouters.push(pendingRouter);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
this.pendingRouters = newPendingRouters;
|
|
119
|
+
}
|
|
120
|
+
const match = findRoute(this.tree, method, pathname);
|
|
121
|
+
if (!match) {
|
|
122
|
+
return void 0;
|
|
123
|
+
}
|
|
124
|
+
if (!match.data.procedure) {
|
|
125
|
+
const { default: maybeProcedure } = await unlazy(getRouterChild(match.data.router, ...match.data.path));
|
|
126
|
+
if (!isProcedure(maybeProcedure)) {
|
|
127
|
+
throw new Error(`
|
|
128
|
+
[Contract-First] Missing or invalid implementation for procedure at path: ${convertPathToHttpPath(match.data.path)}.
|
|
129
|
+
Ensure that the procedure is correctly defined and matches the expected contract.
|
|
130
|
+
`);
|
|
131
|
+
}
|
|
132
|
+
match.data.procedure = createContractedProcedure(match.data.contract, maybeProcedure);
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
path: match.data.path,
|
|
136
|
+
procedure: match.data.procedure,
|
|
137
|
+
params: match.params ? decodeParams(match.params) : void 0
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function toRou3Pattern(path) {
|
|
142
|
+
return standardizeHTTPPath(path).replace(/\{\+([^}]+)\}/g, "**:$1").replace(/\{([^}]+)\}/g, ":$1");
|
|
143
|
+
}
|
|
144
|
+
function decodeParams(params) {
|
|
145
|
+
return Object.fromEntries(Object.entries(params).map(([key, value]) => [key, decodeURIComponent(value)]));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export { OpenAPICodec as O, OpenAPIMatcher as a };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { StandardHandler } from '@orpc/server/standard';
|
|
2
|
+
import { toStandardRequest, toFetchResponse } from '@orpc/standard-server-fetch';
|
|
3
|
+
import { a as OpenAPIMatcher, O as OpenAPICodec } from './openapi.CDsfPHgw.mjs';
|
|
4
|
+
|
|
5
|
+
class OpenAPIHandler {
|
|
6
|
+
standardHandler;
|
|
7
|
+
constructor(router, options) {
|
|
8
|
+
const matcher = options?.matcher ?? new OpenAPIMatcher();
|
|
9
|
+
const codec = options?.codec ?? new OpenAPICodec();
|
|
10
|
+
this.standardHandler = new StandardHandler(router, matcher, codec, options);
|
|
11
|
+
}
|
|
12
|
+
async handle(request, ...[options]) {
|
|
13
|
+
const standardRequest = toStandardRequest(request);
|
|
14
|
+
const result = await this.standardHandler.handle(standardRequest, options);
|
|
15
|
+
if (!result.matched) {
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
matched: true,
|
|
20
|
+
response: toFetchResponse(result.response, options)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { OpenAPIHandler as O };
|