@orpc/server 1.14.10 → 1.14.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -98
- package/dist/adapters/crossws/index.d.mts +45 -21
- package/dist/adapters/crossws/index.d.ts +45 -21
- package/dist/adapters/crossws/index.mjs +40 -18
- package/dist/adapters/fetch/index.d.mts +64 -96
- package/dist/adapters/fetch/index.d.ts +64 -96
- package/dist/adapters/fetch/index.mjs +34 -139
- package/dist/adapters/message-port/index.d.mts +49 -34
- package/dist/adapters/message-port/index.d.ts +49 -34
- package/dist/adapters/message-port/index.mjs +68 -37
- package/dist/adapters/node/index.d.mts +63 -71
- package/dist/adapters/node/index.d.ts +63 -71
- package/dist/adapters/node/index.mjs +36 -113
- package/dist/adapters/standard/index.d.mts +16 -18
- package/dist/adapters/standard/index.d.ts +16 -18
- package/dist/adapters/standard/index.mjs +5 -5
- package/dist/adapters/standard-peer/index.d.mts +12 -14
- package/dist/adapters/standard-peer/index.d.ts +12 -14
- package/dist/adapters/standard-peer/index.mjs +2 -21
- package/dist/adapters/websocket/index.d.mts +53 -38
- package/dist/adapters/websocket/index.d.ts +53 -38
- package/dist/adapters/websocket/index.mjs +59 -42
- package/dist/extensions/callable.d.mts +10 -0
- package/dist/extensions/callable.d.ts +10 -0
- package/dist/extensions/callable.mjs +11 -0
- package/dist/helpers/index.d.mts +4 -4
- package/dist/helpers/index.d.ts +4 -4
- package/dist/helpers/index.mjs +13 -5
- package/dist/index.d.mts +166 -770
- package/dist/index.d.ts +166 -770
- package/dist/index.mjs +306 -399
- package/dist/plugins/index.d.mts +214 -121
- package/dist/plugins/index.d.ts +214 -121
- package/dist/plugins/index.mjs +576 -214
- package/dist/shared/server.15O7oC1p.d.mts +61 -0
- package/dist/shared/server.B4BnEWWm.d.mts +67 -0
- package/dist/shared/server.BhsVw7m7.d.ts +104 -0
- package/dist/shared/server.BoiFpNT7.mjs +224 -0
- package/dist/shared/server.COPVXhDG.mjs +271 -0
- package/dist/shared/server.CX4vUnDk.mjs +11 -0
- package/dist/shared/server.CcR4kgje.d.mts +206 -0
- package/dist/shared/server.CcR4kgje.d.ts +206 -0
- package/dist/shared/server.CnN50DHH.d.ts +67 -0
- package/dist/shared/server.DBs0rrf9.mjs +41 -0
- package/dist/shared/server.DDFizwfU.d.mts +104 -0
- package/dist/shared/server.D_QauotT.mjs +30 -0
- package/dist/shared/server.DofEOwf-.mjs +237 -0
- package/dist/shared/{server.DZ5BIITo.mjs → server.W91HSRkE.mjs} +2 -2
- package/dist/shared/server.m3szVJGU.d.ts +61 -0
- package/package.json +26 -56
- package/dist/adapters/aws-lambda/index.d.mts +0 -46
- package/dist/adapters/aws-lambda/index.d.ts +0 -46
- package/dist/adapters/aws-lambda/index.mjs +0 -40
- package/dist/adapters/bun-ws/index.d.mts +0 -36
- package/dist/adapters/bun-ws/index.d.ts +0 -36
- package/dist/adapters/bun-ws/index.mjs +0 -47
- package/dist/adapters/fastify/index.d.mts +0 -53
- package/dist/adapters/fastify/index.d.ts +0 -53
- package/dist/adapters/fastify/index.mjs +0 -52
- package/dist/adapters/ws/index.d.mts +0 -31
- package/dist/adapters/ws/index.d.ts +0 -31
- package/dist/adapters/ws/index.mjs +0 -41
- package/dist/hibernation/index.d.mts +0 -44
- package/dist/hibernation/index.d.ts +0 -44
- package/dist/hibernation/index.mjs +0 -65
- package/dist/shared/server.7cEtMB30.d.ts +0 -74
- package/dist/shared/server.B8gYOD5g.d.mts +0 -12
- package/dist/shared/server.BqadksTP.d.mts +0 -74
- package/dist/shared/server.C8_sRzQB.d.mts +0 -42
- package/dist/shared/server.ChUyt5-i.d.mts +0 -32
- package/dist/shared/server.ChyoA9XY.d.ts +0 -42
- package/dist/shared/server.DEBcqOjg.mjs +0 -418
- package/dist/shared/server.EfTOZ2Q7.d.ts +0 -12
- package/dist/shared/server.TEVCLCFC.mjs +0 -39
- package/dist/shared/server.ZxHCEN1h.mjs +0 -226
- package/dist/shared/server.qKsRrdxW.d.mts +0 -193
- package/dist/shared/server.qKsRrdxW.d.ts +0 -193
- package/dist/shared/server.yoEB3Fx4.d.ts +0 -32
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { ORPCError, toORPCError, RPCSerializer, COMMON_ERROR_STATUS_MAP } from '@orpc/client';
|
|
2
|
+
import { sortPlugins, getOpenTelemetryConfig, runWithSpan, toArray, matchesHttpPathPrefix, intercept, ORPC_NAME, isAsyncIteratorObject, override, traceAsyncIterator, recordSpanError, pathToHttpPath, normalizeHttpPath, value, parseEmptyableJSON } from '@orpc/shared';
|
|
3
|
+
import { flattenStandardHeader, parseStandardUrl } from '@standardserver/core';
|
|
4
|
+
import { c as createProcedureClient, u as unlazy, P as Procedure } from './server.DofEOwf-.mjs';
|
|
5
|
+
import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.BoiFpNT7.mjs';
|
|
6
|
+
|
|
7
|
+
class CompositeStandardHandlerPlugin {
|
|
8
|
+
name = "~composite";
|
|
9
|
+
plugins;
|
|
10
|
+
constructor(plugins = []) {
|
|
11
|
+
this.plugins = sortPlugins(plugins);
|
|
12
|
+
}
|
|
13
|
+
init(options) {
|
|
14
|
+
for (const plugin of this.plugins) {
|
|
15
|
+
if (plugin.init) {
|
|
16
|
+
options = plugin.init(options);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return options;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class StandardHandler {
|
|
24
|
+
constructor(codec, options) {
|
|
25
|
+
this.codec = codec;
|
|
26
|
+
options = new CompositeStandardHandlerPlugin([
|
|
27
|
+
new OtelHandlerPlugin(),
|
|
28
|
+
...toArray(options.plugins)
|
|
29
|
+
]).init(options);
|
|
30
|
+
this.routingInterceptors = options.routingInterceptors;
|
|
31
|
+
this.interceptors = options.interceptors;
|
|
32
|
+
this.clientInterceptors = options.clientInterceptors;
|
|
33
|
+
}
|
|
34
|
+
routingInterceptors;
|
|
35
|
+
interceptors;
|
|
36
|
+
clientInterceptors;
|
|
37
|
+
async handle(request, { context, prefix }) {
|
|
38
|
+
if (prefix && !matchesHttpPathPrefix(request.url, prefix)) {
|
|
39
|
+
return { matched: false, response: void 0 };
|
|
40
|
+
}
|
|
41
|
+
return intercept(
|
|
42
|
+
this.routingInterceptors,
|
|
43
|
+
{ context, prefix, request },
|
|
44
|
+
async ({ context: context2, prefix: prefix2, request: request2 }) => {
|
|
45
|
+
const span = getOpenTelemetryConfig()?.trace.getActiveSpan();
|
|
46
|
+
let step;
|
|
47
|
+
const matchedOrNot = await runWithSpan("find_procedure", () => this.codec.resolveProcedure(request2, { context: context2, prefix: prefix2 }));
|
|
48
|
+
if (!matchedOrNot) {
|
|
49
|
+
span?.updateName(`${ORPC_NAME}_no_match`);
|
|
50
|
+
span?.setAttribute("http.request.method", request2.method);
|
|
51
|
+
span?.setAttribute("url.path", request2.url);
|
|
52
|
+
return { matched: false };
|
|
53
|
+
}
|
|
54
|
+
const { path, procedure, decodeInput } = matchedOrNot;
|
|
55
|
+
span?.updateName(`${ORPC_NAME}.${path.join("/")}`);
|
|
56
|
+
span?.setAttribute("rpc.system", ORPC_NAME);
|
|
57
|
+
span?.setAttribute("rpc.method", path.join("."));
|
|
58
|
+
try {
|
|
59
|
+
const response = await intercept(
|
|
60
|
+
this.interceptors,
|
|
61
|
+
{ context: context2, prefix: prefix2, request: request2, path, procedure, decodeInput },
|
|
62
|
+
async ({ context: context3, prefix: prefix3, request: request3, path: path2, procedure: procedure2, decodeInput: decodeInput2 }) => {
|
|
63
|
+
step = "decode_input";
|
|
64
|
+
let input = await runWithSpan("decode_input", decodeInput2);
|
|
65
|
+
step = void 0;
|
|
66
|
+
if (isAsyncIteratorObject(input)) {
|
|
67
|
+
input = override(input, traceAsyncIterator("consume_async_iterator_object_input", input));
|
|
68
|
+
}
|
|
69
|
+
const client = createProcedureClient(procedure2, {
|
|
70
|
+
context: context3,
|
|
71
|
+
path: path2,
|
|
72
|
+
interceptors: this.clientInterceptors
|
|
73
|
+
});
|
|
74
|
+
step = "call_procedure";
|
|
75
|
+
const output = await client(input, {
|
|
76
|
+
signal: request3.signal,
|
|
77
|
+
lastEventId: flattenStandardHeader(request3.headers["last-event-id"])
|
|
78
|
+
});
|
|
79
|
+
step = void 0;
|
|
80
|
+
const response2 = await this.codec.encodeOutput(output, procedure2, path2, { context: context3, prefix: prefix3 });
|
|
81
|
+
return response2;
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
return { matched: true, response };
|
|
85
|
+
} catch (e) {
|
|
86
|
+
if (step !== "call_procedure") {
|
|
87
|
+
recordSpanError(span, e);
|
|
88
|
+
}
|
|
89
|
+
const error = step === "decode_input" && !(e instanceof ORPCError) ? new ORPCError("BAD_REQUEST", {
|
|
90
|
+
message: `Malformed request. Ensure the request body is properly formatted and the 'Content-Type' header is set correctly.`,
|
|
91
|
+
cause: e
|
|
92
|
+
}) : toORPCError(e);
|
|
93
|
+
const response = await this.codec.encodeError(error, procedure, path, { context: context2, prefix: prefix2 });
|
|
94
|
+
return { matched: true, response };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
class OtelHandlerPlugin {
|
|
101
|
+
name = "~opentelemetry";
|
|
102
|
+
init(options) {
|
|
103
|
+
return {
|
|
104
|
+
...options,
|
|
105
|
+
routingInterceptors: [
|
|
106
|
+
// Should be placed before user-provided interceptors to help them access the current active context.
|
|
107
|
+
async ({ next, request }) => {
|
|
108
|
+
const otelConfig = getOpenTelemetryConfig();
|
|
109
|
+
let propagationContext;
|
|
110
|
+
if (otelConfig?.propagation) {
|
|
111
|
+
propagationContext = otelConfig.propagation.extract(otelConfig.context.active(), request.headers);
|
|
112
|
+
}
|
|
113
|
+
return runWithSpan(
|
|
114
|
+
{ name: `${request.method} ${request.url}`, context: propagationContext },
|
|
115
|
+
() => next()
|
|
116
|
+
);
|
|
117
|
+
},
|
|
118
|
+
...toArray(options.routingInterceptors)
|
|
119
|
+
]
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class RPCMatcher {
|
|
125
|
+
filter;
|
|
126
|
+
rootRouter;
|
|
127
|
+
tree = /* @__PURE__ */ new Map();
|
|
128
|
+
pendingLazyRouters = [];
|
|
129
|
+
constructor(router, options = {}) {
|
|
130
|
+
this.filter = options.filter ?? true;
|
|
131
|
+
this.rootRouter = router;
|
|
132
|
+
this.index(router);
|
|
133
|
+
}
|
|
134
|
+
index(router, path = []) {
|
|
135
|
+
const lazyResults = walkProcedureContractsSync(router, (procedure, procedurePath) => {
|
|
136
|
+
if (!value(this.filter, procedure, procedurePath)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const httpPath = pathToHttpPath(procedurePath);
|
|
140
|
+
if (procedure instanceof Procedure) {
|
|
141
|
+
this.tree.set(httpPath, {
|
|
142
|
+
path: procedurePath,
|
|
143
|
+
contract: procedure,
|
|
144
|
+
procedure
|
|
145
|
+
});
|
|
146
|
+
} else {
|
|
147
|
+
this.tree.set(httpPath, {
|
|
148
|
+
path: procedurePath,
|
|
149
|
+
contract: procedure
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}, path);
|
|
153
|
+
this.pendingLazyRouters.push(
|
|
154
|
+
...lazyResults.map((result) => ({
|
|
155
|
+
...result,
|
|
156
|
+
httpPathPrefix: pathToHttpPath(result.path)
|
|
157
|
+
}))
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
async match(_method, pathname, prefix) {
|
|
161
|
+
if (pathname.length > 1 && pathname.endsWith("/")) {
|
|
162
|
+
pathname = pathname.slice(0, -1);
|
|
163
|
+
}
|
|
164
|
+
if (prefix) {
|
|
165
|
+
if (!pathname.startsWith(prefix)) {
|
|
166
|
+
return void 0;
|
|
167
|
+
}
|
|
168
|
+
const charAfterPrefix = pathname[prefix.length];
|
|
169
|
+
if (charAfterPrefix === "/") {
|
|
170
|
+
pathname = pathname.slice(prefix.length);
|
|
171
|
+
} else if (charAfterPrefix === void 0) {
|
|
172
|
+
pathname = "/";
|
|
173
|
+
} else if (prefix[prefix.length - 1] === "/") {
|
|
174
|
+
pathname = pathname.slice(prefix.length - 1);
|
|
175
|
+
} else {
|
|
176
|
+
return void 0;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const result = await this.matchPathname(pathname);
|
|
180
|
+
if (!result && pathname.includes("%")) {
|
|
181
|
+
return this.matchPathname(normalizeHttpPath(pathname));
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
async matchPathname(pathname) {
|
|
186
|
+
await this.resolvePendingLazyRouters(pathname);
|
|
187
|
+
const entry = this.tree.get(pathname);
|
|
188
|
+
if (!entry) {
|
|
189
|
+
return void 0;
|
|
190
|
+
}
|
|
191
|
+
const procedure = await this.resolveProcedure(entry);
|
|
192
|
+
return { path: entry.path, procedure };
|
|
193
|
+
}
|
|
194
|
+
async resolvePendingLazyRouters(pathname) {
|
|
195
|
+
if (!this.pendingLazyRouters.length) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const stillPending = [];
|
|
199
|
+
for (const pending of this.pendingLazyRouters) {
|
|
200
|
+
if (pathname.startsWith(pending.httpPathPrefix)) {
|
|
201
|
+
const { default: router } = await unlazy(pending.router);
|
|
202
|
+
this.index(router, pending.path);
|
|
203
|
+
} else {
|
|
204
|
+
stillPending.push(pending);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
this.pendingLazyRouters = stillPending;
|
|
208
|
+
}
|
|
209
|
+
async resolveProcedure(entry) {
|
|
210
|
+
if (entry.procedure) {
|
|
211
|
+
return entry.procedure;
|
|
212
|
+
}
|
|
213
|
+
const { default: maybeProcedure } = await unlazy(getRouter(this.rootRouter, entry.path));
|
|
214
|
+
if (!(maybeProcedure instanceof Procedure)) {
|
|
215
|
+
throw new TypeError(
|
|
216
|
+
`[Contract-First] Missing or invalid implementation for procedure at path: "${entry.path.join(".")}". Ensure the procedure is correctly implemented and matches its contract.`
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
entry.procedure = createContractProcedure(maybeProcedure, entry.contract);
|
|
220
|
+
return entry.procedure;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
class RPCHandlerCodec {
|
|
225
|
+
matcher;
|
|
226
|
+
serializer;
|
|
227
|
+
errorStatusMap;
|
|
228
|
+
outputStatus;
|
|
229
|
+
constructor(router, options = {}) {
|
|
230
|
+
this.matcher = new RPCMatcher(router, options);
|
|
231
|
+
this.serializer = options.serializer ?? new RPCSerializer();
|
|
232
|
+
this.errorStatusMap = options.errorStatusMap ?? COMMON_ERROR_STATUS_MAP;
|
|
233
|
+
this.outputStatus = options.outputStatus;
|
|
234
|
+
}
|
|
235
|
+
async resolveProcedure(request, options) {
|
|
236
|
+
const [pathname, query] = parseStandardUrl(request.url);
|
|
237
|
+
const matched = await this.matcher.match(request.method, pathname, options.prefix);
|
|
238
|
+
if (!matched) {
|
|
239
|
+
return void 0;
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
procedure: matched.procedure,
|
|
243
|
+
path: matched.path,
|
|
244
|
+
decodeInput: async () => {
|
|
245
|
+
if (request.method === "GET") {
|
|
246
|
+
const dataString = new URLSearchParams(query).getAll("data").at(-1);
|
|
247
|
+
return this.serializer.deserialize(parseEmptyableJSON(dataString));
|
|
248
|
+
}
|
|
249
|
+
const body = await request.resolveBody();
|
|
250
|
+
return this.serializer.deserialize(body);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
encodeOutput(output, procedure, path, options) {
|
|
255
|
+
return {
|
|
256
|
+
headers: {},
|
|
257
|
+
status: value(this.outputStatus, output, procedure, path, options) ?? DEFAULT_SUCCESS_STATUS,
|
|
258
|
+
body: this.serializer.serialize(output)
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
encodeError(error, _procedure, _path, _options) {
|
|
262
|
+
const status = this.errorStatusMap[error.code] ?? DEFAULT_ERROR_STATUS;
|
|
263
|
+
return {
|
|
264
|
+
headers: {},
|
|
265
|
+
status,
|
|
266
|
+
body: this.serializer.serialize(error.toJSON())
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export { CompositeStandardHandlerPlugin as C, OtelHandlerPlugin as O, RPCHandlerCodec as R, StandardHandler as S, RPCMatcher as a };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { value } from '@orpc/shared';
|
|
2
|
+
|
|
3
|
+
function createStandardPeerRequestHandler(handler, options) {
|
|
4
|
+
return async (request) => {
|
|
5
|
+
const context = await value(options.context ?? {}, request);
|
|
6
|
+
const { response } = await handler.handle(request, { ...options, context });
|
|
7
|
+
return response ?? { status: 404, headers: {}, body: "No procedure matched" };
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { createStandardPeerRequestHandler as c };
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { ORPCErrorCode, ORPCErrorOptions, ORPCError, AnyORPCError, ClientContext, Client } from '@orpc/client';
|
|
2
|
+
import { ErrorMap, ErrorMapItem, InferSchemaInput, AnyMetaPlugin, AnySchema, ProcedureContractDefinition, Meta, InferSchemaOutput, ORPCErrorFromErrorMap } from '@orpc/contract';
|
|
3
|
+
import { MaybeOptionalOptions, Promisable, Interceptor, PromiseWithError, ThrowableError, Value } from '@orpc/shared';
|
|
4
|
+
|
|
5
|
+
interface Context {
|
|
6
|
+
[key: PropertyKey]: any;
|
|
7
|
+
}
|
|
8
|
+
type MergedInitialContext<TInitial extends Context, TOutContext extends Context, TInContext extends Context> = Exclude<keyof TInContext, keyof TInitial | keyof TOutContext> extends never ? TInitial : TInitial & Omit<TInContext, keyof TInitial | keyof TOutContext>;
|
|
9
|
+
type MergedContext<TCurrent extends Context, TOutContext extends Context> = keyof TOutContext extends never ? TCurrent : Omit<TCurrent, keyof TOutContext> & TOutContext;
|
|
10
|
+
|
|
11
|
+
type ORPCErrorConstructorMapItemOptions<TData> = Omit<ORPCErrorOptions<TData>, 'status'>;
|
|
12
|
+
interface ORPCErrorConstructorMapItem<TCode extends ORPCErrorCode, TInData> {
|
|
13
|
+
(...rest: MaybeOptionalOptions<ORPCErrorConstructorMapItemOptions<TInData>>): ORPCError<TCode, TInData>;
|
|
14
|
+
}
|
|
15
|
+
type ORPCErrorConstructorMap<T extends ErrorMap> = {
|
|
16
|
+
[K in keyof T]: K extends ORPCErrorCode ? T[K] extends ErrorMapItem<infer UInputSchema> ? ORPCErrorConstructorMapItem<K, InferSchemaInput<UInputSchema>> : never : never;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Creates a map of ORPC error constructors.
|
|
20
|
+
*
|
|
21
|
+
* The returned object is a `Proxy` that allows access to arbitrary error codes:
|
|
22
|
+
* - If the code exists in the provided `errorMap`, the corresponding constructor
|
|
23
|
+
* will create a **defined** `ORPCError`.
|
|
24
|
+
* - If the code does not exist, a fallback `ORPCError` constructor is returned.
|
|
25
|
+
*
|
|
26
|
+
* The `in` operator can be used to check whether an error code is explicitly
|
|
27
|
+
* defined in the map.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const errorMap = createORPCErrorConstructorMap({
|
|
32
|
+
* NOT_FOUND: {
|
|
33
|
+
* status: 404,
|
|
34
|
+
* message: 'Not Found',
|
|
35
|
+
* },
|
|
36
|
+
* })
|
|
37
|
+
*
|
|
38
|
+
* if ('NOT_FOUND' in errorMap) {
|
|
39
|
+
* const error = errorMap.NOT_FOUND()
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
declare function createORPCErrorConstructorMap<T extends ErrorMap>(errorMap: T): ORPCErrorConstructorMap<T>;
|
|
44
|
+
|
|
45
|
+
type MiddlewareResult<TOutContext extends Context, TOutput> = Promisable<{
|
|
46
|
+
output: TOutput;
|
|
47
|
+
context: TOutContext;
|
|
48
|
+
}>;
|
|
49
|
+
type MiddlewareNextOptions<TOutContext extends Context> = object extends TOutContext ? {
|
|
50
|
+
context?: TOutContext;
|
|
51
|
+
} : {
|
|
52
|
+
context: TOutContext;
|
|
53
|
+
};
|
|
54
|
+
interface MiddlewareNext<TOutput> {
|
|
55
|
+
<T extends Context = object>(...rest: MaybeOptionalOptions<MiddlewareNextOptions<T>>): MiddlewareResult<T, TOutput>;
|
|
56
|
+
}
|
|
57
|
+
type MiddlewareDoneOptions<TOutContext, TOutput> = (object extends TOutContext ? {
|
|
58
|
+
context?: TOutContext;
|
|
59
|
+
} : {
|
|
60
|
+
context: TOutContext;
|
|
61
|
+
}) & {
|
|
62
|
+
output: TOutput;
|
|
63
|
+
};
|
|
64
|
+
interface MiddlewareDone<TOutput> {
|
|
65
|
+
/**
|
|
66
|
+
* Create a successful result and terminate the middleware chain early.
|
|
67
|
+
*/
|
|
68
|
+
<TOutContext extends Context = object>(...rest: MaybeOptionalOptions<MiddlewareDoneOptions<TOutContext, TOutput>>): MiddlewareResult<TOutContext, TOutput>;
|
|
69
|
+
}
|
|
70
|
+
interface MiddlewareOptions<TInContext extends Context, TOutput, TErrorConstructorMap extends ORPCErrorConstructorMap<any>> {
|
|
71
|
+
context: TInContext;
|
|
72
|
+
path: string[];
|
|
73
|
+
procedure: AnyProcedure;
|
|
74
|
+
signal?: AbortSignal | undefined;
|
|
75
|
+
lastEventId: string | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Invoke to continue the middleware chain.
|
|
78
|
+
*/
|
|
79
|
+
next: MiddlewareNext<TOutput>;
|
|
80
|
+
errors: TErrorConstructorMap;
|
|
81
|
+
}
|
|
82
|
+
interface MiddlewareDefinition<TErrorMap extends ErrorMap> {
|
|
83
|
+
errorMap?: TErrorMap | undefined;
|
|
84
|
+
metaPlugins?: AnyMetaPlugin[] | undefined;
|
|
85
|
+
}
|
|
86
|
+
interface Middleware<TInContext extends Context, TOutContext extends Context, TInput, TOutput, TErrorMap extends ErrorMap> {
|
|
87
|
+
/** this property should be optional to support inline middleware */
|
|
88
|
+
'~orpc'?: MiddlewareDefinition<TErrorMap> | undefined;
|
|
89
|
+
(opts: MiddlewareOptions<TInContext, TOutput, ORPCErrorConstructorMap<TErrorMap>>, input: TInput, done: MiddlewareDone<TOutput>): Promisable<MiddlewareResult<TOutContext, TOutput>>;
|
|
90
|
+
}
|
|
91
|
+
type AnyMiddleware = Middleware<any, any, any, any, any>;
|
|
92
|
+
|
|
93
|
+
interface ProcedureHandlerOptions<TCurrentContext extends Context, TInput, TErrorConstructorMap extends ORPCErrorConstructorMap<any>> {
|
|
94
|
+
context: TCurrentContext;
|
|
95
|
+
input: TInput;
|
|
96
|
+
path: string[];
|
|
97
|
+
procedure: Procedure<Context, Context, AnySchema, AnySchema, ErrorMap, any>;
|
|
98
|
+
signal?: AbortSignal | undefined;
|
|
99
|
+
lastEventId?: string | undefined;
|
|
100
|
+
errors: TErrorConstructorMap;
|
|
101
|
+
}
|
|
102
|
+
interface ProcedureHandler<TCurrentContext extends Context, TInput, THandlerOutput, TErrorConstructorMap extends ORPCErrorConstructorMap<any>> {
|
|
103
|
+
(opts: ProcedureHandlerOptions<TCurrentContext, TInput, TErrorConstructorMap>, input: TInput): Promisable<THandlerOutput>;
|
|
104
|
+
}
|
|
105
|
+
interface OrderedMiddleware {
|
|
106
|
+
/**
|
|
107
|
+
* Snapshot of `inputSchemas.length`
|
|
108
|
+
* at the time this middleware was used.
|
|
109
|
+
*
|
|
110
|
+
* @default 0
|
|
111
|
+
*/
|
|
112
|
+
inputSchemasLengthAtUse?: number | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Snapshot of `outputSchemas.length`
|
|
115
|
+
* at the time this middleware was used.
|
|
116
|
+
*
|
|
117
|
+
* @default 0
|
|
118
|
+
*/
|
|
119
|
+
outputSchemasLengthAtUse?: number | undefined;
|
|
120
|
+
middleware: AnyMiddleware;
|
|
121
|
+
}
|
|
122
|
+
interface ProcedureConfig {
|
|
123
|
+
/**
|
|
124
|
+
* When enabled, input schemas are not validated at runtime.
|
|
125
|
+
* Schemas are still used for type inference and OpenAPI generation.
|
|
126
|
+
*
|
|
127
|
+
* @warning Do not disable validation for schemas that transform values.
|
|
128
|
+
*
|
|
129
|
+
* @default false
|
|
130
|
+
*/
|
|
131
|
+
disableInputValidation?: boolean | undefined;
|
|
132
|
+
/**
|
|
133
|
+
* When enabled, output schemas are not validated at runtime.
|
|
134
|
+
* Schemas are still used for type inference and OpenAPI generation.
|
|
135
|
+
*
|
|
136
|
+
* Useful when output schemas exist only for specification generation.
|
|
137
|
+
*
|
|
138
|
+
* @warning Do not disable validation for schemas that transform values.
|
|
139
|
+
*
|
|
140
|
+
* @default false
|
|
141
|
+
*/
|
|
142
|
+
disableOutputValidation?: boolean | undefined;
|
|
143
|
+
}
|
|
144
|
+
interface ProcedureDefinition<TInitialContext extends Context, TInjectedContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError> extends ProcedureContractDefinition<TInputSchema, TOutputSchema, TErrorMap>, ProcedureConfig {
|
|
145
|
+
__TInitialContext?: (type: TInitialContext) => unknown;
|
|
146
|
+
__TInjectedContext?: (type: TInjectedContext) => unknown;
|
|
147
|
+
__TReturnedError?: () => TReturnedError;
|
|
148
|
+
/**
|
|
149
|
+
* When enabled, errors returned (not thrown) by the handler are passed through as-is,
|
|
150
|
+
* rather than being transformed into inferrable errors.
|
|
151
|
+
*
|
|
152
|
+
* This is intended for the contract-first approach, where the procedure adheres to an
|
|
153
|
+
* external contract and returned errors should not affect the inferred contract types.
|
|
154
|
+
*
|
|
155
|
+
* @default false
|
|
156
|
+
*/
|
|
157
|
+
opaqueReturnedErrors?: boolean | undefined;
|
|
158
|
+
orderedMiddlewares: OrderedMiddleware[];
|
|
159
|
+
handler: ProcedureHandler<any, any, any, any>;
|
|
160
|
+
}
|
|
161
|
+
declare class Procedure<TInitialContext extends Context, TInjectedContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError> {
|
|
162
|
+
'~orpc': ProcedureDefinition<TInitialContext, TInjectedContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>;
|
|
163
|
+
constructor(def: ProcedureDefinition<TInitialContext, TInjectedContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>);
|
|
164
|
+
/**
|
|
165
|
+
* Checks if the given instance satisfies the {@see Procedure} class/interface.
|
|
166
|
+
*/
|
|
167
|
+
static [Symbol.hasInstance](instance: unknown): boolean;
|
|
168
|
+
}
|
|
169
|
+
type AnyProcedure = Procedure<any, any, any, any, any, any>;
|
|
170
|
+
|
|
171
|
+
interface LazyDefinition<T> {
|
|
172
|
+
meta: Meta;
|
|
173
|
+
metaPlugins?: AnyMetaPlugin[] | undefined;
|
|
174
|
+
loader: () => Promise<{
|
|
175
|
+
default: T;
|
|
176
|
+
}>;
|
|
177
|
+
}
|
|
178
|
+
declare class Lazy<T> {
|
|
179
|
+
'~orpc': LazyDefinition<T>;
|
|
180
|
+
constructor(def: LazyDefinition<T>);
|
|
181
|
+
/**
|
|
182
|
+
* Checks if the given instance satisfies the {@see Lazy} class/interface.
|
|
183
|
+
*/
|
|
184
|
+
static [Symbol.hasInstance](instance: unknown): boolean;
|
|
185
|
+
}
|
|
186
|
+
type Lazyable<T> = T | Lazy<T>;
|
|
187
|
+
declare function unlazy<T extends Lazyable<any>>(maybeLazy: T): Promise<{
|
|
188
|
+
default: T extends Lazy<infer U> ? U : T;
|
|
189
|
+
}>;
|
|
190
|
+
|
|
191
|
+
type ProcedureClient<TClientContext extends ClientContext, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedORPCError extends AnyORPCError> = Client<TClientContext, InferSchemaInput<TInputSchema>, InferSchemaOutput<TOutputSchema>, ORPCErrorFromErrorMap<TErrorMap> | TReturnedORPCError | ThrowableError>;
|
|
192
|
+
interface ProcedureClientInterceptorOptions<TInitialContext extends Context, TErrorMap extends ErrorMap> extends ProcedureHandlerOptions<TInitialContext, unknown, ORPCErrorConstructorMap<TErrorMap>> {
|
|
193
|
+
}
|
|
194
|
+
type ProcedureClientInterceptor<TInitialContext extends Context, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError> = Interceptor<ProcedureClientInterceptorOptions<TInitialContext, TErrorMap>, PromiseWithError<InferSchemaOutput<TOutputSchema>, ORPCErrorFromErrorMap<TErrorMap> | TReturnedError | ThrowableError>>;
|
|
195
|
+
type ProcedureClientOptions<TInitialContext extends Context, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError, TClientContext extends ClientContext> = {
|
|
196
|
+
path?: string[];
|
|
197
|
+
interceptors?: ProcedureClientInterceptor<TInitialContext, TOutputSchema, TErrorMap, TReturnedError>[];
|
|
198
|
+
} & (object extends TInitialContext ? {
|
|
199
|
+
context?: Value<Promisable<TInitialContext>, [clientContext: TClientContext]>;
|
|
200
|
+
} : {
|
|
201
|
+
context: Value<Promisable<TInitialContext>, [clientContext: TClientContext]>;
|
|
202
|
+
});
|
|
203
|
+
declare function createProcedureClient<TInitialContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError, TClientContext extends ClientContext = object>(lazyableProcedure: Lazyable<Procedure<TInitialContext, any, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>>, ...rest: MaybeOptionalOptions<ProcedureClientOptions<TInitialContext, TOutputSchema, TErrorMap, TReturnedError, TClientContext>>): ProcedureClient<TClientContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>;
|
|
204
|
+
|
|
205
|
+
export { Procedure as a, Lazy as h, createORPCErrorConstructorMap as x, createProcedureClient as y, unlazy as z };
|
|
206
|
+
export type { AnyProcedure as A, Context as C, Lazyable as L, MergedContext as M, ORPCErrorConstructorMap as O, ProcedureClientOptions as P, ProcedureClient as b, ProcedureClientInterceptor as c, Middleware as d, MergedInitialContext as e, ProcedureConfig as f, AnyMiddleware as g, ProcedureHandler as i, OrderedMiddleware as j, LazyDefinition as k, MiddlewareDefinition as l, MiddlewareDone as m, MiddlewareDoneOptions as n, MiddlewareNext as o, MiddlewareNextOptions as p, MiddlewareOptions as q, MiddlewareResult as r, ORPCErrorConstructorMapItem as s, ORPCErrorConstructorMapItemOptions as t, ProcedureClientInterceptorOptions as u, ProcedureDefinition as v, ProcedureHandlerOptions as w };
|