@orpc/openapi 0.0.0-next.9588d75 → 0.0.0-next.9914009
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-EVWWILO6.js +25 -0
- package/dist/chunk-KNYXLM77.js +107 -0
- package/dist/{chunk-UPDKQRQG.js → chunk-X2HG5K4J.js} +178 -192
- package/dist/fetch.js +10 -7
- package/dist/hono.js +34 -0
- package/dist/index.js +445 -4503
- 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/adapters/fetch/openapi-handler.d.ts +32 -0
- package/dist/src/{fetch → adapters/fetch}/openapi-payload-codec.d.ts +4 -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/index.d.ts +10 -1
- package/dist/src/json-serializer.d.ts +5 -0
- package/dist/src/openapi-content-builder.d.ts +10 -0
- package/dist/src/openapi-error.d.ts +3 -0
- package/dist/src/openapi-generator.d.ts +67 -0
- 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 +12 -0
- package/dist/src/openapi-path-parser.d.ts +8 -0
- package/dist/src/openapi.d.ts +3 -0
- package/dist/src/schema-converter.d.ts +16 -0
- package/dist/src/schema-utils.d.ts +11 -0
- package/dist/src/schema.d.ts +12 -0
- package/dist/src/utils.d.ts +1 -0
- package/package.json +21 -6
- package/dist/src/fetch/input-builder-simple.d.ts +0 -6
- package/dist/src/fetch/openapi-handler.d.ts +0 -28
- package/dist/src/generator.d.ts +0 -26
- package/dist/src/zod-to-json-schema.d.ts +0 -43
- /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
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OpenAPIHandler
|
|
3
|
+
} from "./chunk-X2HG5K4J.js";
|
|
4
|
+
|
|
5
|
+
// src/adapters/fetch/openapi-handler-server.ts
|
|
6
|
+
import { TrieRouter } from "hono/router/trie-router";
|
|
7
|
+
var OpenAPIServerHandler = class extends OpenAPIHandler {
|
|
8
|
+
constructor(router, options) {
|
|
9
|
+
super(new TrieRouter(), router, options);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/adapters/fetch/openapi-handler-serverless.ts
|
|
14
|
+
import { LinearRouter } from "hono/router/linear-router";
|
|
15
|
+
var OpenAPIServerlessHandler = class extends OpenAPIHandler {
|
|
16
|
+
constructor(router, options) {
|
|
17
|
+
super(new LinearRouter(), router, options);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
OpenAPIServerHandler,
|
|
23
|
+
OpenAPIServerlessHandler
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=chunk-EVWWILO6.js.map
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/json-serializer.ts
|
|
2
|
+
import { isPlainObject } from "@orpc/shared";
|
|
3
|
+
var JSONSerializer = class {
|
|
4
|
+
serialize(payload) {
|
|
5
|
+
if (payload instanceof Set)
|
|
6
|
+
return this.serialize([...payload]);
|
|
7
|
+
if (payload instanceof Map)
|
|
8
|
+
return this.serialize([...payload.entries()]);
|
|
9
|
+
if (Array.isArray(payload)) {
|
|
10
|
+
return payload.map((v) => v === void 0 ? "undefined" : this.serialize(v));
|
|
11
|
+
}
|
|
12
|
+
if (Number.isNaN(payload))
|
|
13
|
+
return "NaN";
|
|
14
|
+
if (typeof payload === "bigint")
|
|
15
|
+
return payload.toString();
|
|
16
|
+
if (payload instanceof Date && Number.isNaN(payload.getTime())) {
|
|
17
|
+
return "Invalid Date";
|
|
18
|
+
}
|
|
19
|
+
if (payload instanceof RegExp)
|
|
20
|
+
return payload.toString();
|
|
21
|
+
if (payload instanceof URL)
|
|
22
|
+
return payload.toString();
|
|
23
|
+
if (!isPlainObject(payload))
|
|
24
|
+
return payload;
|
|
25
|
+
return Object.keys(payload).reduce(
|
|
26
|
+
(carry, key) => {
|
|
27
|
+
const val = payload[key];
|
|
28
|
+
carry[key] = this.serialize(val);
|
|
29
|
+
return carry;
|
|
30
|
+
},
|
|
31
|
+
{}
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// src/utils.ts
|
|
37
|
+
import { isContractProcedure } from "@orpc/contract";
|
|
38
|
+
import { getRouterContract, isLazy, isProcedure, unlazy } from "@orpc/server";
|
|
39
|
+
function forEachContractProcedure(options, callback, result = [], isCurrentRouterContract = false) {
|
|
40
|
+
const hiddenContract = getRouterContract(options.router);
|
|
41
|
+
if (!isCurrentRouterContract && hiddenContract) {
|
|
42
|
+
return forEachContractProcedure(
|
|
43
|
+
{
|
|
44
|
+
path: options.path,
|
|
45
|
+
router: hiddenContract
|
|
46
|
+
},
|
|
47
|
+
callback,
|
|
48
|
+
result,
|
|
49
|
+
true
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (isLazy(options.router)) {
|
|
53
|
+
result.push({
|
|
54
|
+
router: options.router,
|
|
55
|
+
path: options.path
|
|
56
|
+
});
|
|
57
|
+
} else if (isProcedure(options.router)) {
|
|
58
|
+
callback({
|
|
59
|
+
contract: options.router["~orpc"].contract,
|
|
60
|
+
path: options.path
|
|
61
|
+
});
|
|
62
|
+
} else if (isContractProcedure(options.router)) {
|
|
63
|
+
callback({
|
|
64
|
+
contract: options.router,
|
|
65
|
+
path: options.path
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
for (const key in options.router) {
|
|
69
|
+
forEachContractProcedure(
|
|
70
|
+
{
|
|
71
|
+
router: options.router[key],
|
|
72
|
+
path: [...options.path, key]
|
|
73
|
+
},
|
|
74
|
+
callback,
|
|
75
|
+
result
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
async function forEachAllContractProcedure(router, callback) {
|
|
82
|
+
const pending = [{
|
|
83
|
+
path: [],
|
|
84
|
+
router
|
|
85
|
+
}];
|
|
86
|
+
for (const item of pending) {
|
|
87
|
+
const lazies = forEachContractProcedure(item, callback);
|
|
88
|
+
for (const lazy of lazies) {
|
|
89
|
+
const { default: router2 } = await unlazy(lazy.router);
|
|
90
|
+
pending.push({
|
|
91
|
+
path: lazy.path,
|
|
92
|
+
router: router2
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function standardizeHTTPPath(path) {
|
|
98
|
+
return `/${path.replace(/\/{2,}/g, "/").replace(/^\/|\/$/g, "")}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
JSONSerializer,
|
|
103
|
+
forEachContractProcedure,
|
|
104
|
+
forEachAllContractProcedure,
|
|
105
|
+
standardizeHTTPPath
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=chunk-KNYXLM77.js.map
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import {
|
|
2
|
+
JSONSerializer,
|
|
3
|
+
forEachContractProcedure,
|
|
4
|
+
standardizeHTTPPath
|
|
5
|
+
} from "./chunk-KNYXLM77.js";
|
|
6
|
+
|
|
7
|
+
// src/adapters/fetch/bracket-notation.ts
|
|
2
8
|
import { isPlainObject } from "@orpc/shared";
|
|
3
9
|
function serialize(payload, parentKey = "") {
|
|
4
10
|
if (!Array.isArray(payload) && !isPlainObject(payload))
|
|
@@ -207,21 +213,9 @@ function parsePath(path) {
|
|
|
207
213
|
return result;
|
|
208
214
|
}
|
|
209
215
|
|
|
210
|
-
// src/fetch/input-
|
|
211
|
-
var InputBuilderFull = class {
|
|
212
|
-
build(params, query, headers, body) {
|
|
213
|
-
return {
|
|
214
|
-
params,
|
|
215
|
-
query,
|
|
216
|
-
headers,
|
|
217
|
-
body
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
// src/fetch/input-builder-simple.ts
|
|
216
|
+
// src/adapters/fetch/input-structure-compact.ts
|
|
223
217
|
import { isPlainObject as isPlainObject2 } from "@orpc/shared";
|
|
224
|
-
var
|
|
218
|
+
var InputStructureCompact = class {
|
|
225
219
|
build(params, payload) {
|
|
226
220
|
if (Object.keys(params).length === 0) {
|
|
227
221
|
return payload;
|
|
@@ -236,17 +230,28 @@ var InputBuilderSimple = class {
|
|
|
236
230
|
}
|
|
237
231
|
};
|
|
238
232
|
|
|
239
|
-
// src/fetch/
|
|
240
|
-
|
|
241
|
-
|
|
233
|
+
// src/adapters/fetch/input-structure-detailed.ts
|
|
234
|
+
var InputStructureDetailed = class {
|
|
235
|
+
build(params, query, headers, body) {
|
|
236
|
+
return {
|
|
237
|
+
params,
|
|
238
|
+
query,
|
|
239
|
+
headers,
|
|
240
|
+
body
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
};
|
|
242
244
|
|
|
243
|
-
// src/fetch/openapi-payload-codec.ts
|
|
245
|
+
// src/adapters/fetch/openapi-payload-codec.ts
|
|
244
246
|
import { ORPCError } from "@orpc/server";
|
|
245
|
-
import { findDeepMatches
|
|
247
|
+
import { findDeepMatches } from "@orpc/shared";
|
|
246
248
|
import cd from "content-disposition";
|
|
247
249
|
import { safeParse } from "fast-content-type-parse";
|
|
248
250
|
import wcmatch from "wildcard-match";
|
|
249
251
|
var OpenAPIPayloadCodec = class {
|
|
252
|
+
constructor(jsonSerializer) {
|
|
253
|
+
this.jsonSerializer = jsonSerializer;
|
|
254
|
+
}
|
|
250
255
|
encode(payload, accept) {
|
|
251
256
|
const typeMatchers = (accept?.split(",").map(safeParse) ?? [{ type: "*/*" }]).map(({ type }) => wcmatch(type));
|
|
252
257
|
if (payload instanceof Blob) {
|
|
@@ -264,7 +269,7 @@ var OpenAPIPayloadCodec = class {
|
|
|
264
269
|
};
|
|
265
270
|
}
|
|
266
271
|
}
|
|
267
|
-
const handledPayload = this.serialize(payload);
|
|
272
|
+
const handledPayload = this.jsonSerializer.serialize(payload);
|
|
268
273
|
const hasBlobs = findDeepMatches((v) => v instanceof Blob, handledPayload).values.length > 0;
|
|
269
274
|
const isExpectedMultipartFormData = typeMatchers.some(
|
|
270
275
|
(isMatch) => isMatch("multipart/form-data")
|
|
@@ -345,129 +350,60 @@ var OpenAPIPayloadCodec = class {
|
|
|
345
350
|
})
|
|
346
351
|
};
|
|
347
352
|
}
|
|
348
|
-
serialize(payload) {
|
|
349
|
-
if (payload instanceof Set)
|
|
350
|
-
return this.serialize([...payload]);
|
|
351
|
-
if (payload instanceof Map)
|
|
352
|
-
return this.serialize([...payload.entries()]);
|
|
353
|
-
if (Array.isArray(payload)) {
|
|
354
|
-
return payload.map((v) => v === void 0 ? "undefined" : this.serialize(v));
|
|
355
|
-
}
|
|
356
|
-
if (Number.isNaN(payload))
|
|
357
|
-
return "NaN";
|
|
358
|
-
if (typeof payload === "bigint")
|
|
359
|
-
return payload.toString();
|
|
360
|
-
if (payload instanceof Date && Number.isNaN(payload.getTime())) {
|
|
361
|
-
return "Invalid Date";
|
|
362
|
-
}
|
|
363
|
-
if (payload instanceof RegExp)
|
|
364
|
-
return payload.toString();
|
|
365
|
-
if (payload instanceof URL)
|
|
366
|
-
return payload.toString();
|
|
367
|
-
if (!isPlainObject3(payload))
|
|
368
|
-
return payload;
|
|
369
|
-
return Object.keys(payload).reduce(
|
|
370
|
-
(carry, key) => {
|
|
371
|
-
const val = payload[key];
|
|
372
|
-
carry[key] = this.serialize(val);
|
|
373
|
-
return carry;
|
|
374
|
-
},
|
|
375
|
-
{}
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
353
|
async decode(re) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const contentType = re.headers.get("content-type");
|
|
383
|
-
const contentDisposition = re.headers.get("content-disposition");
|
|
384
|
-
const fileName = contentDisposition ? cd.parse(contentDisposition).parameters.filename : void 0;
|
|
385
|
-
if (fileName) {
|
|
386
|
-
const blob2 = await re.blob();
|
|
387
|
-
const file = new File([blob2], fileName, {
|
|
388
|
-
type: blob2.type
|
|
389
|
-
});
|
|
390
|
-
return file;
|
|
391
|
-
}
|
|
392
|
-
if (!contentType || contentType.startsWith("application/json")) {
|
|
393
|
-
if (!re.body) {
|
|
394
|
-
return void 0;
|
|
354
|
+
try {
|
|
355
|
+
if (re instanceof Headers || re instanceof URLSearchParams || re instanceof FormData) {
|
|
356
|
+
return deserialize([...re.entries()]);
|
|
395
357
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
358
|
+
const contentType = re.headers.get("content-type");
|
|
359
|
+
const contentDisposition = re.headers.get("content-disposition");
|
|
360
|
+
const fileName = contentDisposition ? cd.parse(contentDisposition).parameters.filename : void 0;
|
|
361
|
+
if (fileName) {
|
|
362
|
+
const blob2 = await re.blob();
|
|
363
|
+
const file = new File([blob2], fileName, {
|
|
364
|
+
type: blob2.type
|
|
365
|
+
});
|
|
366
|
+
return file;
|
|
367
|
+
}
|
|
368
|
+
if (!contentType || contentType.startsWith("application/json")) {
|
|
369
|
+
if (!re.body) {
|
|
370
|
+
return void 0;
|
|
371
|
+
}
|
|
372
|
+
const text = await re.text();
|
|
373
|
+
if (!text) {
|
|
374
|
+
return void 0;
|
|
375
|
+
}
|
|
376
|
+
return JSON.parse(text);
|
|
377
|
+
}
|
|
378
|
+
if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
379
|
+
const params = new URLSearchParams(await re.text());
|
|
380
|
+
return this.decode(params);
|
|
381
|
+
}
|
|
382
|
+
if (contentType.startsWith("text/")) {
|
|
383
|
+
const text = await re.text();
|
|
384
|
+
return text;
|
|
385
|
+
}
|
|
386
|
+
if (contentType.startsWith("multipart/form-data")) {
|
|
387
|
+
const form = await re.formData();
|
|
388
|
+
return this.decode(form);
|
|
389
|
+
}
|
|
390
|
+
const blob = await re.blob();
|
|
391
|
+
return new File([blob], "blob", {
|
|
392
|
+
type: blob.type
|
|
393
|
+
});
|
|
394
|
+
} catch (e) {
|
|
395
|
+
throw new ORPCError({
|
|
396
|
+
code: "BAD_REQUEST",
|
|
397
|
+
message: "Cannot parse request/response. Please check the request/response body and Content-Type header.",
|
|
398
|
+
cause: e
|
|
399
|
+
});
|
|
409
400
|
}
|
|
410
|
-
const blob = await re.blob();
|
|
411
|
-
return new File([blob], "blob", {
|
|
412
|
-
type: blob.type
|
|
413
|
-
});
|
|
414
401
|
}
|
|
415
402
|
};
|
|
416
403
|
|
|
417
|
-
// src/fetch/openapi-procedure-matcher.ts
|
|
418
|
-
import { getLazyRouterPrefix, getRouterChild, isProcedure
|
|
404
|
+
// src/adapters/fetch/openapi-procedure-matcher.ts
|
|
405
|
+
import { fallbackToGlobalConfig, getLazyRouterPrefix, getRouterChild, isProcedure, unlazy } from "@orpc/server";
|
|
419
406
|
import { mapValues } from "@orpc/shared";
|
|
420
|
-
|
|
421
|
-
// src/utils.ts
|
|
422
|
-
import { isContractProcedure } from "@orpc/contract";
|
|
423
|
-
import { getRouterContract, isLazy, isProcedure } from "@orpc/server";
|
|
424
|
-
function forEachContractProcedure(options, callback, result = [], isCurrentRouterContract = false) {
|
|
425
|
-
const hiddenContract = getRouterContract(options.router);
|
|
426
|
-
if (!isCurrentRouterContract && hiddenContract) {
|
|
427
|
-
return forEachContractProcedure(
|
|
428
|
-
{
|
|
429
|
-
path: options.path,
|
|
430
|
-
router: hiddenContract
|
|
431
|
-
},
|
|
432
|
-
callback,
|
|
433
|
-
result,
|
|
434
|
-
true
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
|
-
if (isLazy(options.router)) {
|
|
438
|
-
result.push({
|
|
439
|
-
router: options.router,
|
|
440
|
-
path: options.path
|
|
441
|
-
});
|
|
442
|
-
} else if (isProcedure(options.router)) {
|
|
443
|
-
callback({
|
|
444
|
-
contract: options.router["~orpc"].contract,
|
|
445
|
-
path: options.path
|
|
446
|
-
});
|
|
447
|
-
} else if (isContractProcedure(options.router)) {
|
|
448
|
-
callback({
|
|
449
|
-
contract: options.router,
|
|
450
|
-
path: options.path
|
|
451
|
-
});
|
|
452
|
-
} else {
|
|
453
|
-
for (const key in options.router) {
|
|
454
|
-
forEachContractProcedure(
|
|
455
|
-
{
|
|
456
|
-
router: options.router[key],
|
|
457
|
-
path: [...options.path, key]
|
|
458
|
-
},
|
|
459
|
-
callback,
|
|
460
|
-
result
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
return result;
|
|
465
|
-
}
|
|
466
|
-
function standardizeHTTPPath(path) {
|
|
467
|
-
return `/${path.replace(/\/{2,}/g, "/").replace(/^\/|\/$/g, "")}`;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// src/fetch/openapi-procedure-matcher.ts
|
|
471
407
|
var OpenAPIProcedureMatcher = class {
|
|
472
408
|
constructor(hono, router) {
|
|
473
409
|
this.hono = hono;
|
|
@@ -498,7 +434,7 @@ var OpenAPIProcedureMatcher = class {
|
|
|
498
434
|
(v) => paramStash[v]
|
|
499
435
|
) : match[1];
|
|
500
436
|
const { default: maybeProcedure } = await unlazy(getRouterChild(this.router, ...path));
|
|
501
|
-
if (!
|
|
437
|
+
if (!isProcedure(maybeProcedure)) {
|
|
502
438
|
return void 0;
|
|
503
439
|
}
|
|
504
440
|
return {
|
|
@@ -510,7 +446,7 @@ var OpenAPIProcedureMatcher = class {
|
|
|
510
446
|
}
|
|
511
447
|
add(path, router) {
|
|
512
448
|
const lazies = forEachContractProcedure({ path, router }, ({ path: path2, contract }) => {
|
|
513
|
-
const method = contract["~orpc"].route?.method
|
|
449
|
+
const method = fallbackToGlobalConfig("defaultMethod", contract["~orpc"].route?.method);
|
|
514
450
|
const httpPath = contract["~orpc"].route?.path ? this.convertOpenAPIPathToRouterPath(contract["~orpc"].route?.path) : `/${path2.map(encodeURIComponent).join("/")}`;
|
|
515
451
|
this.hono.add(method, httpPath, [httpPath, path2]);
|
|
516
452
|
});
|
|
@@ -534,7 +470,7 @@ var OpenAPIProcedureMatcher = class {
|
|
|
534
470
|
}
|
|
535
471
|
};
|
|
536
472
|
|
|
537
|
-
// src/fetch/schema-coercer.ts
|
|
473
|
+
// src/adapters/fetch/schema-coercer.ts
|
|
538
474
|
var CompositeSchemaCoercer = class {
|
|
539
475
|
constructor(coercers) {
|
|
540
476
|
this.coercers = coercers;
|
|
@@ -548,49 +484,52 @@ var CompositeSchemaCoercer = class {
|
|
|
548
484
|
}
|
|
549
485
|
};
|
|
550
486
|
|
|
551
|
-
// src/fetch/openapi-handler.ts
|
|
487
|
+
// src/adapters/fetch/openapi-handler.ts
|
|
488
|
+
import { createProcedureClient, fallbackToGlobalConfig as fallbackToGlobalConfig2, ORPCError as ORPCError2 } from "@orpc/server";
|
|
489
|
+
import { executeWithHooks, isPlainObject as isPlainObject3, trim } from "@orpc/shared";
|
|
552
490
|
var OpenAPIHandler = class {
|
|
553
491
|
constructor(hono, router, options) {
|
|
554
492
|
this.options = options;
|
|
493
|
+
const jsonSerializer = options?.jsonSerializer ?? new JSONSerializer();
|
|
555
494
|
this.procedureMatcher = options?.procedureMatcher ?? new OpenAPIProcedureMatcher(hono, router);
|
|
556
|
-
this.payloadCodec = options?.payloadCodec ?? new OpenAPIPayloadCodec();
|
|
557
|
-
this.
|
|
558
|
-
this.
|
|
495
|
+
this.payloadCodec = options?.payloadCodec ?? new OpenAPIPayloadCodec(jsonSerializer);
|
|
496
|
+
this.inputStructureCompact = options?.inputBuilderSimple ?? new InputStructureCompact();
|
|
497
|
+
this.inputStructureDetailed = options?.inputBuilderFull ?? new InputStructureDetailed();
|
|
559
498
|
this.compositeSchemaCoercer = new CompositeSchemaCoercer(options?.schemaCoercers ?? []);
|
|
560
499
|
}
|
|
561
500
|
procedureMatcher;
|
|
562
501
|
payloadCodec;
|
|
563
|
-
|
|
564
|
-
|
|
502
|
+
inputStructureCompact;
|
|
503
|
+
inputStructureDetailed;
|
|
565
504
|
compositeSchemaCoercer;
|
|
566
|
-
|
|
567
|
-
return request.headers.get(ORPC_HANDLER_HEADER) === null;
|
|
568
|
-
}
|
|
569
|
-
async fetch(request, ...[options]) {
|
|
505
|
+
async handle(request, ...[options]) {
|
|
570
506
|
const context = options?.context;
|
|
571
507
|
const headers = request.headers;
|
|
572
|
-
const accept = headers.get("
|
|
508
|
+
const accept = headers.get("accept") || void 0;
|
|
573
509
|
const execute = async () => {
|
|
574
510
|
const url = new URL(request.url);
|
|
575
511
|
const pathname = `/${trim(url.pathname.replace(options?.prefix ?? "", ""), "/")}`;
|
|
576
512
|
const query = url.searchParams;
|
|
577
513
|
const customMethod = request.method === "POST" ? query.get("method")?.toUpperCase() : void 0;
|
|
578
|
-
const
|
|
579
|
-
const
|
|
580
|
-
if (!
|
|
581
|
-
|
|
514
|
+
const matchedMethod = customMethod || request.method;
|
|
515
|
+
const matched = await this.procedureMatcher.match(matchedMethod, pathname);
|
|
516
|
+
if (!matched) {
|
|
517
|
+
return { matched: false, response: void 0 };
|
|
582
518
|
}
|
|
583
|
-
const
|
|
584
|
-
const input = this.
|
|
585
|
-
const coercedInput = this.compositeSchemaCoercer.coerce(
|
|
586
|
-
const client = createProcedureClient({
|
|
519
|
+
const contractDef = matched.procedure["~orpc"].contract["~orpc"];
|
|
520
|
+
const input = await this.decodeInput(matched.procedure, matched.params, request);
|
|
521
|
+
const coercedInput = this.compositeSchemaCoercer.coerce(contractDef.InputSchema, input);
|
|
522
|
+
const client = createProcedureClient(matched.procedure, {
|
|
587
523
|
context,
|
|
588
|
-
|
|
589
|
-
|
|
524
|
+
path: matched.path
|
|
525
|
+
});
|
|
526
|
+
const output = await client(coercedInput, { signal: request.signal });
|
|
527
|
+
const { body, headers: resHeaders } = this.encodeOutput(matched.procedure, output, accept);
|
|
528
|
+
const response = new Response(body, {
|
|
529
|
+
headers: resHeaders,
|
|
530
|
+
status: fallbackToGlobalConfig2("defaultSuccessStatus", contractDef.route?.successStatus)
|
|
590
531
|
});
|
|
591
|
-
|
|
592
|
-
const { body, headers: headers2 } = this.payloadCodec.encode(output);
|
|
593
|
-
return new Response(body, { headers: headers2 });
|
|
532
|
+
return { matched: true, response };
|
|
594
533
|
};
|
|
595
534
|
try {
|
|
596
535
|
return await executeWithHooks({
|
|
@@ -599,27 +538,94 @@ var OpenAPIHandler = class {
|
|
|
599
538
|
input: request,
|
|
600
539
|
hooks: this.options,
|
|
601
540
|
meta: {
|
|
602
|
-
signal:
|
|
541
|
+
signal: request.signal
|
|
603
542
|
}
|
|
604
543
|
});
|
|
605
544
|
} catch (e) {
|
|
606
545
|
const error = this.convertToORPCError(e);
|
|
607
546
|
try {
|
|
608
547
|
const { body, headers: headers2 } = this.payloadCodec.encode(error.toJSON(), accept);
|
|
609
|
-
|
|
548
|
+
const response = new Response(body, {
|
|
610
549
|
status: error.status,
|
|
611
550
|
headers: headers2
|
|
612
551
|
});
|
|
552
|
+
return { matched: true, response };
|
|
613
553
|
} catch (e2) {
|
|
614
554
|
const error2 = this.convertToORPCError(e2);
|
|
615
|
-
const { body, headers: headers2 } = this.payloadCodec.encode(error2.toJSON());
|
|
616
|
-
|
|
555
|
+
const { body, headers: headers2 } = this.payloadCodec.encode(error2.toJSON(), void 0);
|
|
556
|
+
const response = new Response(body, {
|
|
617
557
|
status: error2.status,
|
|
618
558
|
headers: headers2
|
|
619
559
|
});
|
|
560
|
+
return { matched: true, response };
|
|
620
561
|
}
|
|
621
562
|
}
|
|
622
563
|
}
|
|
564
|
+
async decodeInput(procedure, params, request) {
|
|
565
|
+
const inputStructure = fallbackToGlobalConfig2("defaultInputStructure", procedure["~orpc"].contract["~orpc"].route?.inputStructure);
|
|
566
|
+
const url = new URL(request.url);
|
|
567
|
+
const query = url.searchParams;
|
|
568
|
+
const headers = request.headers;
|
|
569
|
+
if (inputStructure === "compact") {
|
|
570
|
+
return this.inputStructureCompact.build(
|
|
571
|
+
params,
|
|
572
|
+
request.method === "GET" ? await this.payloadCodec.decode(query) : await this.payloadCodec.decode(request)
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
const decodedQuery = await this.payloadCodec.decode(query);
|
|
576
|
+
const decodedHeaders = await this.payloadCodec.decode(headers);
|
|
577
|
+
const decodedBody = await this.payloadCodec.decode(request);
|
|
578
|
+
return this.inputStructureDetailed.build(params, decodedQuery, decodedHeaders, decodedBody);
|
|
579
|
+
}
|
|
580
|
+
encodeOutput(procedure, output, accept) {
|
|
581
|
+
const outputStructure = fallbackToGlobalConfig2("defaultOutputStructure", procedure["~orpc"].contract["~orpc"].route?.outputStructure);
|
|
582
|
+
if (outputStructure === "compact") {
|
|
583
|
+
return this.payloadCodec.encode(output, accept);
|
|
584
|
+
}
|
|
585
|
+
this.assertDetailedOutput(output);
|
|
586
|
+
const headers = new Headers();
|
|
587
|
+
if (output.headers) {
|
|
588
|
+
for (const [key, value] of Object.entries(output.headers)) {
|
|
589
|
+
headers.append(key, value);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
const { body, headers: encodedHeaders } = this.payloadCodec.encode(output.body, accept);
|
|
593
|
+
if (encodedHeaders) {
|
|
594
|
+
for (const [key, value] of encodedHeaders.entries()) {
|
|
595
|
+
headers.append(key, value);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return { body, headers };
|
|
599
|
+
}
|
|
600
|
+
assertDetailedOutput(output) {
|
|
601
|
+
const error = new Error(`
|
|
602
|
+
Invalid output structure for 'detailed' output.
|
|
603
|
+
Expected format:
|
|
604
|
+
{
|
|
605
|
+
body?: unknown; // The main response content (optional)
|
|
606
|
+
headers?: { // Additional headers (optional)
|
|
607
|
+
[key: string]: string;
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
Example:
|
|
612
|
+
{
|
|
613
|
+
body: { message: "Success" },
|
|
614
|
+
headers: { "X-Custom-Header": "Custom-Value" },
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
Fix: Ensure your output matches the expected structure.
|
|
618
|
+
`);
|
|
619
|
+
if (!isPlainObject3(output) || Object.keys(output).some((key) => key !== "body" && key !== "headers")) {
|
|
620
|
+
throw error;
|
|
621
|
+
}
|
|
622
|
+
if (output.headers !== void 0 && !isPlainObject3(output.headers)) {
|
|
623
|
+
throw error;
|
|
624
|
+
}
|
|
625
|
+
if (output.headers && Object.entries(output.headers).some(([key, value]) => typeof key !== "string" || typeof value !== "string")) {
|
|
626
|
+
throw error;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
623
629
|
convertToORPCError(e) {
|
|
624
630
|
return e instanceof ORPCError2 ? e : new ORPCError2({
|
|
625
631
|
code: "INTERNAL_SERVER_ERROR",
|
|
@@ -629,37 +635,17 @@ var OpenAPIHandler = class {
|
|
|
629
635
|
}
|
|
630
636
|
};
|
|
631
637
|
|
|
632
|
-
// src/fetch/openapi-handler-server.ts
|
|
633
|
-
import { TrieRouter } from "hono/router/trie-router";
|
|
634
|
-
var OpenAPIServerHandler = class extends OpenAPIHandler {
|
|
635
|
-
constructor(router, options) {
|
|
636
|
-
super(new TrieRouter(), router, options);
|
|
637
|
-
}
|
|
638
|
-
};
|
|
639
|
-
|
|
640
|
-
// src/fetch/openapi-handler-serverless.ts
|
|
641
|
-
import { LinearRouter } from "hono/router/linear-router";
|
|
642
|
-
var OpenAPIServerlessHandler = class extends OpenAPIHandler {
|
|
643
|
-
constructor(router, options) {
|
|
644
|
-
super(new LinearRouter(), router, options);
|
|
645
|
-
}
|
|
646
|
-
};
|
|
647
|
-
|
|
648
638
|
export {
|
|
649
639
|
serialize,
|
|
650
640
|
deserialize,
|
|
651
641
|
escapeSegment,
|
|
652
642
|
stringifyPath,
|
|
653
643
|
parsePath,
|
|
654
|
-
|
|
655
|
-
|
|
644
|
+
InputStructureCompact,
|
|
645
|
+
InputStructureDetailed,
|
|
656
646
|
OpenAPIPayloadCodec,
|
|
657
|
-
forEachContractProcedure,
|
|
658
|
-
standardizeHTTPPath,
|
|
659
647
|
OpenAPIProcedureMatcher,
|
|
660
648
|
CompositeSchemaCoercer,
|
|
661
|
-
OpenAPIHandler
|
|
662
|
-
OpenAPIServerHandler,
|
|
663
|
-
OpenAPIServerlessHandler
|
|
649
|
+
OpenAPIHandler
|
|
664
650
|
};
|
|
665
|
-
//# sourceMappingURL=chunk-
|
|
651
|
+
//# sourceMappingURL=chunk-X2HG5K4J.js.map
|
package/dist/fetch.js
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OpenAPIServerHandler,
|
|
3
|
+
OpenAPIServerlessHandler
|
|
4
|
+
} from "./chunk-EVWWILO6.js";
|
|
1
5
|
import {
|
|
2
6
|
CompositeSchemaCoercer,
|
|
3
|
-
|
|
4
|
-
|
|
7
|
+
InputStructureCompact,
|
|
8
|
+
InputStructureDetailed,
|
|
5
9
|
OpenAPIHandler,
|
|
6
10
|
OpenAPIPayloadCodec,
|
|
7
11
|
OpenAPIProcedureMatcher,
|
|
8
|
-
OpenAPIServerHandler,
|
|
9
|
-
OpenAPIServerlessHandler,
|
|
10
12
|
deserialize,
|
|
11
13
|
escapeSegment,
|
|
12
14
|
parsePath,
|
|
13
15
|
serialize,
|
|
14
16
|
stringifyPath
|
|
15
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-X2HG5K4J.js";
|
|
18
|
+
import "./chunk-KNYXLM77.js";
|
|
16
19
|
export {
|
|
17
20
|
CompositeSchemaCoercer,
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
InputStructureCompact,
|
|
22
|
+
InputStructureDetailed,
|
|
20
23
|
OpenAPIHandler,
|
|
21
24
|
OpenAPIPayloadCodec,
|
|
22
25
|
OpenAPIProcedureMatcher,
|