@orpc/openapi 0.0.0-next.d137cdf → 0.0.0-next.d42488d
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-KNYXLM77.js +107 -0
- package/dist/fetch.js +517 -632
- package/dist/index.js +258 -4337
- package/dist/src/fetch/bracket-notation.d.ts +84 -0
- package/dist/src/fetch/index.d.ts +9 -3
- package/dist/src/fetch/input-builder-full.d.ts +11 -0
- package/dist/src/fetch/input-builder-simple.d.ts +6 -0
- package/dist/src/fetch/openapi-handler-server.d.ts +7 -0
- package/dist/src/fetch/openapi-handler-serverless.d.ts +7 -0
- package/dist/src/fetch/openapi-handler.d.ts +30 -0
- package/dist/src/fetch/openapi-payload-codec.d.ts +15 -0
- package/dist/src/fetch/openapi-procedure-matcher.d.ts +19 -0
- package/dist/src/fetch/schema-coercer.d.ts +10 -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-generator.d.ts +51 -0
- package/dist/src/openapi-parameters-builder.d.ts +9 -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 +7 -5
- package/package.json +11 -8
- package/dist/chunk-KZIT2WCV.js +0 -49
- package/dist/src/fetch/base-handler.d.ts +0 -15
- package/dist/src/fetch/server-handler.d.ts +0 -3
- package/dist/src/fetch/serverless-handler.d.ts +0 -3
- package/dist/src/generator.d.ts +0 -24
- package/dist/src/zod-to-json-schema.d.ts +0 -43
package/dist/fetch.js
CHANGED
|
@@ -1,706 +1,591 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
JSONSerializer,
|
|
3
|
+
forEachContractProcedure,
|
|
4
|
+
standardizeHTTPPath
|
|
5
|
+
} from "./chunk-KNYXLM77.js";
|
|
4
6
|
|
|
5
|
-
// src/fetch/
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
const context = await value(options.context);
|
|
17
|
-
const accept = options.request.headers.get("Accept") || void 0;
|
|
18
|
-
const serializer = new OpenAPISerializer({ accept });
|
|
19
|
-
const handler = async () => {
|
|
20
|
-
const url = new URL(options.request.url);
|
|
21
|
-
const pathname = `/${trim(url.pathname.replace(options.prefix ?? "", ""), "/")}`;
|
|
22
|
-
const customMethod = options.request.method === "POST" ? url.searchParams.get("method")?.toUpperCase() : void 0;
|
|
23
|
-
const method = customMethod || options.request.method;
|
|
24
|
-
const match = await resolveRouter(options.router, method, pathname);
|
|
25
|
-
if (!match) {
|
|
26
|
-
throw new ORPCError({ code: "NOT_FOUND", message: "Not found" });
|
|
27
|
-
}
|
|
28
|
-
const procedure = isLazy(match.procedure) ? (await match.procedure[LAZY_LOADER_SYMBOL]()).default : match.procedure;
|
|
29
|
-
const path = match.path;
|
|
30
|
-
if (!isProcedure(procedure)) {
|
|
31
|
-
throw new ORPCError({
|
|
32
|
-
code: "NOT_FOUND",
|
|
33
|
-
message: "Not found"
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
const params = procedure.zz$p.contract.zz$cp.InputSchema ? zodCoerce(
|
|
37
|
-
procedure.zz$p.contract.zz$cp.InputSchema,
|
|
38
|
-
match.params,
|
|
39
|
-
{ bracketNotation: true }
|
|
40
|
-
) : match.params;
|
|
41
|
-
const input = await deserializeInput(options.request, procedure);
|
|
42
|
-
const mergedInput = mergeParamsAndInput(params, input);
|
|
43
|
-
const caller = createProcedureCaller({
|
|
44
|
-
context,
|
|
45
|
-
procedure,
|
|
46
|
-
path
|
|
47
|
-
});
|
|
48
|
-
const output = await caller(mergedInput);
|
|
49
|
-
const { body, headers } = serializer.serialize(output);
|
|
50
|
-
return new Response(body, {
|
|
51
|
-
status: 200,
|
|
52
|
-
headers
|
|
7
|
+
// src/fetch/bracket-notation.ts
|
|
8
|
+
import { isPlainObject } from "@orpc/shared";
|
|
9
|
+
function serialize(payload, parentKey = "") {
|
|
10
|
+
if (!Array.isArray(payload) && !isPlainObject(payload))
|
|
11
|
+
return [["", payload]];
|
|
12
|
+
const result = [];
|
|
13
|
+
function helper(value, path) {
|
|
14
|
+
if (Array.isArray(value)) {
|
|
15
|
+
value.forEach((item, index) => {
|
|
16
|
+
helper(item, [...path, String(index)]);
|
|
53
17
|
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
context,
|
|
58
|
-
hooks: options,
|
|
59
|
-
execute: handler,
|
|
60
|
-
input: options.request,
|
|
61
|
-
meta: void 0
|
|
62
|
-
});
|
|
63
|
-
} catch (e) {
|
|
64
|
-
const error = toORPCError(e);
|
|
65
|
-
try {
|
|
66
|
-
const { body, headers } = serializer.serialize(error.toJSON());
|
|
67
|
-
return new Response(body, {
|
|
68
|
-
status: error.status,
|
|
69
|
-
headers
|
|
70
|
-
});
|
|
71
|
-
} catch (e2) {
|
|
72
|
-
const error2 = toORPCError(e2);
|
|
73
|
-
const { body, headers } = new OpenAPISerializer().serialize(
|
|
74
|
-
error2.toJSON()
|
|
75
|
-
);
|
|
76
|
-
return new Response(body, {
|
|
77
|
-
status: error2.status,
|
|
78
|
-
headers
|
|
79
|
-
});
|
|
18
|
+
} else if (isPlainObject(value)) {
|
|
19
|
+
for (const [key, val] of Object.entries(value)) {
|
|
20
|
+
helper(val, [...path, key]);
|
|
80
21
|
}
|
|
22
|
+
} else {
|
|
23
|
+
result.push([stringifyPath(path), value]);
|
|
81
24
|
}
|
|
82
|
-
}
|
|
25
|
+
}
|
|
26
|
+
helper(payload, parentKey ? [parentKey] : []);
|
|
27
|
+
return result;
|
|
83
28
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
pending2 = { ref: [] };
|
|
100
|
-
pendingCache.set(router, pending2);
|
|
101
|
-
}
|
|
102
|
-
return pending2;
|
|
103
|
-
})();
|
|
104
|
-
const routing = (() => {
|
|
105
|
-
let routing2 = routingCache.get(router);
|
|
106
|
-
if (!routing2) {
|
|
107
|
-
routing2 = createHonoRouter();
|
|
108
|
-
routingCache.set(router, routing2);
|
|
109
|
-
addRoutes(routing2, pending, { router, path: [] });
|
|
110
|
-
}
|
|
111
|
-
return routing2;
|
|
112
|
-
})();
|
|
113
|
-
const newPending = [];
|
|
114
|
-
for (const item of pending.ref) {
|
|
115
|
-
if (LAZY_ROUTER_PREFIX_SYMBOL in item.lazy && item.lazy[LAZY_ROUTER_PREFIX_SYMBOL] && !pathname.startsWith(item.lazy[LAZY_ROUTER_PREFIX_SYMBOL]) && !pathname.startsWith(`/${item.path.map(encodeURIComponent).join("/")}`)) {
|
|
116
|
-
newPending.push(item);
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
const router2 = (await item.lazy[LAZY_LOADER_SYMBOL]()).default;
|
|
120
|
-
addRoutes(routing, pending, { path: item.path, router: router2 });
|
|
29
|
+
function deserialize(entities) {
|
|
30
|
+
if (entities.length === 0) {
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
const isRootArray = entities.every(([path]) => path === "");
|
|
34
|
+
const result = isRootArray ? [] : {};
|
|
35
|
+
const arrayPushPaths = /* @__PURE__ */ new Set();
|
|
36
|
+
for (const [path, _] of entities) {
|
|
37
|
+
const segments = parsePath(path);
|
|
38
|
+
const base = segments.slice(0, -1).join(".");
|
|
39
|
+
const last = segments[segments.length - 1];
|
|
40
|
+
if (last === "") {
|
|
41
|
+
arrayPushPaths.add(base);
|
|
42
|
+
} else {
|
|
43
|
+
arrayPushPaths.delete(base);
|
|
121
44
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const [
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return
|
|
45
|
+
}
|
|
46
|
+
function setValue(obj, segments, value, fullPath) {
|
|
47
|
+
const [first, ...rest_] = segments;
|
|
48
|
+
if (Array.isArray(obj) && first === "") {
|
|
49
|
+
;
|
|
50
|
+
obj.push(value);
|
|
51
|
+
return;
|
|
129
52
|
}
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
53
|
+
const objAsRecord = obj;
|
|
54
|
+
if (rest_.length === 0) {
|
|
55
|
+
objAsRecord[first] = value;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const rest = rest_;
|
|
59
|
+
if (rest[0] === "") {
|
|
60
|
+
const pathToCheck = segments.slice(0, -1).join(".");
|
|
61
|
+
if (rest.length === 1 && arrayPushPaths.has(pathToCheck)) {
|
|
62
|
+
if (!(first in objAsRecord)) {
|
|
63
|
+
objAsRecord[first] = [];
|
|
64
|
+
}
|
|
65
|
+
if (Array.isArray(objAsRecord[first])) {
|
|
66
|
+
;
|
|
67
|
+
objAsRecord[first].push(value);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!(first in objAsRecord)) {
|
|
72
|
+
objAsRecord[first] = {};
|
|
140
73
|
}
|
|
141
|
-
|
|
74
|
+
const target = objAsRecord[first];
|
|
75
|
+
target[""] = value;
|
|
76
|
+
return;
|
|
142
77
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (Object.keys(coercedParams).length === 0) {
|
|
153
|
-
return input;
|
|
154
|
-
}
|
|
155
|
-
if (!isPlainObject(input)) {
|
|
156
|
-
return coercedParams;
|
|
78
|
+
if (!(first in objAsRecord)) {
|
|
79
|
+
objAsRecord[first] = {};
|
|
80
|
+
}
|
|
81
|
+
setValue(
|
|
82
|
+
objAsRecord[first],
|
|
83
|
+
rest,
|
|
84
|
+
value,
|
|
85
|
+
fullPath
|
|
86
|
+
);
|
|
157
87
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
async function deserializeInput(request, procedure) {
|
|
164
|
-
const deserializer = new OpenAPIDeserializer({
|
|
165
|
-
schema: procedure.zz$p.contract.zz$cp.InputSchema
|
|
166
|
-
});
|
|
167
|
-
try {
|
|
168
|
-
return await deserializer.deserialize(request);
|
|
169
|
-
} catch (e) {
|
|
170
|
-
throw new ORPCError({
|
|
171
|
-
code: "BAD_REQUEST",
|
|
172
|
-
message: "Cannot parse request. Please check the request body and Content-Type header.",
|
|
173
|
-
cause: e
|
|
174
|
-
});
|
|
88
|
+
for (const [path, value] of entities) {
|
|
89
|
+
const segments = parsePath(path);
|
|
90
|
+
setValue(result, segments, value, path);
|
|
175
91
|
}
|
|
92
|
+
return result;
|
|
176
93
|
}
|
|
177
|
-
function
|
|
178
|
-
return
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
94
|
+
function escapeSegment(segment) {
|
|
95
|
+
return segment.replace(/[\\[\]]/g, (match) => {
|
|
96
|
+
switch (match) {
|
|
97
|
+
case "\\":
|
|
98
|
+
return "\\\\";
|
|
99
|
+
case "[":
|
|
100
|
+
return "\\[";
|
|
101
|
+
case "]":
|
|
102
|
+
return "\\]";
|
|
103
|
+
default:
|
|
104
|
+
return match;
|
|
105
|
+
}
|
|
182
106
|
});
|
|
183
107
|
}
|
|
184
|
-
function
|
|
185
|
-
|
|
108
|
+
function stringifyPath(path) {
|
|
109
|
+
const [first, ...rest] = path;
|
|
110
|
+
const firstSegment = escapeSegment(first);
|
|
111
|
+
const base = first === "" ? "" : firstSegment;
|
|
112
|
+
return rest.reduce(
|
|
113
|
+
(result, segment) => `${result}[${escapeSegment(segment)}]`,
|
|
114
|
+
base
|
|
115
|
+
);
|
|
186
116
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
117
|
+
function parsePath(path) {
|
|
118
|
+
if (path === "")
|
|
119
|
+
return [""];
|
|
120
|
+
const result = [];
|
|
121
|
+
let currentSegment = "";
|
|
122
|
+
let inBracket = false;
|
|
123
|
+
let bracketContent = "";
|
|
124
|
+
let backslashCount = 0;
|
|
125
|
+
for (let i = 0; i < path.length; i++) {
|
|
126
|
+
const char = path[i];
|
|
127
|
+
if (char === "\\") {
|
|
128
|
+
backslashCount++;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (backslashCount > 0) {
|
|
132
|
+
const literalBackslashes = "\\".repeat(Math.floor(backslashCount / 2));
|
|
133
|
+
if (char === "[" || char === "]") {
|
|
134
|
+
if (backslashCount % 2 === 1) {
|
|
135
|
+
if (inBracket) {
|
|
136
|
+
bracketContent += literalBackslashes + char;
|
|
137
|
+
} else {
|
|
138
|
+
currentSegment += literalBackslashes + char;
|
|
139
|
+
}
|
|
209
140
|
} else {
|
|
210
|
-
|
|
141
|
+
if (inBracket) {
|
|
142
|
+
bracketContent += literalBackslashes;
|
|
143
|
+
} else {
|
|
144
|
+
currentSegment += literalBackslashes;
|
|
145
|
+
}
|
|
146
|
+
if (char === "[" && !inBracket) {
|
|
147
|
+
if (currentSegment !== "" || result.length === 0) {
|
|
148
|
+
result.push(currentSegment);
|
|
149
|
+
}
|
|
150
|
+
inBracket = true;
|
|
151
|
+
bracketContent = "";
|
|
152
|
+
currentSegment = "";
|
|
153
|
+
} else if (char === "]" && inBracket) {
|
|
154
|
+
result.push(bracketContent);
|
|
155
|
+
inBracket = false;
|
|
156
|
+
bracketContent = "";
|
|
157
|
+
} else {
|
|
158
|
+
if (inBracket) {
|
|
159
|
+
bracketContent += char;
|
|
160
|
+
} else {
|
|
161
|
+
currentSegment += char;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
211
164
|
}
|
|
212
|
-
const optionalSegment = segment.replace("?", "");
|
|
213
|
-
basePath += "/" + optionalSegment;
|
|
214
|
-
results.push(basePath);
|
|
215
165
|
} else {
|
|
216
|
-
|
|
166
|
+
const allBackslashes = "\\".repeat(backslashCount);
|
|
167
|
+
if (inBracket) {
|
|
168
|
+
bracketContent += allBackslashes + char;
|
|
169
|
+
} else {
|
|
170
|
+
currentSegment += allBackslashes + char;
|
|
171
|
+
}
|
|
217
172
|
}
|
|
173
|
+
backslashCount = 0;
|
|
174
|
+
continue;
|
|
218
175
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
// ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/reg-exp-router/node.js
|
|
224
|
-
var LABEL_REG_EXP_STR = "[^/]+";
|
|
225
|
-
var ONLY_WILDCARD_REG_EXP_STR = ".*";
|
|
226
|
-
var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
|
|
227
|
-
var PATH_ERROR = Symbol();
|
|
228
|
-
var regExpMetaChars = new Set(".\\+*[^]$()");
|
|
229
|
-
function compareKey(a, b) {
|
|
230
|
-
if (a.length === 1) {
|
|
231
|
-
return b.length === 1 ? a < b ? -1 : 1 : -1;
|
|
232
|
-
}
|
|
233
|
-
if (b.length === 1) {
|
|
234
|
-
return 1;
|
|
235
|
-
}
|
|
236
|
-
if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
|
|
237
|
-
return 1;
|
|
238
|
-
} else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
|
|
239
|
-
return -1;
|
|
240
|
-
}
|
|
241
|
-
if (a === LABEL_REG_EXP_STR) {
|
|
242
|
-
return 1;
|
|
243
|
-
} else if (b === LABEL_REG_EXP_STR) {
|
|
244
|
-
return -1;
|
|
245
|
-
}
|
|
246
|
-
return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length;
|
|
247
|
-
}
|
|
248
|
-
var Node = class {
|
|
249
|
-
#index;
|
|
250
|
-
#varIndex;
|
|
251
|
-
#children = /* @__PURE__ */ Object.create(null);
|
|
252
|
-
insert(tokens, index, paramMap, context, pathErrorCheckOnly) {
|
|
253
|
-
if (tokens.length === 0) {
|
|
254
|
-
if (this.#index !== void 0) {
|
|
255
|
-
throw PATH_ERROR;
|
|
256
|
-
}
|
|
257
|
-
if (pathErrorCheckOnly) {
|
|
258
|
-
return;
|
|
176
|
+
if (char === "[" && !inBracket) {
|
|
177
|
+
if (currentSegment !== "" || result.length === 0) {
|
|
178
|
+
result.push(currentSegment);
|
|
259
179
|
}
|
|
260
|
-
|
|
261
|
-
|
|
180
|
+
inBracket = true;
|
|
181
|
+
bracketContent = "";
|
|
182
|
+
currentSegment = "";
|
|
183
|
+
continue;
|
|
262
184
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if (/\((?!\?:)/.test(regexpStr)) {
|
|
272
|
-
throw PATH_ERROR;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
node = this.#children[regexpStr];
|
|
276
|
-
if (!node) {
|
|
277
|
-
if (Object.keys(this.#children).some(
|
|
278
|
-
(k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
|
|
279
|
-
)) {
|
|
280
|
-
throw PATH_ERROR;
|
|
281
|
-
}
|
|
282
|
-
if (pathErrorCheckOnly) {
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
node = this.#children[regexpStr] = new Node();
|
|
286
|
-
if (name !== "") {
|
|
287
|
-
node.#varIndex = context.varIndex++;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
if (!pathErrorCheckOnly && name !== "") {
|
|
291
|
-
paramMap.push([name, node.#varIndex]);
|
|
292
|
-
}
|
|
185
|
+
if (char === "]" && inBracket) {
|
|
186
|
+
result.push(bracketContent);
|
|
187
|
+
inBracket = false;
|
|
188
|
+
bracketContent = "";
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (inBracket) {
|
|
192
|
+
bracketContent += char;
|
|
293
193
|
} else {
|
|
294
|
-
|
|
295
|
-
if (!node) {
|
|
296
|
-
if (Object.keys(this.#children).some(
|
|
297
|
-
(k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
|
|
298
|
-
)) {
|
|
299
|
-
throw PATH_ERROR;
|
|
300
|
-
}
|
|
301
|
-
if (pathErrorCheckOnly) {
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
node = this.#children[token] = new Node();
|
|
305
|
-
}
|
|
194
|
+
currentSegment += char;
|
|
306
195
|
}
|
|
307
|
-
node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly);
|
|
308
196
|
}
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if (typeof this.#index === "number") {
|
|
316
|
-
strList.unshift(`#${this.#index}`);
|
|
317
|
-
}
|
|
318
|
-
if (strList.length === 0) {
|
|
319
|
-
return "";
|
|
197
|
+
if (backslashCount > 0) {
|
|
198
|
+
const remainingBackslashes = "\\".repeat(backslashCount);
|
|
199
|
+
if (inBracket) {
|
|
200
|
+
bracketContent += remainingBackslashes;
|
|
201
|
+
} else {
|
|
202
|
+
currentSegment += remainingBackslashes;
|
|
320
203
|
}
|
|
321
|
-
|
|
322
|
-
|
|
204
|
+
}
|
|
205
|
+
if (inBracket) {
|
|
206
|
+
if (currentSegment !== "" || result.length === 0) {
|
|
207
|
+
result.push(currentSegment);
|
|
323
208
|
}
|
|
324
|
-
|
|
209
|
+
result.push(`[${bracketContent}`);
|
|
210
|
+
} else if (currentSegment !== "" || result.length === 0) {
|
|
211
|
+
result.push(currentSegment);
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/fetch/input-builder-full.ts
|
|
217
|
+
var InputBuilderFull = class {
|
|
218
|
+
build(params, query, headers, body) {
|
|
219
|
+
return {
|
|
220
|
+
params,
|
|
221
|
+
query,
|
|
222
|
+
headers,
|
|
223
|
+
body
|
|
224
|
+
};
|
|
325
225
|
}
|
|
326
226
|
};
|
|
327
227
|
|
|
328
|
-
//
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const groups = [];
|
|
335
|
-
for (let i = 0; ; ) {
|
|
336
|
-
let replaced = false;
|
|
337
|
-
path = path.replace(/\{[^}]+\}/g, (m) => {
|
|
338
|
-
const mark = `@\\${i}`;
|
|
339
|
-
groups[i] = [mark, m];
|
|
340
|
-
i++;
|
|
341
|
-
replaced = true;
|
|
342
|
-
return mark;
|
|
343
|
-
});
|
|
344
|
-
if (!replaced) {
|
|
345
|
-
break;
|
|
346
|
-
}
|
|
228
|
+
// src/fetch/input-builder-simple.ts
|
|
229
|
+
import { isPlainObject as isPlainObject2 } from "@orpc/shared";
|
|
230
|
+
var InputBuilderSimple = class {
|
|
231
|
+
build(params, payload) {
|
|
232
|
+
if (Object.keys(params).length === 0) {
|
|
233
|
+
return payload;
|
|
347
234
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
const [mark] = groups[i];
|
|
351
|
-
for (let j = tokens.length - 1; j >= 0; j--) {
|
|
352
|
-
if (tokens[j].indexOf(mark) !== -1) {
|
|
353
|
-
tokens[j] = tokens[j].replace(mark, groups[i][1]);
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
235
|
+
if (!isPlainObject2(payload)) {
|
|
236
|
+
return params;
|
|
357
237
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
let regexp = this.#root.buildRegExpStr();
|
|
363
|
-
if (regexp === "") {
|
|
364
|
-
return [/^$/, [], []];
|
|
365
|
-
}
|
|
366
|
-
let captureIndex = 0;
|
|
367
|
-
const indexReplacementMap = [];
|
|
368
|
-
const paramReplacementMap = [];
|
|
369
|
-
regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => {
|
|
370
|
-
if (handlerIndex !== void 0) {
|
|
371
|
-
indexReplacementMap[++captureIndex] = Number(handlerIndex);
|
|
372
|
-
return "$()";
|
|
373
|
-
}
|
|
374
|
-
if (paramIndex !== void 0) {
|
|
375
|
-
paramReplacementMap[Number(paramIndex)] = ++captureIndex;
|
|
376
|
-
return "";
|
|
377
|
-
}
|
|
378
|
-
return "";
|
|
379
|
-
});
|
|
380
|
-
return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
|
|
238
|
+
return {
|
|
239
|
+
...params,
|
|
240
|
+
...payload
|
|
241
|
+
};
|
|
381
242
|
}
|
|
382
243
|
};
|
|
383
244
|
|
|
384
|
-
//
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
398
|
-
}
|
|
399
|
-
function buildMatcherFromPreprocessedRoutes(routes) {
|
|
400
|
-
const trie = new Trie();
|
|
401
|
-
const handlerData = [];
|
|
402
|
-
if (routes.length === 0) {
|
|
403
|
-
return nullMatcher;
|
|
245
|
+
// src/fetch/openapi-handler.ts
|
|
246
|
+
import { createProcedureClient, ORPCError as ORPCError2 } from "@orpc/server";
|
|
247
|
+
import { executeWithHooks, ORPC_HANDLER_HEADER, trim } from "@orpc/shared";
|
|
248
|
+
|
|
249
|
+
// src/fetch/openapi-payload-codec.ts
|
|
250
|
+
import { ORPCError } from "@orpc/server";
|
|
251
|
+
import { findDeepMatches } from "@orpc/shared";
|
|
252
|
+
import cd from "content-disposition";
|
|
253
|
+
import { safeParse } from "fast-content-type-parse";
|
|
254
|
+
import wcmatch from "wildcard-match";
|
|
255
|
+
var OpenAPIPayloadCodec = class {
|
|
256
|
+
constructor(jsonSerializer) {
|
|
257
|
+
this.jsonSerializer = jsonSerializer;
|
|
404
258
|
}
|
|
405
|
-
|
|
406
|
-
(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
259
|
+
encode(payload, accept) {
|
|
260
|
+
const typeMatchers = (accept?.split(",").map(safeParse) ?? [{ type: "*/*" }]).map(({ type }) => wcmatch(type));
|
|
261
|
+
if (payload instanceof Blob) {
|
|
262
|
+
const contentType = payload.type || "application/octet-stream";
|
|
263
|
+
if (typeMatchers.some((isMatch) => isMatch(contentType))) {
|
|
264
|
+
const headers = new Headers({
|
|
265
|
+
"Content-Type": contentType
|
|
266
|
+
});
|
|
267
|
+
if (payload instanceof File && payload.name) {
|
|
268
|
+
headers.append("Content-Disposition", cd(payload.name));
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
body: payload,
|
|
272
|
+
headers
|
|
273
|
+
};
|
|
274
|
+
}
|
|
417
275
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
276
|
+
const handledPayload = this.jsonSerializer.serialize(payload);
|
|
277
|
+
const hasBlobs = findDeepMatches((v) => v instanceof Blob, handledPayload).values.length > 0;
|
|
278
|
+
const isExpectedMultipartFormData = typeMatchers.some(
|
|
279
|
+
(isMatch) => isMatch("multipart/form-data")
|
|
280
|
+
);
|
|
281
|
+
if (hasBlobs && isExpectedMultipartFormData) {
|
|
282
|
+
return this.encodeAsFormData(handledPayload);
|
|
423
283
|
}
|
|
424
|
-
if (
|
|
425
|
-
|
|
284
|
+
if (typeMatchers.some((isMatch) => isMatch("application/json"))) {
|
|
285
|
+
return this.encodeAsJSON(handledPayload);
|
|
426
286
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
287
|
+
if (typeMatchers.some(
|
|
288
|
+
(isMatch) => isMatch("application/x-www-form-urlencoded")
|
|
289
|
+
)) {
|
|
290
|
+
return this.encodeAsURLSearchParams(handledPayload);
|
|
291
|
+
}
|
|
292
|
+
if (isExpectedMultipartFormData) {
|
|
293
|
+
return this.encodeAsFormData(handledPayload);
|
|
294
|
+
}
|
|
295
|
+
throw new ORPCError({
|
|
296
|
+
code: "NOT_ACCEPTABLE",
|
|
297
|
+
message: `Unsupported content-type: ${accept}`
|
|
435
298
|
});
|
|
436
299
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
for (let k = 0, len3 = keys.length; k < len3; k++) {
|
|
446
|
-
map[keys[k]] = paramReplacementMap[map[keys[k]]];
|
|
447
|
-
}
|
|
300
|
+
encodeAsJSON(payload) {
|
|
301
|
+
if (payload === void 0) {
|
|
302
|
+
return {
|
|
303
|
+
body: void 0,
|
|
304
|
+
headers: new Headers({
|
|
305
|
+
"content-type": "application/json"
|
|
306
|
+
})
|
|
307
|
+
};
|
|
448
308
|
}
|
|
309
|
+
return {
|
|
310
|
+
body: JSON.stringify(payload),
|
|
311
|
+
headers: new Headers({
|
|
312
|
+
"content-type": "application/json"
|
|
313
|
+
})
|
|
314
|
+
};
|
|
449
315
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
316
|
+
encodeAsFormData(payload) {
|
|
317
|
+
const form = new FormData();
|
|
318
|
+
for (const [path, value] of serialize(payload)) {
|
|
319
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
320
|
+
form.append(path, value.toString());
|
|
321
|
+
} else if (value === null) {
|
|
322
|
+
form.append(path, "null");
|
|
323
|
+
} else if (value instanceof Date) {
|
|
324
|
+
form.append(
|
|
325
|
+
path,
|
|
326
|
+
Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString()
|
|
327
|
+
);
|
|
328
|
+
} else if (value instanceof Blob) {
|
|
329
|
+
form.append(path, value);
|
|
330
|
+
}
|
|
463
331
|
}
|
|
332
|
+
return {
|
|
333
|
+
body: form
|
|
334
|
+
};
|
|
464
335
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
336
|
+
encodeAsURLSearchParams(payload) {
|
|
337
|
+
const params = new URLSearchParams();
|
|
338
|
+
for (const [path, value] of serialize(payload)) {
|
|
339
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
340
|
+
params.append(path, value.toString());
|
|
341
|
+
} else if (value === null) {
|
|
342
|
+
params.append(path, "null");
|
|
343
|
+
} else if (value instanceof Date) {
|
|
344
|
+
params.append(
|
|
345
|
+
path,
|
|
346
|
+
Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString()
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
body: params.toString(),
|
|
352
|
+
headers: new Headers({
|
|
353
|
+
"content-type": "application/x-www-form-urlencoded"
|
|
354
|
+
})
|
|
355
|
+
};
|
|
474
356
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (!middleware || !routes) {
|
|
479
|
-
throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
|
|
357
|
+
async decode(re) {
|
|
358
|
+
if (re instanceof Headers || re instanceof URLSearchParams || re instanceof FormData) {
|
|
359
|
+
return deserialize([...re.entries()]);
|
|
480
360
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
361
|
+
const contentType = re.headers.get("content-type");
|
|
362
|
+
const contentDisposition = re.headers.get("content-disposition");
|
|
363
|
+
const fileName = contentDisposition ? cd.parse(contentDisposition).parameters.filename : void 0;
|
|
364
|
+
if (fileName) {
|
|
365
|
+
const blob2 = await re.blob();
|
|
366
|
+
const file = new File([blob2], fileName, {
|
|
367
|
+
type: blob2.type
|
|
488
368
|
});
|
|
369
|
+
return file;
|
|
489
370
|
}
|
|
490
|
-
if (
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
const paramCount = (path.match(/\/:/g) || []).length;
|
|
494
|
-
if (/\*$/.test(path)) {
|
|
495
|
-
const re = buildWildcardRegExp(path);
|
|
496
|
-
if (method === METHOD_NAME_ALL) {
|
|
497
|
-
Object.keys(middleware).forEach((m) => {
|
|
498
|
-
middleware[m][path] ||= findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
|
|
499
|
-
});
|
|
500
|
-
} else {
|
|
501
|
-
middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
|
|
371
|
+
if (!contentType || contentType.startsWith("application/json")) {
|
|
372
|
+
if (!re.body) {
|
|
373
|
+
return void 0;
|
|
502
374
|
}
|
|
503
|
-
|
|
504
|
-
if (method === METHOD_NAME_ALL || method === m) {
|
|
505
|
-
Object.keys(middleware[m]).forEach((p) => {
|
|
506
|
-
re.test(p) && middleware[m][p].push([handler, paramCount]);
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
|
-
});
|
|
510
|
-
Object.keys(routes).forEach((m) => {
|
|
511
|
-
if (method === METHOD_NAME_ALL || method === m) {
|
|
512
|
-
Object.keys(routes[m]).forEach(
|
|
513
|
-
(p) => re.test(p) && routes[m][p].push([handler, paramCount])
|
|
514
|
-
);
|
|
515
|
-
}
|
|
516
|
-
});
|
|
517
|
-
return;
|
|
375
|
+
return await re.json();
|
|
518
376
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
Object.keys(routes).forEach((m) => {
|
|
523
|
-
if (method === METHOD_NAME_ALL || method === m) {
|
|
524
|
-
routes[m][path2] ||= [
|
|
525
|
-
...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
|
|
526
|
-
];
|
|
527
|
-
routes[m][path2].push([handler, paramCount - len + i + 1]);
|
|
528
|
-
}
|
|
529
|
-
});
|
|
377
|
+
if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
378
|
+
const params = new URLSearchParams(await re.text());
|
|
379
|
+
return this.decode(params);
|
|
530
380
|
}
|
|
381
|
+
if (contentType.startsWith("text/")) {
|
|
382
|
+
const text = await re.text();
|
|
383
|
+
return text;
|
|
384
|
+
}
|
|
385
|
+
if (contentType.startsWith("multipart/form-data")) {
|
|
386
|
+
const form = await re.formData();
|
|
387
|
+
return this.decode(form);
|
|
388
|
+
}
|
|
389
|
+
const blob = await re.blob();
|
|
390
|
+
return new File([blob], "blob", {
|
|
391
|
+
type: blob.type
|
|
392
|
+
});
|
|
531
393
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
// src/fetch/openapi-procedure-matcher.ts
|
|
397
|
+
import { getLazyRouterPrefix, getRouterChild, isProcedure, unlazy } from "@orpc/server";
|
|
398
|
+
import { mapValues } from "@orpc/shared";
|
|
399
|
+
var OpenAPIProcedureMatcher = class {
|
|
400
|
+
constructor(hono, router) {
|
|
401
|
+
this.hono = hono;
|
|
402
|
+
this.router = router;
|
|
403
|
+
this.pendingRouters = [{ path: [], router }];
|
|
404
|
+
}
|
|
405
|
+
pendingRouters;
|
|
406
|
+
async match(method, pathname) {
|
|
407
|
+
await this.handlePendingRouters(pathname);
|
|
408
|
+
const [matches, paramStash] = this.hono.match(method, pathname);
|
|
409
|
+
const [match] = matches.sort((a, b) => {
|
|
410
|
+
const slashCountA = a[0][0].split("/").length;
|
|
411
|
+
const slashCountB = b[0][0].split("/").length;
|
|
412
|
+
if (slashCountA !== slashCountB) {
|
|
413
|
+
return slashCountB - slashCountA;
|
|
544
414
|
}
|
|
545
|
-
const
|
|
546
|
-
|
|
415
|
+
const paramsCountA = Object.keys(a[1]).length;
|
|
416
|
+
const paramsCountB = Object.keys(b[1]).length;
|
|
417
|
+
return paramsCountA - paramsCountB;
|
|
418
|
+
});
|
|
419
|
+
if (!match) {
|
|
420
|
+
return void 0;
|
|
421
|
+
}
|
|
422
|
+
const path = match[0][1];
|
|
423
|
+
const params = paramStash ? mapValues(
|
|
424
|
+
match[1],
|
|
425
|
+
// if paramStash is defined, then match[1] is ParamIndexMap
|
|
426
|
+
(v) => paramStash[v]
|
|
427
|
+
) : match[1];
|
|
428
|
+
const { default: maybeProcedure } = await unlazy(getRouterChild(this.router, ...path));
|
|
429
|
+
if (!isProcedure(maybeProcedure)) {
|
|
430
|
+
return void 0;
|
|
431
|
+
}
|
|
432
|
+
return {
|
|
433
|
+
path,
|
|
434
|
+
procedure: maybeProcedure,
|
|
435
|
+
params: { ...params }
|
|
436
|
+
// normalize params from hono
|
|
547
437
|
};
|
|
548
|
-
return this.match(method, path);
|
|
549
438
|
}
|
|
550
|
-
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
439
|
+
add(path, router) {
|
|
440
|
+
const lazies = forEachContractProcedure({ path, router }, ({ path: path2, contract }) => {
|
|
441
|
+
const method = contract["~orpc"].route?.method ?? "POST";
|
|
442
|
+
const httpPath = contract["~orpc"].route?.path ? this.convertOpenAPIPathToRouterPath(contract["~orpc"].route?.path) : `/${path2.map(encodeURIComponent).join("/")}`;
|
|
443
|
+
this.hono.add(method, httpPath, [httpPath, path2]);
|
|
554
444
|
});
|
|
555
|
-
this
|
|
556
|
-
return matchers;
|
|
445
|
+
this.pendingRouters.push(...lazies);
|
|
557
446
|
}
|
|
558
|
-
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
routes.push(...ownRoute);
|
|
566
|
-
} else if (method !== METHOD_NAME_ALL) {
|
|
567
|
-
routes.push(
|
|
568
|
-
...Object.keys(r[METHOD_NAME_ALL]).map((path) => [path, r[METHOD_NAME_ALL][path]])
|
|
569
|
-
);
|
|
447
|
+
async handlePendingRouters(pathname) {
|
|
448
|
+
const newPendingLazyRouters = [];
|
|
449
|
+
for (const item of this.pendingRouters) {
|
|
450
|
+
const lazyPrefix = getLazyRouterPrefix(item.router);
|
|
451
|
+
if (lazyPrefix && !pathname.startsWith(lazyPrefix) && !pathname.startsWith(`/${item.path.map(encodeURIComponent).join("/")}`)) {
|
|
452
|
+
newPendingLazyRouters.push(item);
|
|
453
|
+
continue;
|
|
570
454
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
return null;
|
|
574
|
-
} else {
|
|
575
|
-
return buildMatcherFromPreprocessedRoutes(routes);
|
|
455
|
+
const { default: router } = await unlazy(item.router);
|
|
456
|
+
this.add(item.path, router);
|
|
576
457
|
}
|
|
458
|
+
this.pendingRouters = newPendingLazyRouters;
|
|
459
|
+
}
|
|
460
|
+
convertOpenAPIPathToRouterPath(path) {
|
|
461
|
+
return standardizeHTTPPath(path).replace(/\{([^}]+)\}/g, ":$1");
|
|
577
462
|
}
|
|
578
463
|
};
|
|
579
464
|
|
|
580
|
-
// src/fetch/
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
var LinearRouter = class {
|
|
590
|
-
name = "LinearRouter";
|
|
591
|
-
#routes = [];
|
|
592
|
-
add(method, path, handler) {
|
|
593
|
-
for (let i = 0, paths = checkOptionalParameter(path) || [path], len = paths.length; i < len; i++) {
|
|
594
|
-
this.#routes.push([method, paths[i], handler]);
|
|
465
|
+
// src/fetch/schema-coercer.ts
|
|
466
|
+
var CompositeSchemaCoercer = class {
|
|
467
|
+
constructor(coercers) {
|
|
468
|
+
this.coercers = coercers;
|
|
469
|
+
}
|
|
470
|
+
coerce(schema, value) {
|
|
471
|
+
let current = value;
|
|
472
|
+
for (const coercer of this.coercers) {
|
|
473
|
+
current = coercer.coerce(schema, current);
|
|
595
474
|
}
|
|
475
|
+
return current;
|
|
596
476
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
const restPath = path.slice(pos + 1);
|
|
653
|
-
const match = new RegExp(pattern, "d").exec(restPath);
|
|
654
|
-
if (!match || match.indices[0][0] !== 0 || match.indices[0][1] === 0) {
|
|
655
|
-
continue ROUTES_LOOP;
|
|
656
|
-
}
|
|
657
|
-
name = name.slice(0, openBracePos);
|
|
658
|
-
value2 = restPath.slice(...match.indices[0]);
|
|
659
|
-
pos += match.indices[0][1] + 1;
|
|
660
|
-
} else {
|
|
661
|
-
let endValuePos = path.indexOf("/", pos + 1);
|
|
662
|
-
if (endValuePos === -1) {
|
|
663
|
-
if (pos + 1 === path.length) {
|
|
664
|
-
continue ROUTES_LOOP;
|
|
665
|
-
}
|
|
666
|
-
endValuePos = path.length;
|
|
667
|
-
}
|
|
668
|
-
value2 = path.slice(pos + 1, endValuePos);
|
|
669
|
-
pos = endValuePos;
|
|
670
|
-
}
|
|
671
|
-
params[name] ||= value2;
|
|
672
|
-
} else {
|
|
673
|
-
const index = path.indexOf(part, pos);
|
|
674
|
-
if (index !== pos) {
|
|
675
|
-
continue ROUTES_LOOP;
|
|
676
|
-
}
|
|
677
|
-
pos += part.length;
|
|
678
|
-
}
|
|
679
|
-
if (j === lastIndex) {
|
|
680
|
-
if (pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) {
|
|
681
|
-
continue ROUTES_LOOP;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
handlers.push([handler, params]);
|
|
686
|
-
} else if (hasLabel && hasStar) {
|
|
687
|
-
throw new UnsupportedPathError();
|
|
688
|
-
}
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
// src/fetch/openapi-handler.ts
|
|
480
|
+
var OpenAPIHandler = class {
|
|
481
|
+
constructor(hono, router, options) {
|
|
482
|
+
this.options = options;
|
|
483
|
+
const jsonSerializer = options?.jsonSerializer ?? new JSONSerializer();
|
|
484
|
+
this.procedureMatcher = options?.procedureMatcher ?? new OpenAPIProcedureMatcher(hono, router);
|
|
485
|
+
this.payloadCodec = options?.payloadCodec ?? new OpenAPIPayloadCodec(jsonSerializer);
|
|
486
|
+
this.inputBuilderSimple = options?.inputBuilderSimple ?? new InputBuilderSimple();
|
|
487
|
+
this.inputBuilderFull = options?.inputBuilderFull ?? new InputBuilderFull();
|
|
488
|
+
this.compositeSchemaCoercer = new CompositeSchemaCoercer(options?.schemaCoercers ?? []);
|
|
489
|
+
}
|
|
490
|
+
procedureMatcher;
|
|
491
|
+
payloadCodec;
|
|
492
|
+
inputBuilderSimple;
|
|
493
|
+
inputBuilderFull;
|
|
494
|
+
compositeSchemaCoercer;
|
|
495
|
+
condition(request) {
|
|
496
|
+
return request.headers.get(ORPC_HANDLER_HEADER) === null;
|
|
497
|
+
}
|
|
498
|
+
async fetch(request, ...[options]) {
|
|
499
|
+
const context = options?.context;
|
|
500
|
+
const headers = request.headers;
|
|
501
|
+
const accept = headers.get("Accept") || void 0;
|
|
502
|
+
const execute = async () => {
|
|
503
|
+
const url = new URL(request.url);
|
|
504
|
+
const pathname = `/${trim(url.pathname.replace(options?.prefix ?? "", ""), "/")}`;
|
|
505
|
+
const query = url.searchParams;
|
|
506
|
+
const customMethod = request.method === "POST" ? query.get("method")?.toUpperCase() : void 0;
|
|
507
|
+
const method = customMethod || request.method;
|
|
508
|
+
const match = await this.procedureMatcher.match(method, pathname);
|
|
509
|
+
if (!match) {
|
|
510
|
+
throw new ORPCError2({ code: "NOT_FOUND", message: "Not found" });
|
|
511
|
+
}
|
|
512
|
+
const decodedPayload = request.method === "GET" ? await this.payloadCodec.decode(query) : await this.payloadCodec.decode(request);
|
|
513
|
+
const input = this.inputBuilderSimple.build(match.params, decodedPayload);
|
|
514
|
+
const coercedInput = this.compositeSchemaCoercer.coerce(match.procedure["~orpc"].contract["~orpc"].InputSchema, input);
|
|
515
|
+
const client = createProcedureClient({
|
|
516
|
+
context,
|
|
517
|
+
procedure: match.procedure,
|
|
518
|
+
path: match.path
|
|
519
|
+
});
|
|
520
|
+
const output = await client(coercedInput, { signal: options?.signal });
|
|
521
|
+
const { body, headers: headers2 } = this.payloadCodec.encode(output);
|
|
522
|
+
return new Response(body, { headers: headers2 });
|
|
523
|
+
};
|
|
524
|
+
try {
|
|
525
|
+
return await executeWithHooks({
|
|
526
|
+
context,
|
|
527
|
+
execute,
|
|
528
|
+
input: request,
|
|
529
|
+
hooks: this.options,
|
|
530
|
+
meta: {
|
|
531
|
+
signal: options?.signal
|
|
689
532
|
}
|
|
533
|
+
});
|
|
534
|
+
} catch (e) {
|
|
535
|
+
const error = this.convertToORPCError(e);
|
|
536
|
+
try {
|
|
537
|
+
const { body, headers: headers2 } = this.payloadCodec.encode(error.toJSON(), accept);
|
|
538
|
+
return new Response(body, {
|
|
539
|
+
status: error.status,
|
|
540
|
+
headers: headers2
|
|
541
|
+
});
|
|
542
|
+
} catch (e2) {
|
|
543
|
+
const error2 = this.convertToORPCError(e2);
|
|
544
|
+
const { body, headers: headers2 } = this.payloadCodec.encode(error2.toJSON());
|
|
545
|
+
return new Response(body, {
|
|
546
|
+
status: error2.status,
|
|
547
|
+
headers: headers2
|
|
548
|
+
});
|
|
690
549
|
}
|
|
691
|
-
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
convertToORPCError(e) {
|
|
553
|
+
return e instanceof ORPCError2 ? e : new ORPCError2({
|
|
554
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
555
|
+
message: "Internal server error",
|
|
556
|
+
cause: e
|
|
557
|
+
});
|
|
692
558
|
}
|
|
693
559
|
};
|
|
694
560
|
|
|
695
|
-
// src/fetch/
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
561
|
+
// src/fetch/openapi-handler-server.ts
|
|
562
|
+
import { TrieRouter } from "hono/router/trie-router";
|
|
563
|
+
var OpenAPIServerHandler = class extends OpenAPIHandler {
|
|
564
|
+
constructor(router, options) {
|
|
565
|
+
super(new TrieRouter(), router, options);
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
// src/fetch/openapi-handler-serverless.ts
|
|
570
|
+
import { LinearRouter } from "hono/router/linear-router";
|
|
571
|
+
var OpenAPIServerlessHandler = class extends OpenAPIHandler {
|
|
572
|
+
constructor(router, options) {
|
|
573
|
+
super(new LinearRouter(), router, options);
|
|
574
|
+
}
|
|
575
|
+
};
|
|
699
576
|
export {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
577
|
+
CompositeSchemaCoercer,
|
|
578
|
+
InputBuilderFull,
|
|
579
|
+
InputBuilderSimple,
|
|
580
|
+
OpenAPIHandler,
|
|
581
|
+
OpenAPIPayloadCodec,
|
|
582
|
+
OpenAPIProcedureMatcher,
|
|
583
|
+
OpenAPIServerHandler,
|
|
584
|
+
OpenAPIServerlessHandler,
|
|
585
|
+
deserialize,
|
|
586
|
+
escapeSegment,
|
|
587
|
+
parsePath,
|
|
588
|
+
serialize,
|
|
589
|
+
stringifyPath
|
|
705
590
|
};
|
|
706
591
|
//# sourceMappingURL=fetch.js.map
|