@orpc/openapi 0.0.0-next.6a8bf13 → 0.0.0-next.73eb96a
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 +586 -631
- package/dist/index.js +393 -4344
- package/dist/src/fetch/bracket-notation.d.ts +84 -0
- package/dist/src/fetch/index.d.ts +9 -3
- package/dist/src/fetch/input-structure-compact.d.ts +6 -0
- package/dist/src/fetch/input-structure-detailed.d.ts +11 -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 +33 -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-error.d.ts +3 -0
- package/dist/src/openapi-generator.d.ts +60 -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 +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,661 @@
|
|
|
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;
|
|
78
|
+
if (!(first in objAsRecord)) {
|
|
79
|
+
objAsRecord[first] = {};
|
|
80
|
+
}
|
|
81
|
+
setValue(
|
|
82
|
+
objAsRecord[first],
|
|
83
|
+
rest,
|
|
84
|
+
value,
|
|
85
|
+
fullPath
|
|
86
|
+
);
|
|
154
87
|
}
|
|
155
|
-
|
|
156
|
-
|
|
88
|
+
for (const [path, value] of entities) {
|
|
89
|
+
const segments = parsePath(path);
|
|
90
|
+
setValue(result, segments, value, path);
|
|
157
91
|
}
|
|
158
|
-
return
|
|
159
|
-
...coercedParams,
|
|
160
|
-
...input
|
|
161
|
-
};
|
|
92
|
+
return result;
|
|
162
93
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function toORPCError(e) {
|
|
178
|
-
return e instanceof ORPCError ? e : new ORPCError({
|
|
179
|
-
code: "INTERNAL_SERVER_ERROR",
|
|
180
|
-
message: "Internal server error",
|
|
181
|
-
cause: e
|
|
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;
|
|
176
|
+
if (char === "[" && !inBracket) {
|
|
177
|
+
if (currentSegment !== "" || result.length === 0) {
|
|
178
|
+
result.push(currentSegment);
|
|
256
179
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return;
|
|
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
|
-
|
|
316
|
-
|
|
197
|
+
if (backslashCount > 0) {
|
|
198
|
+
const remainingBackslashes = "\\".repeat(backslashCount);
|
|
199
|
+
if (inBracket) {
|
|
200
|
+
bracketContent += remainingBackslashes;
|
|
201
|
+
} else {
|
|
202
|
+
currentSegment += remainingBackslashes;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (inBracket) {
|
|
206
|
+
if (currentSegment !== "" || result.length === 0) {
|
|
207
|
+
result.push(currentSegment);
|
|
317
208
|
}
|
|
318
|
-
|
|
319
|
-
|
|
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-structure-compact.ts
|
|
217
|
+
import { isPlainObject as isPlainObject2 } from "@orpc/shared";
|
|
218
|
+
var InputStructureCompact = class {
|
|
219
|
+
build(params, payload) {
|
|
220
|
+
if (Object.keys(params).length === 0) {
|
|
221
|
+
return payload;
|
|
320
222
|
}
|
|
321
|
-
if (
|
|
322
|
-
return
|
|
223
|
+
if (!isPlainObject2(payload)) {
|
|
224
|
+
return params;
|
|
323
225
|
}
|
|
324
|
-
return
|
|
226
|
+
return {
|
|
227
|
+
...params,
|
|
228
|
+
...payload
|
|
229
|
+
};
|
|
325
230
|
}
|
|
326
231
|
};
|
|
327
232
|
|
|
328
|
-
//
|
|
329
|
-
var
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
233
|
+
// src/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
|
+
};
|
|
244
|
+
|
|
245
|
+
// src/fetch/openapi-handler.ts
|
|
246
|
+
import { createProcedureClient, ORPCError as ORPCError2 } from "@orpc/server";
|
|
247
|
+
import { executeWithHooks, isPlainObject as isPlainObject3, 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;
|
|
258
|
+
}
|
|
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
|
+
};
|
|
346
274
|
}
|
|
347
275
|
}
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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);
|
|
283
|
+
}
|
|
284
|
+
if (typeMatchers.some((isMatch) => isMatch("application/json"))) {
|
|
285
|
+
return this.encodeAsJSON(handledPayload);
|
|
286
|
+
}
|
|
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}`
|
|
298
|
+
});
|
|
299
|
+
}
|
|
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
|
+
};
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
body: JSON.stringify(payload),
|
|
311
|
+
headers: new Headers({
|
|
312
|
+
"content-type": "application/json"
|
|
313
|
+
})
|
|
314
|
+
};
|
|
315
|
+
}
|
|
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);
|
|
356
330
|
}
|
|
357
331
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
332
|
+
return {
|
|
333
|
+
body: form
|
|
334
|
+
};
|
|
335
|
+
}
|
|
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
|
+
);
|
|
373
348
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
body: params.toString(),
|
|
352
|
+
headers: new Headers({
|
|
353
|
+
"content-type": "application/x-www-form-urlencoded"
|
|
354
|
+
})
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
async decode(re) {
|
|
358
|
+
if (re instanceof Headers || re instanceof URLSearchParams || re instanceof FormData) {
|
|
359
|
+
return deserialize([...re.entries()]);
|
|
360
|
+
}
|
|
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
|
|
368
|
+
});
|
|
369
|
+
return file;
|
|
370
|
+
}
|
|
371
|
+
if (!contentType || contentType.startsWith("application/json")) {
|
|
372
|
+
if (!re.body) {
|
|
373
|
+
return void 0;
|
|
377
374
|
}
|
|
378
|
-
return
|
|
375
|
+
return await re.json();
|
|
376
|
+
}
|
|
377
|
+
if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
378
|
+
const params = new URLSearchParams(await re.text());
|
|
379
|
+
return this.decode(params);
|
|
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
|
|
379
392
|
});
|
|
380
|
-
return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
|
|
381
393
|
}
|
|
382
394
|
};
|
|
383
395
|
|
|
384
|
-
//
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
var
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
)
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
);
|
|
410
|
-
const staticMap = /* @__PURE__ */ Object.create(null);
|
|
411
|
-
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
|
|
412
|
-
const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
|
|
413
|
-
if (pathErrorCheckOnly) {
|
|
414
|
-
staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
|
|
415
|
-
} else {
|
|
416
|
-
j++;
|
|
417
|
-
}
|
|
418
|
-
let paramAssoc;
|
|
419
|
-
try {
|
|
420
|
-
paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
|
|
421
|
-
} catch (e) {
|
|
422
|
-
throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
|
|
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;
|
|
414
|
+
}
|
|
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;
|
|
423
421
|
}
|
|
424
|
-
|
|
425
|
-
|
|
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;
|
|
426
431
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
432
|
+
return {
|
|
433
|
+
path,
|
|
434
|
+
procedure: maybeProcedure,
|
|
435
|
+
params: { ...params }
|
|
436
|
+
// normalize params from hono
|
|
437
|
+
};
|
|
438
|
+
}
|
|
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]);
|
|
435
444
|
});
|
|
445
|
+
this.pendingRouters.push(...lazies);
|
|
436
446
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
for (
|
|
440
|
-
const
|
|
441
|
-
if (!map) {
|
|
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);
|
|
442
453
|
continue;
|
|
443
454
|
}
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
map[keys[k]] = paramReplacementMap[map[keys[k]]];
|
|
447
|
-
}
|
|
455
|
+
const { default: router } = await unlazy(item.router);
|
|
456
|
+
this.add(item.path, router);
|
|
448
457
|
}
|
|
458
|
+
this.pendingRouters = newPendingLazyRouters;
|
|
449
459
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
handlerMap[i] = handlerData[indexReplacementMap[i]];
|
|
460
|
+
convertOpenAPIPathToRouterPath(path) {
|
|
461
|
+
return standardizeHTTPPath(path).replace(/\{([^}]+)\}/g, ":$1");
|
|
453
462
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// src/fetch/schema-coercer.ts
|
|
466
|
+
var CompositeSchemaCoercer = class {
|
|
467
|
+
constructor(coercers) {
|
|
468
|
+
this.coercers = coercers;
|
|
459
469
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
470
|
+
coerce(schema, value) {
|
|
471
|
+
let current = value;
|
|
472
|
+
for (const coercer of this.coercers) {
|
|
473
|
+
current = coercer.coerce(schema, current);
|
|
463
474
|
}
|
|
475
|
+
return current;
|
|
464
476
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
this
|
|
473
|
-
this
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
});
|
|
500
|
-
} else {
|
|
501
|
-
middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
|
|
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.inputStructureCompact = options?.inputBuilderSimple ?? new InputStructureCompact();
|
|
487
|
+
this.inputStructureDetailed = options?.inputBuilderFull ?? new InputStructureDetailed();
|
|
488
|
+
this.compositeSchemaCoercer = new CompositeSchemaCoercer(options?.schemaCoercers ?? []);
|
|
489
|
+
}
|
|
490
|
+
procedureMatcher;
|
|
491
|
+
payloadCodec;
|
|
492
|
+
inputStructureCompact;
|
|
493
|
+
inputStructureDetailed;
|
|
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 matchedMethod = customMethod || request.method;
|
|
508
|
+
const matched = await this.procedureMatcher.match(matchedMethod, pathname);
|
|
509
|
+
if (!matched) {
|
|
510
|
+
throw new ORPCError2({ code: "NOT_FOUND", message: "Not found" });
|
|
502
511
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
512
|
+
const contractDef = matched.procedure["~orpc"].contract["~orpc"];
|
|
513
|
+
const input = await this.decodeInput(matched.procedure, matched.params, request);
|
|
514
|
+
const coercedInput = this.compositeSchemaCoercer.coerce(contractDef.InputSchema, input);
|
|
515
|
+
const client = createProcedureClient({
|
|
516
|
+
context,
|
|
517
|
+
procedure: matched.procedure,
|
|
518
|
+
path: matched.path
|
|
509
519
|
});
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
}
|
|
520
|
+
const output = await client(coercedInput, { signal: options?.signal });
|
|
521
|
+
const { body, headers: resHeaders } = this.encodeOutput(matched.procedure, output, accept);
|
|
522
|
+
return new Response(body, {
|
|
523
|
+
headers: resHeaders,
|
|
524
|
+
status: contractDef.route?.successStatus ?? 200
|
|
516
525
|
});
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
];
|
|
527
|
-
routes[m][path2].push([handler, paramCount - len + i + 1]);
|
|
526
|
+
};
|
|
527
|
+
try {
|
|
528
|
+
return await executeWithHooks({
|
|
529
|
+
context,
|
|
530
|
+
execute,
|
|
531
|
+
input: request,
|
|
532
|
+
hooks: this.options,
|
|
533
|
+
meta: {
|
|
534
|
+
signal: options?.signal
|
|
528
535
|
}
|
|
529
536
|
});
|
|
537
|
+
} catch (e) {
|
|
538
|
+
const error = this.convertToORPCError(e);
|
|
539
|
+
try {
|
|
540
|
+
const { body, headers: headers2 } = this.payloadCodec.encode(error.toJSON(), accept);
|
|
541
|
+
return new Response(body, {
|
|
542
|
+
status: error.status,
|
|
543
|
+
headers: headers2
|
|
544
|
+
});
|
|
545
|
+
} catch (e2) {
|
|
546
|
+
const error2 = this.convertToORPCError(e2);
|
|
547
|
+
const { body, headers: headers2 } = this.payloadCodec.encode(error2.toJSON(), void 0);
|
|
548
|
+
return new Response(body, {
|
|
549
|
+
status: error2.status,
|
|
550
|
+
headers: headers2
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
async decodeInput(procedure, params, request) {
|
|
556
|
+
const inputStructure = procedure["~orpc"].contract["~orpc"].route?.inputStructure;
|
|
557
|
+
const url = new URL(request.url);
|
|
558
|
+
const query = url.searchParams;
|
|
559
|
+
const headers = request.headers;
|
|
560
|
+
if (!inputStructure || inputStructure === "compact") {
|
|
561
|
+
return this.inputStructureCompact.build(
|
|
562
|
+
params,
|
|
563
|
+
request.method === "GET" ? await this.payloadCodec.decode(query) : await this.payloadCodec.decode(request)
|
|
564
|
+
);
|
|
530
565
|
}
|
|
566
|
+
const _expect = inputStructure;
|
|
567
|
+
const decodedQuery = await this.payloadCodec.decode(query);
|
|
568
|
+
const decodedHeaders = await this.payloadCodec.decode(headers);
|
|
569
|
+
const decodedBody = await this.payloadCodec.decode(request);
|
|
570
|
+
return this.inputStructureDetailed.build(params, decodedQuery, decodedHeaders, decodedBody);
|
|
531
571
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
572
|
+
encodeOutput(procedure, output, accept) {
|
|
573
|
+
const outputStructure = procedure["~orpc"].contract["~orpc"].route?.outputStructure;
|
|
574
|
+
if (!outputStructure || outputStructure === "compact") {
|
|
575
|
+
return this.payloadCodec.encode(output, accept);
|
|
576
|
+
}
|
|
577
|
+
const _expect = outputStructure;
|
|
578
|
+
this.assertDetailedOutput(output);
|
|
579
|
+
const headers = new Headers();
|
|
580
|
+
if (output.headers) {
|
|
581
|
+
for (const [key, value] of Object.entries(output.headers)) {
|
|
582
|
+
headers.append(key, value);
|
|
540
583
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
584
|
+
}
|
|
585
|
+
const { body, headers: encodedHeaders } = this.payloadCodec.encode(output.body, accept);
|
|
586
|
+
if (encodedHeaders) {
|
|
587
|
+
for (const [key, value] of encodedHeaders.entries()) {
|
|
588
|
+
headers.append(key, value);
|
|
544
589
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
};
|
|
548
|
-
return this.match(method, path);
|
|
590
|
+
}
|
|
591
|
+
return { body, headers };
|
|
549
592
|
}
|
|
550
|
-
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
const routes = [];
|
|
560
|
-
let hasOwnRoute = method === METHOD_NAME_ALL;
|
|
561
|
-
[this.#middleware, this.#routes].forEach((r) => {
|
|
562
|
-
const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
|
|
563
|
-
if (ownRoute.length !== 0) {
|
|
564
|
-
hasOwnRoute ||= true;
|
|
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
|
-
);
|
|
593
|
+
assertDetailedOutput(output) {
|
|
594
|
+
const error = new Error(`
|
|
595
|
+
Invalid output structure for 'detailed' output.
|
|
596
|
+
Expected format:
|
|
597
|
+
{
|
|
598
|
+
body?: unknown; // The main response content (optional)
|
|
599
|
+
headers?: { // Additional headers (optional)
|
|
600
|
+
[key: string]: string;
|
|
601
|
+
};
|
|
570
602
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
603
|
+
|
|
604
|
+
Example:
|
|
605
|
+
{
|
|
606
|
+
body: { message: "Success" },
|
|
607
|
+
headers: { "X-Custom-Header": "Custom-Value" },
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
Fix: Ensure your output matches the expected structure.
|
|
611
|
+
`);
|
|
612
|
+
if (!isPlainObject3(output) || Object.keys(output).some((key) => key !== "body" && key !== "headers")) {
|
|
613
|
+
throw error;
|
|
576
614
|
}
|
|
615
|
+
if (output.headers !== void 0 && !isPlainObject3(output.headers)) {
|
|
616
|
+
throw error;
|
|
617
|
+
}
|
|
618
|
+
if (output.headers && Object.entries(output.headers).some(([key, value]) => typeof key !== "string" || typeof value !== "string")) {
|
|
619
|
+
throw error;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
convertToORPCError(e) {
|
|
623
|
+
return e instanceof ORPCError2 ? e : new ORPCError2({
|
|
624
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
625
|
+
message: "Internal server error",
|
|
626
|
+
cause: e
|
|
627
|
+
});
|
|
577
628
|
}
|
|
578
629
|
};
|
|
579
630
|
|
|
580
|
-
// src/fetch/
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
// ../../node_modules/.pnpm/hono@4.6.12/node_modules/hono/dist/router/linear-router/router.js
|
|
586
|
-
var emptyParams = /* @__PURE__ */ Object.create(null);
|
|
587
|
-
var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
|
|
588
|
-
var splitByStarRe = /\*/;
|
|
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]);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
match(method, path) {
|
|
598
|
-
const handlers = [];
|
|
599
|
-
ROUTES_LOOP:
|
|
600
|
-
for (let i = 0, len = this.#routes.length; i < len; i++) {
|
|
601
|
-
const [routeMethod, routePath, handler] = this.#routes[i];
|
|
602
|
-
if (routeMethod === method || routeMethod === METHOD_NAME_ALL) {
|
|
603
|
-
if (routePath === "*" || routePath === "/*") {
|
|
604
|
-
handlers.push([handler, emptyParams]);
|
|
605
|
-
continue;
|
|
606
|
-
}
|
|
607
|
-
const hasStar = routePath.indexOf("*") !== -1;
|
|
608
|
-
const hasLabel = routePath.indexOf(":") !== -1;
|
|
609
|
-
if (!hasStar && !hasLabel) {
|
|
610
|
-
if (routePath === path || routePath + "/" === path) {
|
|
611
|
-
handlers.push([handler, emptyParams]);
|
|
612
|
-
}
|
|
613
|
-
} else if (hasStar && !hasLabel) {
|
|
614
|
-
const endsWithStar = routePath.charCodeAt(routePath.length - 1) === 42;
|
|
615
|
-
const parts = (endsWithStar ? routePath.slice(0, -2) : routePath).split(splitByStarRe);
|
|
616
|
-
const lastIndex = parts.length - 1;
|
|
617
|
-
for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
|
|
618
|
-
const part = parts[j];
|
|
619
|
-
const index = path.indexOf(part, pos);
|
|
620
|
-
if (index !== pos) {
|
|
621
|
-
continue ROUTES_LOOP;
|
|
622
|
-
}
|
|
623
|
-
pos += part.length;
|
|
624
|
-
if (j === lastIndex) {
|
|
625
|
-
if (!endsWithStar && pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) {
|
|
626
|
-
continue ROUTES_LOOP;
|
|
627
|
-
}
|
|
628
|
-
} else {
|
|
629
|
-
const index2 = path.indexOf("/", pos);
|
|
630
|
-
if (index2 === -1) {
|
|
631
|
-
continue ROUTES_LOOP;
|
|
632
|
-
}
|
|
633
|
-
pos = index2;
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
handlers.push([handler, emptyParams]);
|
|
637
|
-
} else if (hasLabel && !hasStar) {
|
|
638
|
-
const params = /* @__PURE__ */ Object.create(null);
|
|
639
|
-
const parts = routePath.match(splitPathRe);
|
|
640
|
-
const lastIndex = parts.length - 1;
|
|
641
|
-
for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
|
|
642
|
-
if (pos === -1 || pos >= path.length) {
|
|
643
|
-
continue ROUTES_LOOP;
|
|
644
|
-
}
|
|
645
|
-
const part = parts[j];
|
|
646
|
-
if (part.charCodeAt(1) === 58) {
|
|
647
|
-
let name = part.slice(2);
|
|
648
|
-
let value2;
|
|
649
|
-
if (name.charCodeAt(name.length - 1) === 125) {
|
|
650
|
-
const openBracePos = name.indexOf("{");
|
|
651
|
-
const pattern = name.slice(openBracePos + 1, -1);
|
|
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
|
-
}
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
return [handlers];
|
|
631
|
+
// src/fetch/openapi-handler-server.ts
|
|
632
|
+
import { TrieRouter } from "hono/router/trie-router";
|
|
633
|
+
var OpenAPIServerHandler = class extends OpenAPIHandler {
|
|
634
|
+
constructor(router, options) {
|
|
635
|
+
super(new TrieRouter(), router, options);
|
|
692
636
|
}
|
|
693
637
|
};
|
|
694
638
|
|
|
695
|
-
// src/fetch/
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
639
|
+
// src/fetch/openapi-handler-serverless.ts
|
|
640
|
+
import { LinearRouter } from "hono/router/linear-router";
|
|
641
|
+
var OpenAPIServerlessHandler = class extends OpenAPIHandler {
|
|
642
|
+
constructor(router, options) {
|
|
643
|
+
super(new LinearRouter(), router, options);
|
|
644
|
+
}
|
|
645
|
+
};
|
|
699
646
|
export {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
647
|
+
CompositeSchemaCoercer,
|
|
648
|
+
InputStructureCompact,
|
|
649
|
+
InputStructureDetailed,
|
|
650
|
+
OpenAPIHandler,
|
|
651
|
+
OpenAPIPayloadCodec,
|
|
652
|
+
OpenAPIProcedureMatcher,
|
|
653
|
+
OpenAPIServerHandler,
|
|
654
|
+
OpenAPIServerlessHandler,
|
|
655
|
+
deserialize,
|
|
656
|
+
escapeSegment,
|
|
657
|
+
parsePath,
|
|
658
|
+
serialize,
|
|
659
|
+
stringifyPath
|
|
705
660
|
};
|
|
706
661
|
//# sourceMappingURL=fetch.js.map
|