@temporary-name/server 1.9.3-alpha.6f8b694b2a090fe0182bfd5f16d29ca20f259307 → 1.9.3-alpha.72daecd600ae901064d3c4f8ab780582c1335ffe
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/adapters/aws-lambda/index.d.mts +5 -7
- package/dist/adapters/aws-lambda/index.d.ts +5 -7
- package/dist/adapters/aws-lambda/index.mjs +6 -9
- package/dist/adapters/fetch/index.d.mts +8 -86
- package/dist/adapters/fetch/index.d.ts +8 -86
- package/dist/adapters/fetch/index.mjs +18 -160
- package/dist/adapters/node/index.d.mts +9 -64
- package/dist/adapters/node/index.d.ts +9 -64
- package/dist/adapters/node/index.mjs +16 -125
- package/dist/handler/index.d.mts +28 -0
- package/dist/handler/index.d.ts +28 -0
- package/dist/handler/index.mjs +8 -0
- package/dist/helpers/index.mjs +3 -29
- package/dist/index.d.mts +373 -493
- package/dist/index.d.ts +373 -493
- package/dist/index.mjs +547 -469
- package/dist/openapi/index.d.mts +18 -53
- package/dist/openapi/index.d.ts +18 -53
- package/dist/openapi/index.mjs +384 -378
- package/dist/shared/server.BwcJq6aP.d.mts +808 -0
- package/dist/shared/server.BwcJq6aP.d.ts +808 -0
- package/dist/shared/server.C1RJffw4.mjs +30 -0
- package/dist/shared/server.CjPiuQYH.d.mts +51 -0
- package/dist/shared/server.CjPiuQYH.d.ts +51 -0
- package/dist/shared/server.D1LXM1bf.mjs +523 -0
- package/dist/shared/server.DEC2sW8B.mjs +496 -0
- package/dist/shared/server.Deg5phAY.d.ts +39 -0
- package/dist/shared/server.H11763QX.mjs +315 -0
- package/dist/shared/server.gSXsB9Bn.mjs +156 -0
- package/dist/shared/server.hAH-LVh_.d.mts +39 -0
- package/package.json +13 -30
- package/dist/adapters/standard/index.d.mts +0 -42
- package/dist/adapters/standard/index.d.ts +0 -42
- package/dist/adapters/standard/index.mjs +0 -11
- package/dist/plugins/index.d.mts +0 -160
- package/dist/plugins/index.d.ts +0 -160
- package/dist/plugins/index.mjs +0 -288
- package/dist/shared/server.BEHw7Eyx.mjs +0 -247
- package/dist/shared/server.BKSOrA6h.d.mts +0 -192
- package/dist/shared/server.BKSOrA6h.d.ts +0 -192
- package/dist/shared/server.BKh8I1Ny.mjs +0 -239
- package/dist/shared/server.BeuTpcmO.d.mts +0 -23
- package/dist/shared/server.C1fnTLq0.d.mts +0 -57
- package/dist/shared/server.CQyYNJ1H.d.ts +0 -57
- package/dist/shared/server.DLsti1Pv.mjs +0 -293
- package/dist/shared/server.SLLuK6_v.d.ts +0 -23
package/dist/index.mjs
CHANGED
|
@@ -1,136 +1,82 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { assertNever, splitFirst, onError, isObject, toArray, guard, resolveMaybeOptionalOptions, isTypescriptObject, isPropertyKey } from '@temporary-name/shared';
|
|
2
|
+
export { AsyncIteratorClass, EventPublisher, asyncIteratorToStream as eventIteratorToStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@temporary-name/shared';
|
|
3
|
+
import * as z from '@temporary-name/zod';
|
|
4
|
+
import { SchemaClass, object, core, gatingContext } from '@temporary-name/zod';
|
|
5
|
+
export { z as baseZ };
|
|
6
|
+
import { U as UnauthorizedError, P as Procedure, m as mergePrefix, a as mergeTags, b as enhanceRouter, C as Contract, p as parseEndpointDefinition, c as mergeRoute, d as prefixRoute, f as addMiddleware, l as lazyInternal, h as getLazyMeta, u as unlazy, j as isProcedure } from './shared/server.DEC2sW8B.mjs';
|
|
7
|
+
export { A as APIError, B as BadRequestError, F as ForbiddenError, I as InternalServerError, L as LAZY_SYMBOL, N as NotFoundError, V as ValidationError, x as createAccessibleLazyRouter, e as encodeError, D as endpointRegex, g as getDynamicParams, w as getRouter, i as isAPIErrorStatus, E as isDevelopment, o as isLazy, q as isStartWithMiddlewares, n as lazy, k as makeErrors, v as mergeMiddlewares, r as resolveContractProcedures, s as standardizeHTTPPath, t as toAPIError, y as traverseContractProcedures, z as unlazyRouter } from './shared/server.DEC2sW8B.mjs';
|
|
8
|
+
import { g as getCookie } from './shared/server.C1RJffw4.mjs';
|
|
9
|
+
import { c as createProcedureClient } from './shared/server.gSXsB9Bn.mjs';
|
|
10
|
+
export { m as mergeCurrentContext, a as middlewareOutputFn } from './shared/server.gSXsB9Bn.mjs';
|
|
11
|
+
import { J as JsonSchemaXNativeType } from './shared/server.D1LXM1bf.mjs';
|
|
12
|
+
export { b as JSON_SCHEMA_INPUT_REGISTRY, c as JSON_SCHEMA_OUTPUT_REGISTRY, a as JSON_SCHEMA_REGISTRY, Z as ZodToJsonSchemaConverter, e as eventIterator, g as getEventIteratorSchemaDetails } from './shared/server.D1LXM1bf.mjs';
|
|
7
13
|
export { getEventMeta, withEventMeta } from '@temporary-name/standard-server';
|
|
8
|
-
import '
|
|
9
|
-
import '
|
|
14
|
+
import 'cookie';
|
|
15
|
+
import '@temporary-name/server/openapi';
|
|
10
16
|
import 'zod/v4/core';
|
|
11
17
|
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const mapped = decorateMiddleware(
|
|
16
|
-
(options, input, ...rest) => middleware(options, mapInput(input), ...rest)
|
|
17
|
-
);
|
|
18
|
-
return mapped;
|
|
19
|
-
};
|
|
20
|
-
decorated.concat = (concatMiddleware, mapInput) => {
|
|
21
|
-
const mapped = mapInput ? decorateMiddleware(concatMiddleware).mapInput(mapInput) : concatMiddleware;
|
|
22
|
-
const concatted = decorateMiddleware((options, input, output, ...rest) => {
|
|
23
|
-
const merged = middleware(
|
|
24
|
-
{
|
|
25
|
-
...options,
|
|
26
|
-
next: (...[nextOptions1]) => mapped(
|
|
27
|
-
{
|
|
28
|
-
...options,
|
|
29
|
-
context: { ...options.context, ...nextOptions1?.context },
|
|
30
|
-
next: (...[nextOptions2]) => options.next({ context: { ...nextOptions1?.context, ...nextOptions2?.context } })
|
|
31
|
-
},
|
|
32
|
-
input,
|
|
33
|
-
output,
|
|
34
|
-
...rest
|
|
35
|
-
)
|
|
36
|
-
},
|
|
37
|
-
input,
|
|
38
|
-
output,
|
|
39
|
-
...rest
|
|
40
|
-
);
|
|
41
|
-
return merged;
|
|
42
|
-
});
|
|
43
|
-
return concatted;
|
|
44
|
-
};
|
|
45
|
-
return decorated;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function isStartWithMiddlewares(middlewares, compare) {
|
|
49
|
-
if (compare.length > middlewares.length) {
|
|
50
|
-
return false;
|
|
18
|
+
function validateTokenPrefix(prefix, token) {
|
|
19
|
+
if (prefix && !token.startsWith(prefix)) {
|
|
20
|
+
throw new UnauthorizedError({ message: `Invalid auth token. It must start with "${prefix}"` });
|
|
51
21
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
22
|
+
}
|
|
23
|
+
function validateTokenAuth(config, token, options) {
|
|
24
|
+
const { tokenPrefix, validate } = config;
|
|
25
|
+
validateTokenPrefix(tokenPrefix, token);
|
|
26
|
+
return validate(token, options);
|
|
27
|
+
}
|
|
28
|
+
function runAuth(config, options) {
|
|
29
|
+
switch (config.type) {
|
|
30
|
+
case "header": {
|
|
31
|
+
const authHeader = options.request.headers.get(config.name);
|
|
32
|
+
return authHeader ? validateTokenAuth(config, authHeader, options) : void 0;
|
|
33
|
+
}
|
|
34
|
+
case "query": {
|
|
35
|
+
const { name, tokenPrefix, validate } = config;
|
|
36
|
+
const query = options.request.url.searchParams;
|
|
37
|
+
const token = query.get(name);
|
|
38
|
+
if (!token) return void 0;
|
|
39
|
+
validateTokenPrefix(tokenPrefix, token);
|
|
40
|
+
return validate(token, options);
|
|
41
|
+
}
|
|
42
|
+
case "cookie": {
|
|
43
|
+
const cookie = getCookie(options.request.headers, config.name);
|
|
44
|
+
return cookie ? validateTokenAuth(config, cookie, options) : void 0;
|
|
45
|
+
}
|
|
46
|
+
case "bearer": {
|
|
47
|
+
const authHeader = options.request.headers.get("Authorization");
|
|
48
|
+
if (!authHeader) return void 0;
|
|
49
|
+
const [authType, bearer] = splitFirst(authHeader, " ");
|
|
50
|
+
return authType === "Bearer" ? validateTokenAuth(config, bearer, options) : void 0;
|
|
51
|
+
}
|
|
52
|
+
case "basic": {
|
|
53
|
+
const authHeader = options.request.headers.get("Authorization");
|
|
54
|
+
if (!authHeader) return void 0;
|
|
55
|
+
const [authType, encoded] = splitFirst(authHeader, " ");
|
|
56
|
+
if (authType !== "Basic") return void 0;
|
|
57
|
+
const decoded = Buffer.from(encoded, "base64").toString("utf-8");
|
|
58
|
+
const [username, password] = splitFirst(decoded, ":");
|
|
59
|
+
validateTokenPrefix(config.tokenPrefix, password);
|
|
60
|
+
return config.validate(username, password, options);
|
|
55
61
|
}
|
|
56
|
-
|
|
62
|
+
case "none": {
|
|
57
63
|
return false;
|
|
58
64
|
}
|
|
65
|
+
default: {
|
|
66
|
+
assertNever(config);
|
|
67
|
+
}
|
|
59
68
|
}
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
function mergeMiddlewares(first, second, options) {
|
|
63
|
-
if (options.dedupeLeading && isStartWithMiddlewares(second, first)) {
|
|
64
|
-
return second;
|
|
65
|
-
}
|
|
66
|
-
return [...first, ...second];
|
|
67
69
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
+
function authDescription(config) {
|
|
71
|
+
const { type } = config;
|
|
72
|
+
return type === "basic" ? "a Basic Authentication header" : type === "bearer" ? "a Bearer Authentication header" : type === "header" ? `a header named "${config.name}"` : type === "query" ? `a query parameter named "${config.name}"` : type === "cookie" ? `a cookie named "${config.name}"` : type === "none" ? "no authentication" : assertNever(type);
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
* This property holds the defined options.
|
|
75
|
-
*/
|
|
76
|
-
"~orpc";
|
|
77
|
-
constructor(def) {
|
|
78
|
-
this["~orpc"] = def;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function isProcedure(item) {
|
|
82
|
-
if (item instanceof Procedure) {
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
return isContractProcedure(item) && "middlewares" in item["~orpc"] && "inputValidationIndex" in item["~orpc"] && "outputValidationIndex" in item["~orpc"] && "handler" in item["~orpc"];
|
|
75
|
+
function mergeMeta(meta1, meta2) {
|
|
76
|
+
return { ...meta1, ...meta2 };
|
|
86
77
|
}
|
|
87
78
|
|
|
88
79
|
class DecoratedProcedure extends Procedure {
|
|
89
|
-
/**
|
|
90
|
-
* Adds type-safe custom errors.
|
|
91
|
-
* The provided errors are spared-merged with any existing errors.
|
|
92
|
-
*
|
|
93
|
-
* @see {@link https://orpc.unnoq.com/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
|
|
94
|
-
*/
|
|
95
|
-
errors(errors) {
|
|
96
|
-
return new DecoratedProcedure({
|
|
97
|
-
...this["~orpc"],
|
|
98
|
-
errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Sets or updates the metadata.
|
|
103
|
-
* The provided metadata is spared-merged with any existing metadata.
|
|
104
|
-
*
|
|
105
|
-
* @see {@link https://orpc.unnoq.com/docs/metadata Metadata Docs}
|
|
106
|
-
*/
|
|
107
|
-
meta(meta) {
|
|
108
|
-
return new DecoratedProcedure({
|
|
109
|
-
...this["~orpc"],
|
|
110
|
-
meta: mergeMeta(this["~orpc"].meta, meta)
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Sets or updates the route definition.
|
|
115
|
-
* The provided route is spared-merged with any existing route.
|
|
116
|
-
* This option is typically relevant when integrating with OpenAPI.
|
|
117
|
-
*
|
|
118
|
-
* @see {@link https://orpc.unnoq.com/docs/openapi/routing OpenAPI Routing Docs}
|
|
119
|
-
* @see {@link https://orpc.unnoq.com/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
|
|
120
|
-
*/
|
|
121
|
-
route(route) {
|
|
122
|
-
return new DecoratedProcedure({
|
|
123
|
-
...this["~orpc"],
|
|
124
|
-
route: mergeRoute(this["~orpc"].route, route)
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
use(middleware, mapInput) {
|
|
128
|
-
const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
|
|
129
|
-
return new DecoratedProcedure({
|
|
130
|
-
...this["~orpc"],
|
|
131
|
-
middlewares: addMiddleware(this["~orpc"].middlewares, mapped)
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
80
|
/**
|
|
135
81
|
* Make this procedure callable (works like a function while still being a procedure).
|
|
136
82
|
*
|
|
@@ -149,244 +95,76 @@ class DecoratedProcedure extends Procedure {
|
|
|
149
95
|
}
|
|
150
96
|
}
|
|
151
97
|
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
return Reflect.get(target, key);
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
function getHiddenRouterContract(router) {
|
|
164
|
-
return router[HIDDEN_ROUTER_CONTRACT_SYMBOL];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function getRouter(router, path) {
|
|
168
|
-
let current = router;
|
|
169
|
-
for (let i = 0; i < path.length; i++) {
|
|
170
|
-
const segment = path[i];
|
|
171
|
-
if (!current) {
|
|
172
|
-
return void 0;
|
|
173
|
-
}
|
|
174
|
-
if (isProcedure(current)) {
|
|
175
|
-
return void 0;
|
|
176
|
-
}
|
|
177
|
-
if (!isLazy(current)) {
|
|
178
|
-
current = current[segment];
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
const lazied = current;
|
|
182
|
-
const rest = path.slice(i);
|
|
183
|
-
return lazy(async () => {
|
|
184
|
-
const unwrapped = await unlazy(lazied);
|
|
185
|
-
const next = getRouter(unwrapped.default, rest);
|
|
186
|
-
return unlazy(next);
|
|
187
|
-
}, getLazyMeta(lazied));
|
|
188
|
-
}
|
|
189
|
-
return current;
|
|
190
|
-
}
|
|
191
|
-
function createAccessibleLazyRouter(lazied) {
|
|
192
|
-
const recursive = new Proxy(lazied, {
|
|
193
|
-
get(target, key) {
|
|
194
|
-
if (typeof key !== "string") {
|
|
195
|
-
return Reflect.get(target, key);
|
|
196
|
-
}
|
|
197
|
-
const next = getRouter(lazied, [key]);
|
|
198
|
-
return createAccessibleLazyRouter(next);
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
|
-
return recursive;
|
|
202
|
-
}
|
|
203
|
-
function enhanceRouter(router, options) {
|
|
204
|
-
if (isLazy(router)) {
|
|
205
|
-
const laziedMeta = getLazyMeta(router);
|
|
206
|
-
const enhancedPrefix = laziedMeta?.prefix ? mergePrefix(options.prefix, laziedMeta?.prefix) : options.prefix;
|
|
207
|
-
const enhanced2 = lazy(
|
|
208
|
-
async () => {
|
|
209
|
-
const { default: unlaziedRouter } = await unlazy(router);
|
|
210
|
-
const enhanced3 = enhanceRouter(unlaziedRouter, options);
|
|
211
|
-
return unlazy(enhanced3);
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
...laziedMeta,
|
|
215
|
-
prefix: enhancedPrefix
|
|
216
|
-
}
|
|
217
|
-
);
|
|
218
|
-
const accessible = createAccessibleLazyRouter(enhanced2);
|
|
219
|
-
return accessible;
|
|
220
|
-
}
|
|
221
|
-
if (isProcedure(router)) {
|
|
222
|
-
const newMiddlewares = mergeMiddlewares(options.middlewares, router["~orpc"].middlewares, {
|
|
223
|
-
dedupeLeading: options.dedupeLeadingMiddlewares
|
|
224
|
-
});
|
|
225
|
-
const newMiddlewareAdded = newMiddlewares.length - router["~orpc"].middlewares.length;
|
|
226
|
-
const enhanced2 = new Procedure({
|
|
227
|
-
...router["~orpc"],
|
|
228
|
-
route: enhanceRoute(router["~orpc"].route, options),
|
|
229
|
-
errorMap: mergeErrorMap(options.errorMap, router["~orpc"].errorMap),
|
|
230
|
-
middlewares: newMiddlewares,
|
|
231
|
-
inputValidationIndex: router["~orpc"].inputValidationIndex + newMiddlewareAdded,
|
|
232
|
-
outputValidationIndex: router["~orpc"].outputValidationIndex + newMiddlewareAdded
|
|
233
|
-
});
|
|
234
|
-
return enhanced2;
|
|
235
|
-
}
|
|
236
|
-
const enhanced = {};
|
|
237
|
-
for (const key in router) {
|
|
238
|
-
enhanced[key] = enhanceRouter(router[key], options);
|
|
239
|
-
}
|
|
240
|
-
return enhanced;
|
|
241
|
-
}
|
|
242
|
-
function traverseContractProcedures(options, callback, lazyOptions = []) {
|
|
243
|
-
let currentRouter = options.router;
|
|
244
|
-
const hiddenContract = getHiddenRouterContract(options.router);
|
|
245
|
-
if (hiddenContract !== void 0) {
|
|
246
|
-
currentRouter = hiddenContract;
|
|
247
|
-
}
|
|
248
|
-
if (isLazy(currentRouter)) {
|
|
249
|
-
lazyOptions.push({
|
|
250
|
-
router: currentRouter,
|
|
251
|
-
path: options.path
|
|
252
|
-
});
|
|
253
|
-
} else if (isContractProcedure(currentRouter)) {
|
|
254
|
-
callback({
|
|
255
|
-
contract: currentRouter,
|
|
256
|
-
path: options.path
|
|
257
|
-
});
|
|
258
|
-
} else {
|
|
259
|
-
for (const key in currentRouter) {
|
|
260
|
-
traverseContractProcedures(
|
|
261
|
-
{
|
|
262
|
-
router: currentRouter[key],
|
|
263
|
-
path: [...options.path, key]
|
|
264
|
-
},
|
|
265
|
-
callback,
|
|
266
|
-
lazyOptions
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return lazyOptions;
|
|
271
|
-
}
|
|
272
|
-
async function resolveContractProcedures(options, callback) {
|
|
273
|
-
const pending = [options];
|
|
274
|
-
for (const options2 of pending) {
|
|
275
|
-
const lazyOptions = traverseContractProcedures(options2, callback);
|
|
276
|
-
for (const options3 of lazyOptions) {
|
|
277
|
-
const { default: router } = await unlazy(options3.router);
|
|
278
|
-
pending.push({
|
|
279
|
-
router,
|
|
280
|
-
path: options3.path
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
async function unlazyRouter(router) {
|
|
286
|
-
if (isProcedure(router)) {
|
|
287
|
-
return router;
|
|
288
|
-
}
|
|
289
|
-
const unlazied = {};
|
|
290
|
-
for (const key in router) {
|
|
291
|
-
const item = router[key];
|
|
292
|
-
const { default: unlaziedRouter } = await unlazy(item);
|
|
293
|
-
unlazied[key] = await unlazyRouter(unlaziedRouter);
|
|
294
|
-
}
|
|
295
|
-
return unlazied;
|
|
296
|
-
}
|
|
98
|
+
const initialSchemas = {
|
|
99
|
+
pathSchema: z.strictObject({}),
|
|
100
|
+
querySchema: z.strictObject({}),
|
|
101
|
+
bodySchema: z.strictObject({}),
|
|
102
|
+
outputSchema: z.unknown()
|
|
103
|
+
};
|
|
297
104
|
|
|
298
|
-
class
|
|
299
|
-
|
|
300
|
-
* This property holds the defined options.
|
|
301
|
-
*/
|
|
302
|
-
"~orpc";
|
|
105
|
+
class ProcedureBuilder extends Contract {
|
|
106
|
+
z;
|
|
303
107
|
constructor(def) {
|
|
304
|
-
|
|
108
|
+
super(def);
|
|
109
|
+
this.z = new SchemaClass();
|
|
305
110
|
}
|
|
306
111
|
/**
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
* @see {@link https://orpc.unnoq.com/docs/context Context Docs}
|
|
310
|
-
*/
|
|
311
|
-
$context() {
|
|
312
|
-
return this;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Creates a middleware.
|
|
316
|
-
*
|
|
317
|
-
* @see {@link https://orpc.unnoq.com/docs/middleware Middleware Docs}
|
|
318
|
-
*/
|
|
319
|
-
middleware(middleware) {
|
|
320
|
-
return decorateMiddleware(middleware);
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Adds type-safe custom errors.
|
|
324
|
-
* The provided errors are spared-merged with any existing errors.
|
|
325
|
-
*
|
|
326
|
-
* @see {@link https://orpc.unnoq.com/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
|
|
327
|
-
*/
|
|
328
|
-
errors(errors) {
|
|
329
|
-
return new Builder({
|
|
330
|
-
...this["~orpc"],
|
|
331
|
-
errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Uses a middleware to modify the context or improve the pipeline.
|
|
336
|
-
*
|
|
337
|
-
* @info Supports both normal middleware and inline middleware implementations.
|
|
338
|
-
* @note The current context must be satisfy middleware dependent-context
|
|
339
|
-
* @see {@link https://orpc.unnoq.com/docs/middleware Middleware Docs}
|
|
340
|
-
*/
|
|
341
|
-
use(middleware) {
|
|
342
|
-
return new Builder({
|
|
343
|
-
...this["~orpc"],
|
|
344
|
-
middlewares: addMiddleware(this["~orpc"].middlewares, middleware)
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
useGating(gates, isGateEnabled) {
|
|
348
|
-
return this.use(({ next, context }) => {
|
|
349
|
-
return gatingContext.run(
|
|
350
|
-
(gate) => isGateEnabled(gate, context),
|
|
351
|
-
() => next({ context: { isGateEnabled } })
|
|
352
|
-
);
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Sets or updates the metadata.
|
|
357
|
-
* The provided metadata is spared-merged with any existing metadata.
|
|
112
|
+
* Sets or updates the metadata for the contract.
|
|
113
|
+
* The provided metadata is spared-merged with any existing metadata in the contract.
|
|
358
114
|
*
|
|
359
115
|
* @see {@link https://orpc.unnoq.com/docs/metadata Metadata Docs}
|
|
360
116
|
*/
|
|
361
117
|
meta(meta) {
|
|
362
|
-
return new
|
|
118
|
+
return new ProcedureBuilder({
|
|
363
119
|
...this["~orpc"],
|
|
364
120
|
meta: mergeMeta(this["~orpc"].meta, meta)
|
|
365
121
|
});
|
|
366
122
|
}
|
|
123
|
+
endpoint(stringsOrEndpoint, ...values) {
|
|
124
|
+
const { method, path, pathSchema } = parseEndpointDefinition(stringsOrEndpoint, values);
|
|
125
|
+
const { prefix } = this["~orpc"];
|
|
126
|
+
const route = { method, path };
|
|
127
|
+
return new ProcedureBuilder({
|
|
128
|
+
...this["~orpc"],
|
|
129
|
+
route: mergeRoute(this["~orpc"].route, prefix ? prefixRoute(route, prefix) : route),
|
|
130
|
+
schemas: {
|
|
131
|
+
...this["~orpc"].schemas,
|
|
132
|
+
pathSchema
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
367
136
|
/**
|
|
368
|
-
* Sets or updates the route definition.
|
|
369
|
-
* The provided route is spared-merged with any existing route.
|
|
137
|
+
* Sets or updates the route definition for the contract.
|
|
138
|
+
* The provided route is spared-merged with any existing route in the contract.
|
|
370
139
|
* This option is typically relevant when integrating with OpenAPI.
|
|
371
140
|
*
|
|
372
141
|
* @see {@link https://orpc.unnoq.com/docs/openapi/routing OpenAPI Routing Docs}
|
|
373
142
|
* @see {@link https://orpc.unnoq.com/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
|
|
374
143
|
*/
|
|
375
|
-
|
|
376
|
-
|
|
144
|
+
endpointOpts(route) {
|
|
145
|
+
const { prefix } = this["~orpc"];
|
|
146
|
+
return new ProcedureBuilder({
|
|
377
147
|
...this["~orpc"],
|
|
378
|
-
route: mergeRoute(this["~orpc"].route, route)
|
|
148
|
+
route: mergeRoute(this["~orpc"].route, prefix ? prefixRoute(route, prefix) : route)
|
|
379
149
|
});
|
|
380
150
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
*
|
|
384
|
-
* @see {@link https://orpc.unnoq.com/docs/procedure#input-output-validation Input Validation Docs}
|
|
385
|
-
*/
|
|
386
|
-
input(schema) {
|
|
387
|
-
return new Builder({
|
|
151
|
+
query(schema) {
|
|
152
|
+
return new ProcedureBuilder({
|
|
388
153
|
...this["~orpc"],
|
|
389
|
-
|
|
154
|
+
schemas: {
|
|
155
|
+
...this["~orpc"].schemas,
|
|
156
|
+
querySchema: schema instanceof core.$ZodType ? schema : object(schema)
|
|
157
|
+
},
|
|
158
|
+
inputValidationIndex: this["~orpc"].middlewares.length
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
body(schema) {
|
|
162
|
+
return new ProcedureBuilder({
|
|
163
|
+
...this["~orpc"],
|
|
164
|
+
schemas: {
|
|
165
|
+
...this["~orpc"].schemas,
|
|
166
|
+
bodySchema: schema instanceof core.$ZodType ? schema : object(schema)
|
|
167
|
+
},
|
|
390
168
|
inputValidationIndex: this["~orpc"].middlewares.length
|
|
391
169
|
});
|
|
392
170
|
}
|
|
@@ -396,23 +174,79 @@ class Builder {
|
|
|
396
174
|
* @see {@link https://orpc.unnoq.com/docs/procedure#input-output-validation Output Validation Docs}
|
|
397
175
|
*/
|
|
398
176
|
output(schema) {
|
|
399
|
-
return new
|
|
177
|
+
return new ProcedureBuilder({
|
|
400
178
|
...this["~orpc"],
|
|
401
|
-
|
|
179
|
+
schemas: {
|
|
180
|
+
...this["~orpc"].schemas,
|
|
181
|
+
outputSchema: schema instanceof core.$ZodType ? schema : object(schema)
|
|
182
|
+
},
|
|
402
183
|
outputValidationIndex: this["~orpc"].middlewares.length
|
|
403
184
|
});
|
|
404
185
|
}
|
|
186
|
+
use(middleware) {
|
|
187
|
+
return new this.constructor({
|
|
188
|
+
...this["~orpc"],
|
|
189
|
+
middlewares: addMiddleware(this["~orpc"].middlewares, middleware)
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
useErrors(errorMap) {
|
|
193
|
+
return new this.constructor({
|
|
194
|
+
...this["~orpc"],
|
|
195
|
+
errorMap
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
// The default of false for ValidatedAuthContext is used when you pass in the type 'none'. We use false
|
|
199
|
+
// because we can't use null or undefined (see ValidatedAuthContext) but we still want it to be falsy.
|
|
200
|
+
useAuth(config) {
|
|
201
|
+
const middleware = baseApi.$context().middleware(async (options) => {
|
|
202
|
+
const { next, context } = options;
|
|
203
|
+
if (context.auth) return next();
|
|
204
|
+
const auth = await runAuth(config, options);
|
|
205
|
+
if (auth === void 0) {
|
|
206
|
+
const { authConfigs } = options.procedure["~orpc"];
|
|
207
|
+
if (context.auth !== false && config === authConfigs.at(-1)) {
|
|
208
|
+
let authDescriptions = authConfigs.map(authDescription).join(", ");
|
|
209
|
+
if (authConfigs.length > 1) {
|
|
210
|
+
authDescriptions = `one of: ${authDescriptions}`;
|
|
211
|
+
}
|
|
212
|
+
throw new UnauthorizedError({
|
|
213
|
+
message: `Authentication required. You must provide ${authDescriptions}`
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return next();
|
|
217
|
+
}
|
|
218
|
+
return next({ context: { auth } });
|
|
219
|
+
});
|
|
220
|
+
return new this.constructor({
|
|
221
|
+
...this["~orpc"],
|
|
222
|
+
authConfigs: [...this["~orpc"].authConfigs, config],
|
|
223
|
+
middlewares: addMiddleware(this["~orpc"].middlewares, middleware)
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
useGating(gates, isGateEnabled) {
|
|
227
|
+
return this.use(({ next, context }) => {
|
|
228
|
+
return gatingContext.run(
|
|
229
|
+
(gate) => isGateEnabled(gate, context),
|
|
230
|
+
() => next({ context: { isGateEnabled } })
|
|
231
|
+
);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
405
234
|
/**
|
|
406
235
|
* Defines the handler of the procedure.
|
|
407
236
|
*
|
|
408
237
|
* @see {@link https://orpc.unnoq.com/docs/procedure Procedure Docs}
|
|
409
238
|
*/
|
|
410
239
|
handler(handler) {
|
|
240
|
+
if (this["~orpc"].schemas.outputSchema === initialSchemas.outputSchema) {
|
|
241
|
+
throw new Error("You must call .output() before calling .handler()");
|
|
242
|
+
}
|
|
411
243
|
return new DecoratedProcedure({
|
|
412
244
|
...this["~orpc"],
|
|
413
245
|
handler
|
|
414
246
|
});
|
|
415
247
|
}
|
|
248
|
+
}
|
|
249
|
+
class BuilderWithMiddlewares extends ProcedureBuilder {
|
|
416
250
|
/**
|
|
417
251
|
* Prefixes all procedures in the router.
|
|
418
252
|
* The provided prefix is post-appended to any existing router prefix.
|
|
@@ -422,7 +256,7 @@ class Builder {
|
|
|
422
256
|
* @see {@link https://orpc.unnoq.com/docs/openapi/routing#route-prefixes OpenAPI Route Prefixes Docs}
|
|
423
257
|
*/
|
|
424
258
|
prefix(prefix) {
|
|
425
|
-
return new
|
|
259
|
+
return new this.constructor({
|
|
426
260
|
...this["~orpc"],
|
|
427
261
|
prefix: mergePrefix(this["~orpc"].prefix, prefix)
|
|
428
262
|
});
|
|
@@ -434,7 +268,7 @@ class Builder {
|
|
|
434
268
|
* @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification#operation-metadata OpenAPI Operation Metadata Docs}
|
|
435
269
|
*/
|
|
436
270
|
tag(...tags) {
|
|
437
|
-
return new
|
|
271
|
+
return new this.constructor({
|
|
438
272
|
...this["~orpc"],
|
|
439
273
|
tags: mergeTags(this["~orpc"].tags, tags)
|
|
440
274
|
});
|
|
@@ -447,123 +281,383 @@ class Builder {
|
|
|
447
281
|
router(router) {
|
|
448
282
|
return enhanceRouter(router, this["~orpc"]);
|
|
449
283
|
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function decorateMiddleware(middleware) {
|
|
287
|
+
const decorated = ((...args) => middleware(...args));
|
|
288
|
+
decorated.mapInput = (mapInput) => {
|
|
289
|
+
const mapped = decorateMiddleware(
|
|
290
|
+
(options, input, ...rest) => middleware(options, mapInput(input), ...rest)
|
|
291
|
+
);
|
|
292
|
+
return mapped;
|
|
293
|
+
};
|
|
294
|
+
return decorated;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
class Builder extends BuilderWithMiddlewares {
|
|
450
298
|
/**
|
|
451
|
-
*
|
|
452
|
-
* And applies all of the previously defined options to the specified router.
|
|
299
|
+
* Set or override the initial context.
|
|
453
300
|
*
|
|
454
|
-
* @see {@link https://orpc.unnoq.com/docs/
|
|
301
|
+
* @see {@link https://orpc.unnoq.com/docs/context Context Docs}
|
|
455
302
|
*/
|
|
456
|
-
|
|
457
|
-
return
|
|
303
|
+
$context() {
|
|
304
|
+
return this;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Creates a middleware.
|
|
308
|
+
*
|
|
309
|
+
* @see {@link https://orpc.unnoq.com/docs/middleware Middleware Docs}
|
|
310
|
+
*/
|
|
311
|
+
middleware(middleware) {
|
|
312
|
+
return decorateMiddleware(middleware);
|
|
458
313
|
}
|
|
459
314
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
const os = createApiBuilder();
|
|
315
|
+
const baseApi = new Builder({
|
|
316
|
+
route: {},
|
|
317
|
+
meta: {},
|
|
318
|
+
errorMap: {},
|
|
319
|
+
inputValidationIndex: 0,
|
|
320
|
+
outputValidationIndex: 0,
|
|
321
|
+
middlewares: [
|
|
322
|
+
onError((error, _options) => {
|
|
323
|
+
console.dir(error, { depth: null });
|
|
324
|
+
})
|
|
325
|
+
],
|
|
326
|
+
schemas: initialSchemas,
|
|
327
|
+
// NB: this is a relic from orpc -- I'm not convinced there's a need for this (or if there is, that it's
|
|
328
|
+
// the best solution). For now I've removed the interface to configure it externally.
|
|
329
|
+
dedupeLeadingMiddlewares: true,
|
|
330
|
+
authConfigs: []
|
|
331
|
+
});
|
|
479
332
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
errorMap: {},
|
|
508
|
-
prefix: void 0,
|
|
509
|
-
tags: void 0,
|
|
510
|
-
dedupeLeadingMiddlewares: true
|
|
511
|
-
});
|
|
512
|
-
return setHiddenRouterContract(adapted, contract);
|
|
513
|
-
};
|
|
514
|
-
} else if (key === "lazyRoute") {
|
|
515
|
-
method = (loader) => {
|
|
516
|
-
const adapted = enhanceRouter(lazy(loader), {
|
|
517
|
-
middlewares,
|
|
518
|
-
errorMap: {},
|
|
519
|
-
prefix: void 0,
|
|
520
|
-
tags: void 0,
|
|
521
|
-
dedupeLeadingMiddlewares: true
|
|
522
|
-
});
|
|
523
|
-
return setHiddenRouterContract(adapted, contract);
|
|
524
|
-
};
|
|
333
|
+
const FLEXIBLE_DATE_FORMAT_REGEX = /^[^-]+-[^-]+-[^-]+$/;
|
|
334
|
+
class experimental_JsonSchemaCoercer {
|
|
335
|
+
coerce(schema, value, options = {}) {
|
|
336
|
+
const [, coerced] = this.#coerce(schema, value, options);
|
|
337
|
+
return coerced;
|
|
338
|
+
}
|
|
339
|
+
#coerce(schema, originalValue, options) {
|
|
340
|
+
if (typeof schema === "boolean") {
|
|
341
|
+
return [schema, originalValue];
|
|
342
|
+
}
|
|
343
|
+
if (Array.isArray(schema.type)) {
|
|
344
|
+
return this.#coerce(
|
|
345
|
+
{
|
|
346
|
+
anyOf: schema.type.map((type) => ({ ...schema, type }))
|
|
347
|
+
},
|
|
348
|
+
originalValue,
|
|
349
|
+
options
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
let coerced = originalValue;
|
|
353
|
+
let satisfied = true;
|
|
354
|
+
if (typeof schema.$ref === "string") {
|
|
355
|
+
const refSchema = options?.components?.[schema.$ref];
|
|
356
|
+
if (refSchema !== void 0) {
|
|
357
|
+
const [subSatisfied, subCoerced] = this.#coerce(refSchema, coerced, options);
|
|
358
|
+
coerced = subCoerced;
|
|
359
|
+
satisfied = subSatisfied;
|
|
525
360
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
361
|
+
}
|
|
362
|
+
const enumValues = schema.const !== void 0 ? [schema.const] : schema.enum;
|
|
363
|
+
if (enumValues !== void 0 && !enumValues.includes(coerced)) {
|
|
364
|
+
if (typeof coerced === "string") {
|
|
365
|
+
const numberValue = this.#stringToNumber(coerced);
|
|
366
|
+
if (enumValues.includes(numberValue)) {
|
|
367
|
+
coerced = numberValue;
|
|
368
|
+
} else {
|
|
369
|
+
const booleanValue = this.#stringToBoolean(coerced);
|
|
370
|
+
if (enumValues.includes(booleanValue)) {
|
|
371
|
+
coerced = booleanValue;
|
|
372
|
+
} else {
|
|
373
|
+
satisfied = false;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
} else {
|
|
377
|
+
satisfied = false;
|
|
529
378
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
379
|
+
}
|
|
380
|
+
if (typeof schema.type === "string") {
|
|
381
|
+
switch (schema.type) {
|
|
382
|
+
case "null": {
|
|
383
|
+
if (coerced !== null) {
|
|
384
|
+
satisfied = false;
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
case "string": {
|
|
389
|
+
if (typeof coerced !== "string") {
|
|
390
|
+
satisfied = false;
|
|
535
391
|
}
|
|
536
|
-
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
case "number": {
|
|
395
|
+
if (typeof coerced === "string") {
|
|
396
|
+
coerced = this.#stringToNumber(coerced);
|
|
397
|
+
}
|
|
398
|
+
if (typeof coerced !== "number") {
|
|
399
|
+
satisfied = false;
|
|
400
|
+
}
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
case "integer": {
|
|
404
|
+
if (typeof coerced === "string") {
|
|
405
|
+
coerced = this.#stringToInteger(coerced);
|
|
406
|
+
}
|
|
407
|
+
if (typeof coerced !== "number" || !Number.isInteger(coerced)) {
|
|
408
|
+
satisfied = false;
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
case "boolean": {
|
|
413
|
+
if (typeof coerced === "string") {
|
|
414
|
+
coerced = this.#stringToBoolean(coerced);
|
|
415
|
+
}
|
|
416
|
+
if (typeof coerced !== "boolean") {
|
|
417
|
+
satisfied = false;
|
|
418
|
+
}
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
case "array": {
|
|
422
|
+
if (Array.isArray(coerced)) {
|
|
423
|
+
const prefixItemSchemas = "prefixItems" in schema ? toArray(schema.prefixItems) : Array.isArray(schema.items) ? schema.items : [];
|
|
424
|
+
const itemSchema = Array.isArray(schema.items) ? schema.additionalItems : schema.items;
|
|
425
|
+
let shouldUseCoercedItems = false;
|
|
426
|
+
const coercedItems = coerced.map((item, i) => {
|
|
427
|
+
const subSchema = prefixItemSchemas[i] ?? itemSchema;
|
|
428
|
+
if (subSchema === void 0) {
|
|
429
|
+
satisfied = false;
|
|
430
|
+
return item;
|
|
431
|
+
}
|
|
432
|
+
const [subSatisfied, subCoerced] = this.#coerce(subSchema, item, options);
|
|
433
|
+
if (!subSatisfied) {
|
|
434
|
+
satisfied = false;
|
|
435
|
+
}
|
|
436
|
+
if (subCoerced !== item) {
|
|
437
|
+
shouldUseCoercedItems = true;
|
|
438
|
+
}
|
|
439
|
+
return subCoerced;
|
|
440
|
+
});
|
|
441
|
+
if (coercedItems.length < prefixItemSchemas.length) {
|
|
442
|
+
satisfied = false;
|
|
443
|
+
}
|
|
444
|
+
if (shouldUseCoercedItems) {
|
|
445
|
+
coerced = coercedItems;
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
satisfied = false;
|
|
449
|
+
}
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
case "object": {
|
|
453
|
+
if (Array.isArray(coerced)) {
|
|
454
|
+
coerced = { ...coerced };
|
|
455
|
+
}
|
|
456
|
+
if (isObject(coerced)) {
|
|
457
|
+
let shouldUseCoercedItems = false;
|
|
458
|
+
const coercedItems = {};
|
|
459
|
+
const patternProperties = Object.entries(schema.patternProperties ?? {}).map(
|
|
460
|
+
([key, value]) => [new RegExp(key), value]
|
|
461
|
+
);
|
|
462
|
+
for (const key in coerced) {
|
|
463
|
+
const value = coerced[key];
|
|
464
|
+
const subSchema = schema.properties?.[key] ?? patternProperties.find(([pattern]) => pattern.test(key))?.[1] ?? schema.additionalProperties;
|
|
465
|
+
if (value === void 0 && !schema.required?.includes(key)) {
|
|
466
|
+
coercedItems[key] = value;
|
|
467
|
+
} else if (subSchema === void 0) {
|
|
468
|
+
coercedItems[key] = value;
|
|
469
|
+
satisfied = false;
|
|
470
|
+
} else {
|
|
471
|
+
const [subSatisfied, subCoerced] = this.#coerce(subSchema, value, options);
|
|
472
|
+
coercedItems[key] = subCoerced;
|
|
473
|
+
if (!subSatisfied) {
|
|
474
|
+
satisfied = false;
|
|
475
|
+
}
|
|
476
|
+
if (subCoerced !== value) {
|
|
477
|
+
shouldUseCoercedItems = true;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
if (schema.required?.some((key) => !Object.hasOwn(coercedItems, key))) {
|
|
482
|
+
satisfied = false;
|
|
483
|
+
}
|
|
484
|
+
if (shouldUseCoercedItems) {
|
|
485
|
+
coerced = coercedItems;
|
|
486
|
+
}
|
|
487
|
+
} else {
|
|
488
|
+
satisfied = false;
|
|
489
|
+
}
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
537
492
|
}
|
|
538
|
-
return nextImpl;
|
|
539
493
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
494
|
+
if ("x-native-type" in schema && typeof schema["x-native-type"] === "string") {
|
|
495
|
+
switch (schema["x-native-type"]) {
|
|
496
|
+
case JsonSchemaXNativeType.Date: {
|
|
497
|
+
if (typeof coerced === "string") {
|
|
498
|
+
coerced = this.#stringToDate(coerced);
|
|
499
|
+
}
|
|
500
|
+
if (!(coerced instanceof Date)) {
|
|
501
|
+
satisfied = false;
|
|
502
|
+
}
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
case JsonSchemaXNativeType.BigInt: {
|
|
506
|
+
switch (typeof coerced) {
|
|
507
|
+
case "string":
|
|
508
|
+
coerced = this.#stringToBigInt(coerced);
|
|
509
|
+
break;
|
|
510
|
+
case "number":
|
|
511
|
+
coerced = this.#numberToBigInt(coerced);
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
if (typeof coerced !== "bigint") {
|
|
515
|
+
satisfied = false;
|
|
516
|
+
}
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
case JsonSchemaXNativeType.RegExp: {
|
|
520
|
+
if (typeof coerced === "string") {
|
|
521
|
+
coerced = this.#stringToRegExp(coerced);
|
|
522
|
+
}
|
|
523
|
+
if (!(coerced instanceof RegExp)) {
|
|
524
|
+
satisfied = false;
|
|
525
|
+
}
|
|
526
|
+
break;
|
|
527
|
+
}
|
|
528
|
+
case JsonSchemaXNativeType.Url: {
|
|
529
|
+
if (typeof coerced === "string") {
|
|
530
|
+
coerced = this.#stringToURL(coerced);
|
|
531
|
+
}
|
|
532
|
+
if (!(coerced instanceof URL)) {
|
|
533
|
+
satisfied = false;
|
|
534
|
+
}
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
case JsonSchemaXNativeType.Set: {
|
|
538
|
+
if (Array.isArray(coerced)) {
|
|
539
|
+
coerced = this.#arrayToSet(coerced);
|
|
540
|
+
}
|
|
541
|
+
if (!(coerced instanceof Set)) {
|
|
542
|
+
satisfied = false;
|
|
543
|
+
}
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
case JsonSchemaXNativeType.Map: {
|
|
547
|
+
if (Array.isArray(coerced)) {
|
|
548
|
+
coerced = this.#arrayToMap(coerced);
|
|
549
|
+
}
|
|
550
|
+
if (!(coerced instanceof Map)) {
|
|
551
|
+
satisfied = false;
|
|
552
|
+
}
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
550
555
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
556
|
+
}
|
|
557
|
+
if (schema.allOf) {
|
|
558
|
+
for (const subSchema of schema.allOf) {
|
|
559
|
+
const [subSatisfied, subCoerced] = this.#coerce(subSchema, coerced, options);
|
|
560
|
+
coerced = subCoerced;
|
|
561
|
+
if (!subSatisfied) {
|
|
562
|
+
satisfied = false;
|
|
563
|
+
}
|
|
554
564
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
565
|
+
}
|
|
566
|
+
for (const key of ["anyOf", "oneOf"]) {
|
|
567
|
+
if (schema[key]) {
|
|
568
|
+
let bestOptions;
|
|
569
|
+
for (const subSchema of schema[key]) {
|
|
570
|
+
const [subSatisfied, subCoerced] = this.#coerce(subSchema, coerced, options);
|
|
571
|
+
if (subSatisfied) {
|
|
572
|
+
if (!bestOptions || subCoerced === coerced) {
|
|
573
|
+
bestOptions = { coerced: subCoerced, satisfied: subSatisfied };
|
|
574
|
+
}
|
|
575
|
+
if (subCoerced === coerced) {
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
558
579
|
}
|
|
559
|
-
|
|
580
|
+
coerced = bestOptions ? bestOptions.coerced : coerced;
|
|
581
|
+
satisfied = bestOptions ? bestOptions.satisfied : false;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if (typeof schema.not !== "undefined") {
|
|
585
|
+
const [notSatisfied] = this.#coerce(schema.not, coerced, options);
|
|
586
|
+
if (notSatisfied) {
|
|
587
|
+
satisfied = false;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return [satisfied, coerced];
|
|
591
|
+
}
|
|
592
|
+
#stringToNumber(value) {
|
|
593
|
+
const num = Number.parseFloat(value);
|
|
594
|
+
if (Number.isNaN(num) || num !== Number(value)) {
|
|
595
|
+
return value;
|
|
596
|
+
}
|
|
597
|
+
return num;
|
|
598
|
+
}
|
|
599
|
+
#stringToInteger(value) {
|
|
600
|
+
const num = Number.parseInt(value);
|
|
601
|
+
if (Number.isNaN(num) || num !== Number(value)) {
|
|
602
|
+
return value;
|
|
603
|
+
}
|
|
604
|
+
return num;
|
|
605
|
+
}
|
|
606
|
+
#stringToBoolean(value) {
|
|
607
|
+
const lower = value.toLowerCase();
|
|
608
|
+
if (lower === "false" || lower === "off") {
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
if (lower === "true" || lower === "on") {
|
|
612
|
+
return true;
|
|
613
|
+
}
|
|
614
|
+
return value;
|
|
615
|
+
}
|
|
616
|
+
#stringToBigInt(value) {
|
|
617
|
+
return guard(() => BigInt(value)) ?? value;
|
|
618
|
+
}
|
|
619
|
+
#numberToBigInt(value) {
|
|
620
|
+
return guard(() => BigInt(value)) ?? value;
|
|
621
|
+
}
|
|
622
|
+
#stringToDate(value) {
|
|
623
|
+
const date = new Date(value);
|
|
624
|
+
if (Number.isNaN(date.getTime()) || !FLEXIBLE_DATE_FORMAT_REGEX.test(value)) {
|
|
625
|
+
return value;
|
|
626
|
+
}
|
|
627
|
+
return date;
|
|
628
|
+
}
|
|
629
|
+
#stringToRegExp(value) {
|
|
630
|
+
const match = value.match(/^\/(.*)\/([a-z]*)$/);
|
|
631
|
+
if (match) {
|
|
632
|
+
const [, pattern, flags] = match;
|
|
633
|
+
return guard(() => new RegExp(pattern, flags)) ?? value;
|
|
560
634
|
}
|
|
561
|
-
|
|
562
|
-
|
|
635
|
+
return value;
|
|
636
|
+
}
|
|
637
|
+
#stringToURL(value) {
|
|
638
|
+
return guard(() => new URL(value)) ?? value;
|
|
639
|
+
}
|
|
640
|
+
#arrayToSet(value) {
|
|
641
|
+
const set = new Set(value);
|
|
642
|
+
if (set.size !== value.length) {
|
|
643
|
+
return value;
|
|
644
|
+
}
|
|
645
|
+
return set;
|
|
646
|
+
}
|
|
647
|
+
#arrayToMap(value) {
|
|
648
|
+
if (value.some((item) => !Array.isArray(item) || item.length !== 2)) {
|
|
649
|
+
return value;
|
|
650
|
+
}
|
|
651
|
+
const result = new Map(value);
|
|
652
|
+
if (result.size !== value.length) {
|
|
653
|
+
return value;
|
|
654
|
+
}
|
|
655
|
+
return result;
|
|
656
|
+
}
|
|
563
657
|
}
|
|
564
658
|
|
|
565
659
|
function createAssertedLazyProcedure(lazied) {
|
|
566
|
-
const lazyProcedure =
|
|
660
|
+
const lazyProcedure = lazyInternal(async () => {
|
|
567
661
|
const { default: maybeProcedure } = await unlazy(lazied);
|
|
568
662
|
if (!isProcedure(maybeProcedure)) {
|
|
569
663
|
throw new Error(`
|
|
@@ -576,42 +670,26 @@ function createAssertedLazyProcedure(lazied) {
|
|
|
576
670
|
}, getLazyMeta(lazied));
|
|
577
671
|
return lazyProcedure;
|
|
578
672
|
}
|
|
579
|
-
function createContractedProcedure(procedure, contract) {
|
|
580
|
-
return new Procedure({
|
|
581
|
-
...procedure["~orpc"],
|
|
582
|
-
errorMap: contract["~orpc"].errorMap,
|
|
583
|
-
route: contract["~orpc"].route,
|
|
584
|
-
meta: contract["~orpc"].meta
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
673
|
function call(procedure, input, ...rest) {
|
|
588
674
|
const options = resolveMaybeOptionalOptions(rest);
|
|
589
675
|
return createProcedureClient(procedure, options)(input, options);
|
|
590
676
|
}
|
|
591
677
|
|
|
592
|
-
function
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
const recursive = new Proxy(procedureCaller, {
|
|
600
|
-
get(target, key) {
|
|
601
|
-
if (typeof key !== "string") {
|
|
602
|
-
return Reflect.get(target, key);
|
|
603
|
-
}
|
|
604
|
-
const next = getRouter(router, [key]);
|
|
605
|
-
if (!next) {
|
|
606
|
-
return Reflect.get(target, key);
|
|
607
|
-
}
|
|
608
|
-
return createRouterClient(next, {
|
|
609
|
-
...rest[0],
|
|
610
|
-
path: [...rest[0]?.path ?? [], key]
|
|
611
|
-
});
|
|
678
|
+
function isSchemaIssue(issue) {
|
|
679
|
+
if (!isTypescriptObject(issue) || typeof issue.message !== "string") {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
if (issue.path !== void 0) {
|
|
683
|
+
if (!Array.isArray(issue.path)) {
|
|
684
|
+
return false;
|
|
612
685
|
}
|
|
613
|
-
|
|
614
|
-
|
|
686
|
+
if (!issue.path.every(
|
|
687
|
+
(segment) => isPropertyKey(segment) || isTypescriptObject(segment) && isPropertyKey(segment.key)
|
|
688
|
+
)) {
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
return true;
|
|
615
693
|
}
|
|
616
694
|
|
|
617
|
-
export { Builder, DecoratedProcedure, Procedure,
|
|
695
|
+
export { Builder, BuilderWithMiddlewares, Contract, DecoratedProcedure, JsonSchemaXNativeType, Procedure, ProcedureBuilder, UnauthorizedError, addMiddleware, baseApi, call, createAssertedLazyProcedure, createProcedureClient, decorateMiddleware, enhanceRouter, experimental_JsonSchemaCoercer, getLazyMeta, initialSchemas, isProcedure, isSchemaIssue, lazyInternal, mergeMeta, parseEndpointDefinition, unlazy };
|