@orpc/server 1.14.6 → 2.0.0-beta.10
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 +78 -137
- package/dist/adapters/crossws/index.d.mts +42 -21
- package/dist/adapters/crossws/index.d.ts +42 -21
- package/dist/adapters/crossws/index.mjs +37 -18
- package/dist/adapters/fetch/index.d.mts +83 -67
- package/dist/adapters/fetch/index.d.ts +83 -67
- package/dist/adapters/fetch/index.mjs +131 -106
- package/dist/adapters/message-port/index.d.mts +51 -34
- package/dist/adapters/message-port/index.d.ts +51 -34
- package/dist/adapters/message-port/index.mjs +73 -38
- package/dist/adapters/node/index.d.mts +82 -60
- package/dist/adapters/node/index.d.ts +82 -60
- package/dist/adapters/node/index.mjs +127 -98
- 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 +50 -36
- package/dist/adapters/websocket/index.d.ts +50 -36
- package/dist/adapters/websocket/index.mjs +55 -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 +2 -2
- package/dist/helpers/index.d.ts +2 -2
- package/dist/helpers/index.mjs +1 -1
- package/dist/index.d.mts +163 -770
- package/dist/index.d.ts +163 -770
- package/dist/index.mjs +296 -403
- package/dist/plugins/index.d.mts +120 -127
- package/dist/plugins/index.d.ts +120 -127
- package/dist/plugins/index.mjs +252 -223
- package/dist/shared/server.BL22TloH.d.mts +184 -0
- package/dist/shared/server.BL22TloH.d.ts +184 -0
- package/dist/shared/server.BsNNjG5J.d.mts +61 -0
- package/dist/shared/server.BwHnWUuN.mjs +222 -0
- package/dist/shared/server.CX4vUnDk.mjs +11 -0
- package/dist/shared/server.Cj5lgPuG.d.mts +66 -0
- package/dist/shared/server.CjOb6ItT.mjs +41 -0
- package/dist/shared/server.CrlKQucM.mjs +233 -0
- package/dist/shared/server.DBANIheG.d.ts +104 -0
- package/dist/shared/server.DJIkub_t.d.mts +104 -0
- package/dist/shared/server.D_QauotT.mjs +30 -0
- package/dist/shared/server.GDpX6Df8.mjs +271 -0
- package/dist/shared/server.Pa0F03f_.d.ts +61 -0
- package/dist/shared/{server.DZ5BIITo.mjs → server.W91HSRkE.mjs} +2 -2
- package/dist/shared/server.d_2NS3g5.d.ts +66 -0
- package/package.json +26 -55
- 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 -37
- 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,66 @@
|
|
|
1
|
+
import { RPCSerializer, AnyORPCError } from '@orpc/client';
|
|
2
|
+
import { Value, Promisable } from '@orpc/shared';
|
|
3
|
+
import { StandardMethod, StandardLazyRequest, StandardResponse } from '@standardserver/core';
|
|
4
|
+
import { A as AnyProcedure, C as Context } from './server.BL22TloH.mjs';
|
|
5
|
+
import { A as AnyRouter } from './server.BsNNjG5J.mjs';
|
|
6
|
+
import { AnyProcedureContract } from '@orpc/contract';
|
|
7
|
+
import { b as StandardHandlerHandleOptions, c as StandardHandlerCodec, d as StandardHandlerCodecResolvedProcedure } from './server.DJIkub_t.mjs';
|
|
8
|
+
|
|
9
|
+
interface RPCMatcherOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Filter which procedures are exposed for matching. Return `false` to exclude.
|
|
12
|
+
*
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
filter?: Value<boolean, [procedure: AnyProcedureContract | AnyProcedure, path: string[]]>;
|
|
16
|
+
}
|
|
17
|
+
declare class RPCMatcher {
|
|
18
|
+
private readonly filter;
|
|
19
|
+
private readonly rootRouter;
|
|
20
|
+
private readonly tree;
|
|
21
|
+
private pendingLazyRouters;
|
|
22
|
+
constructor(router: AnyRouter, options?: RPCMatcherOptions);
|
|
23
|
+
private index;
|
|
24
|
+
match(_method: StandardMethod, pathname: `/${string}`, prefix: `/${string}` | undefined): Promise<{
|
|
25
|
+
path: string[];
|
|
26
|
+
procedure: AnyProcedure;
|
|
27
|
+
} | undefined>;
|
|
28
|
+
private matchPathname;
|
|
29
|
+
private resolvePendingLazyRouters;
|
|
30
|
+
private resolveProcedure;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface RPCHandlerCodecOptions<T extends Context> extends RPCMatcherOptions {
|
|
34
|
+
/**
|
|
35
|
+
* Override the default RPC serializer.
|
|
36
|
+
*/
|
|
37
|
+
serializer?: Pick<RPCSerializer, keyof RPCSerializer>;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve HTTP status for encoded successful outputs.
|
|
40
|
+
*
|
|
41
|
+
* Value should be in range `200-299`
|
|
42
|
+
* Return `undefined` or `null` to fallback to default
|
|
43
|
+
*
|
|
44
|
+
* @default DEFAULT_ERROR_STATUS, DEFAULT_ERROR_STATUS
|
|
45
|
+
*/
|
|
46
|
+
outputStatus?: Value<number | undefined | null, [output: unknown, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>]>;
|
|
47
|
+
/**
|
|
48
|
+
* Mapping ORPCError Code -> HTTP Status Code
|
|
49
|
+
*
|
|
50
|
+
* @default COMMON_ERROR_STATUS_MAP
|
|
51
|
+
*/
|
|
52
|
+
errorStatusMap?: Record<string, number> | undefined;
|
|
53
|
+
}
|
|
54
|
+
declare class RPCHandlerCodec<T extends Context> implements StandardHandlerCodec<T> {
|
|
55
|
+
private readonly matcher;
|
|
56
|
+
private readonly serializer;
|
|
57
|
+
private readonly errorStatusMap;
|
|
58
|
+
private readonly outputStatus;
|
|
59
|
+
constructor(router: AnyRouter, options?: RPCHandlerCodecOptions<T>);
|
|
60
|
+
resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promise<StandardHandlerCodecResolvedProcedure | undefined>;
|
|
61
|
+
encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
62
|
+
encodeError(error: AnyORPCError, _procedure: AnyProcedure, _path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { RPCHandlerCodec as a, RPCMatcher as b };
|
|
66
|
+
export type { RPCHandlerCodecOptions as R, RPCMatcherOptions as c };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { resolveMetaPlugins, mergeErrorMap, getHiddenMetaPlugins } from '@orpc/contract';
|
|
2
|
+
import { P as Procedure } from './server.CrlKQucM.mjs';
|
|
3
|
+
|
|
4
|
+
class DecoratedProcedure extends Procedure {
|
|
5
|
+
meta(...plugins) {
|
|
6
|
+
const [meta, metaPlugins] = resolveMetaPlugins(this["~orpc"].meta, this["~orpc"].metaPlugins, plugins);
|
|
7
|
+
return new DecoratedProcedure({
|
|
8
|
+
...this["~orpc"],
|
|
9
|
+
meta,
|
|
10
|
+
metaPlugins
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
errors(errors) {
|
|
14
|
+
let procedure = new DecoratedProcedure({
|
|
15
|
+
...this["~orpc"],
|
|
16
|
+
errorMap: mergeErrorMap(this["~orpc"].errorMap, errors)
|
|
17
|
+
});
|
|
18
|
+
const plugins = getHiddenMetaPlugins(errors);
|
|
19
|
+
if (plugins) {
|
|
20
|
+
procedure = procedure.meta(...plugins);
|
|
21
|
+
}
|
|
22
|
+
return procedure;
|
|
23
|
+
}
|
|
24
|
+
use(middleware) {
|
|
25
|
+
let procedure = new DecoratedProcedure({
|
|
26
|
+
...this["~orpc"],
|
|
27
|
+
errorMap: mergeErrorMap(middleware["~orpc"]?.errorMap, this["~orpc"].errorMap),
|
|
28
|
+
orderedMiddlewares: [...this["~orpc"].orderedMiddlewares, {
|
|
29
|
+
middleware,
|
|
30
|
+
inputSchemasLengthAtUse: this["~orpc"].inputSchemas?.length,
|
|
31
|
+
outputSchemasLengthAtUse: this["~orpc"].outputSchemas?.length
|
|
32
|
+
}]
|
|
33
|
+
});
|
|
34
|
+
if (middleware["~orpc"]?.metaPlugins) {
|
|
35
|
+
procedure = procedure.meta(...middleware["~orpc"]?.metaPlugins);
|
|
36
|
+
}
|
|
37
|
+
return procedure;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { DecoratedProcedure as D };
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { ORPCError, wrapEventIteratorPreservingMeta, cloneORPCError } from '@orpc/client';
|
|
2
|
+
import { reconcileORPCError, ValidationError, ProcedureContract } from '@orpc/contract';
|
|
3
|
+
import { getOrBind, resolveMaybeOptionalOptions, getConstructor, isTypescriptObject, toArray, value, runWithSpan, intercept, isAsyncIteratorObject, override, traceAsyncIterator, traceReadableStream } from '@orpc/shared';
|
|
4
|
+
|
|
5
|
+
function createORPCErrorConstructorMap(errorMap) {
|
|
6
|
+
const proxy = new Proxy(errorMap, {
|
|
7
|
+
get(target, code) {
|
|
8
|
+
if (typeof code !== "string") {
|
|
9
|
+
return getOrBind(target, code);
|
|
10
|
+
}
|
|
11
|
+
const item = (...rest) => {
|
|
12
|
+
const options = resolveMaybeOptionalOptions(rest);
|
|
13
|
+
const config = errorMap[code];
|
|
14
|
+
const error = new ORPCError(code, {
|
|
15
|
+
message: options.message ?? config?.message,
|
|
16
|
+
data: options.data,
|
|
17
|
+
cause: options.cause
|
|
18
|
+
});
|
|
19
|
+
if (config) {
|
|
20
|
+
error.defined = true;
|
|
21
|
+
error.inferable = true;
|
|
22
|
+
}
|
|
23
|
+
return error;
|
|
24
|
+
};
|
|
25
|
+
return item;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return proxy;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class Lazy {
|
|
32
|
+
"~orpc";
|
|
33
|
+
constructor(def) {
|
|
34
|
+
this["~orpc"] = def;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Checks if the given instance satisfies the {@see Lazy} class/interface.
|
|
38
|
+
*/
|
|
39
|
+
static [Symbol.hasInstance](instance) {
|
|
40
|
+
if (this !== Lazy) {
|
|
41
|
+
return Function.prototype[Symbol.hasInstance].call(this, instance);
|
|
42
|
+
}
|
|
43
|
+
const constructor = getConstructor(instance);
|
|
44
|
+
if (constructor === Lazy) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return isTypescriptObject(instance) && isTypescriptObject(instance["~orpc"]) && isTypescriptObject(instance["~orpc"].meta) && (instance["~orpc"].metaPlugins === void 0 || Array.isArray(instance["~orpc"].metaPlugins)) && typeof instance["~orpc"].loader === "function";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function unlazy(maybeLazy) {
|
|
51
|
+
return maybeLazy instanceof Lazy ? maybeLazy["~orpc"].loader() : Promise.resolve({ default: maybeLazy });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function createProcedureClient(lazyableProcedure, ...rest) {
|
|
55
|
+
const options = resolveMaybeOptionalOptions(rest);
|
|
56
|
+
return async (...[input, callerOptions]) => {
|
|
57
|
+
const path = toArray(options.path);
|
|
58
|
+
const { default: procedure } = await unlazy(lazyableProcedure);
|
|
59
|
+
const clientContext = callerOptions?.context ?? {};
|
|
60
|
+
const context = await value(options.context, clientContext) ?? {};
|
|
61
|
+
const errors = createORPCErrorConstructorMap(procedure["~orpc"].errorMap);
|
|
62
|
+
const reconcileError = async (e) => {
|
|
63
|
+
if (e instanceof ORPCError) {
|
|
64
|
+
return await reconcileORPCError(procedure["~orpc"].errorMap, e);
|
|
65
|
+
}
|
|
66
|
+
return e;
|
|
67
|
+
};
|
|
68
|
+
try {
|
|
69
|
+
const output = await runWithSpan("call_procedure", (span) => {
|
|
70
|
+
span?.setAttribute("procedure.path", path);
|
|
71
|
+
return intercept(
|
|
72
|
+
options.interceptors,
|
|
73
|
+
{
|
|
74
|
+
context,
|
|
75
|
+
// input can be optional if it is undefinable
|
|
76
|
+
input,
|
|
77
|
+
errors,
|
|
78
|
+
path,
|
|
79
|
+
procedure,
|
|
80
|
+
signal: callerOptions?.signal,
|
|
81
|
+
lastEventId: callerOptions?.lastEventId
|
|
82
|
+
},
|
|
83
|
+
(interceptorOptions) => executeProcedureInternal(interceptorOptions.procedure, interceptorOptions)
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
if (isAsyncIteratorObject(output)) {
|
|
87
|
+
return override(output, wrapEventIteratorPreservingMeta(
|
|
88
|
+
traceAsyncIterator("consume_event_iterator_output", output),
|
|
89
|
+
{ mapError: reconcileError }
|
|
90
|
+
));
|
|
91
|
+
}
|
|
92
|
+
if (output instanceof ReadableStream) {
|
|
93
|
+
return override(output, traceReadableStream("consume_octet_stream_output", output));
|
|
94
|
+
}
|
|
95
|
+
return output;
|
|
96
|
+
} catch (e) {
|
|
97
|
+
throw await reconcileError(e);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async function validateInput(i, schema, input) {
|
|
102
|
+
return runWithSpan(`validate_input.${i}`, async (span) => {
|
|
103
|
+
span?.setAttribute("input_schema.index", i);
|
|
104
|
+
const result = await schema["~standard"].validate(input);
|
|
105
|
+
if (result.issues) {
|
|
106
|
+
throw new ORPCError("BAD_REQUEST", {
|
|
107
|
+
message: "Input validation failed",
|
|
108
|
+
data: {
|
|
109
|
+
issues: result.issues
|
|
110
|
+
},
|
|
111
|
+
cause: new ValidationError({
|
|
112
|
+
message: "Input validation failed",
|
|
113
|
+
issues: result.issues,
|
|
114
|
+
invalidData: input
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return result.value;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async function validateOutput(i, schema, output) {
|
|
122
|
+
return runWithSpan(`validate_output.${i}`, async (span) => {
|
|
123
|
+
span?.setAttribute("output_schema.index", i);
|
|
124
|
+
const result = await schema["~standard"].validate(output);
|
|
125
|
+
if (result.issues) {
|
|
126
|
+
throw new ORPCError("INTERNAL_SERVER_ERROR", {
|
|
127
|
+
message: "Output validation failed",
|
|
128
|
+
cause: new ValidationError({
|
|
129
|
+
message: "Output validation failed",
|
|
130
|
+
issues: result.issues,
|
|
131
|
+
invalidData: output
|
|
132
|
+
})
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return result.value;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const middlewareDone = (...rest) => {
|
|
139
|
+
const options = resolveMaybeOptionalOptions(rest);
|
|
140
|
+
return {
|
|
141
|
+
output: options.output,
|
|
142
|
+
// context can be undefined when all field is optional
|
|
143
|
+
context: options.context ?? {}
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
async function executeProcedureInternal(procedure, options) {
|
|
147
|
+
const inputSchemas = toArray(procedure["~orpc"].inputSchemas);
|
|
148
|
+
const outputSchemas = toArray(procedure["~orpc"].outputSchemas);
|
|
149
|
+
const orderedMiddlewares = procedure["~orpc"].orderedMiddlewares;
|
|
150
|
+
const next = async (midIndex, context, input) => {
|
|
151
|
+
let currentInput = input;
|
|
152
|
+
const startInputIndex = midIndex === 0 ? 0 : orderedMiddlewares[midIndex - 1].inputSchemasLengthAtUse ?? 0;
|
|
153
|
+
const endInputIndex = midIndex === orderedMiddlewares.length ? inputSchemas.length : orderedMiddlewares[midIndex].inputSchemasLengthAtUse ?? 0;
|
|
154
|
+
for (let i = startInputIndex; i < endInputIndex; i++) {
|
|
155
|
+
currentInput = await validateInput(i, inputSchemas[i], currentInput);
|
|
156
|
+
}
|
|
157
|
+
let currentOutput;
|
|
158
|
+
let currentContext = context;
|
|
159
|
+
if (midIndex < orderedMiddlewares.length) {
|
|
160
|
+
const { middleware } = orderedMiddlewares[midIndex];
|
|
161
|
+
const result = await runWithSpan(`middleware.${middleware.name}`, async (span) => {
|
|
162
|
+
span?.setAttribute("middleware.index", midIndex);
|
|
163
|
+
return await middleware(
|
|
164
|
+
{
|
|
165
|
+
...options,
|
|
166
|
+
context,
|
|
167
|
+
next: (...rest) => {
|
|
168
|
+
const nextOptions = resolveMaybeOptionalOptions(rest);
|
|
169
|
+
const nextContext = nextOptions.context ?? {};
|
|
170
|
+
return next(
|
|
171
|
+
midIndex + 1,
|
|
172
|
+
{ ...context, ...nextContext },
|
|
173
|
+
currentInput
|
|
174
|
+
);
|
|
175
|
+
},
|
|
176
|
+
lastEventId: options.lastEventId
|
|
177
|
+
},
|
|
178
|
+
currentInput,
|
|
179
|
+
middlewareDone
|
|
180
|
+
);
|
|
181
|
+
});
|
|
182
|
+
currentOutput = result.output;
|
|
183
|
+
currentContext = { ...context, ...result.context };
|
|
184
|
+
} else {
|
|
185
|
+
currentOutput = await runWithSpan(
|
|
186
|
+
"handler",
|
|
187
|
+
() => procedure["~orpc"].handler({ ...options, context, input: currentInput }, currentInput)
|
|
188
|
+
);
|
|
189
|
+
if (currentOutput instanceof ORPCError) {
|
|
190
|
+
if (procedure["~orpc"].opaqueReturnedErrors) {
|
|
191
|
+
throw currentOutput;
|
|
192
|
+
}
|
|
193
|
+
if (currentOutput.inferable && !currentOutput.defined) {
|
|
194
|
+
throw currentOutput;
|
|
195
|
+
}
|
|
196
|
+
const error = cloneORPCError(currentOutput);
|
|
197
|
+
error.defined = false;
|
|
198
|
+
error.inferable = true;
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const startOutputIndex = midIndex === 0 ? 0 : orderedMiddlewares[midIndex - 1].outputSchemasLengthAtUse ?? 0;
|
|
203
|
+
const endOutputIndex = midIndex === orderedMiddlewares.length ? outputSchemas.length : orderedMiddlewares[midIndex].outputSchemasLengthAtUse ?? 0;
|
|
204
|
+
for (let i = endOutputIndex - 1; i >= startOutputIndex; i--) {
|
|
205
|
+
currentOutput = await validateOutput(i, outputSchemas[i], currentOutput);
|
|
206
|
+
}
|
|
207
|
+
return { output: currentOutput, context: currentContext };
|
|
208
|
+
};
|
|
209
|
+
const { output } = await next(0, options.context, options.input);
|
|
210
|
+
return output;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
class Procedure {
|
|
214
|
+
"~orpc";
|
|
215
|
+
constructor(def) {
|
|
216
|
+
this["~orpc"] = def;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Checks if the given instance satisfies the {@see Procedure} class/interface.
|
|
220
|
+
*/
|
|
221
|
+
static [Symbol.hasInstance](instance) {
|
|
222
|
+
if (this !== Procedure) {
|
|
223
|
+
return Function.prototype[Symbol.hasInstance].call(this, instance);
|
|
224
|
+
}
|
|
225
|
+
const constructor = getConstructor(instance);
|
|
226
|
+
if (constructor === Procedure) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
return instance instanceof ProcedureContract && Array.isArray(instance["~orpc"].orderedMiddlewares) && typeof instance["~orpc"].handler === "function";
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export { Lazy as L, Procedure as P, createORPCErrorConstructorMap as a, createProcedureClient as c, unlazy as u };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { AnyORPCError } from '@orpc/client';
|
|
2
|
+
import { OrderablePlugin, Interceptor, Promisable } from '@orpc/shared';
|
|
3
|
+
import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
|
|
4
|
+
import { C as Context, c as ProcedureClientInterceptor, A as AnyProcedure } from './server.BL22TloH.js';
|
|
5
|
+
import { Schema, ErrorMap } from '@orpc/contract';
|
|
6
|
+
|
|
7
|
+
interface StandardHandlerPlugin<T extends Context> extends OrderablePlugin {
|
|
8
|
+
/**
|
|
9
|
+
* Initializes the plugin and returns new handler options.
|
|
10
|
+
* Called once per plugin instance during composition.
|
|
11
|
+
*
|
|
12
|
+
* This method allows plugins to wrap, extend, or transform handler options
|
|
13
|
+
* such as interceptors, or configuration.
|
|
14
|
+
*
|
|
15
|
+
* @param options - The current handler options from previous plugins or base configuration
|
|
16
|
+
* @returns Transformed handler options with plugin's modifications applied
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* init(options) {
|
|
21
|
+
* return {
|
|
22
|
+
* ...options,
|
|
23
|
+
* interceptors: [...(options.interceptors || []), myInterceptor]
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
init?(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
29
|
+
}
|
|
30
|
+
declare class CompositeStandardHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
31
|
+
readonly name = "~composite";
|
|
32
|
+
protected readonly plugins: StandardHandlerPlugin<T>[];
|
|
33
|
+
constructor(plugins?: StandardHandlerPlugin<T>[]);
|
|
34
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface StandardHandlerHandleOptions<T extends Context> {
|
|
38
|
+
prefix?: `/${string}` | undefined;
|
|
39
|
+
context: T;
|
|
40
|
+
}
|
|
41
|
+
type StandardHandlerHandleResult = {
|
|
42
|
+
matched: true;
|
|
43
|
+
response: StandardResponse;
|
|
44
|
+
} | {
|
|
45
|
+
matched: false;
|
|
46
|
+
response?: undefined;
|
|
47
|
+
};
|
|
48
|
+
interface StandardHandlerInterceptorOptions<T extends Context> extends StandardHandlerCodecResolvedProcedure, StandardHandlerHandleOptions<T> {
|
|
49
|
+
request: StandardLazyRequest;
|
|
50
|
+
}
|
|
51
|
+
type StandardHandlerInterceptor<T extends Context> = Interceptor<StandardHandlerInterceptorOptions<T>, Promise<StandardResponse>>;
|
|
52
|
+
interface StandardHandlerRoutingInterceptorOptions<T extends Context> extends StandardHandlerHandleOptions<T> {
|
|
53
|
+
request: StandardLazyRequest;
|
|
54
|
+
}
|
|
55
|
+
type StandardHandlerRoutingInterceptor<T extends Context> = Interceptor<StandardHandlerRoutingInterceptorOptions<T>, Promise<StandardHandlerHandleResult>>;
|
|
56
|
+
interface StandardHandlerOptions<TContext extends Context> {
|
|
57
|
+
/**
|
|
58
|
+
* Fired on every request before routing, useful when you want
|
|
59
|
+
* to intercept all requests regardless of whether they match a procedure or not.
|
|
60
|
+
*
|
|
61
|
+
* @examples
|
|
62
|
+
* - batch plugins - separate one request into multiple and call multiple next
|
|
63
|
+
* - openapi spec plugin - to intercept a request and early response
|
|
64
|
+
*/
|
|
65
|
+
routingInterceptors?: StandardHandlerRoutingInterceptor<TContext>[];
|
|
66
|
+
/**
|
|
67
|
+
* interceptor run after routing and before error handler,
|
|
68
|
+
* useful for error handling, logging, metrics, etc.
|
|
69
|
+
*/
|
|
70
|
+
interceptors?: StandardHandlerInterceptor<TContext>[];
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* ClientInterceptor equivalent with createRouterClient.interceptors / createProcedure.interceptors
|
|
74
|
+
* useful for error handling, logging, metrics, etc. (not counting encoding/decoding)
|
|
75
|
+
*/
|
|
76
|
+
clientInterceptors?: ProcedureClientInterceptor<TContext, Schema<unknown>, ErrorMap, any>[];
|
|
77
|
+
plugins?: StandardHandlerPlugin<TContext>[];
|
|
78
|
+
}
|
|
79
|
+
declare class StandardHandler<T extends Context> {
|
|
80
|
+
private readonly codec;
|
|
81
|
+
private readonly routingInterceptors;
|
|
82
|
+
private readonly interceptors;
|
|
83
|
+
private readonly clientInterceptors;
|
|
84
|
+
constructor(codec: StandardHandlerCodec<T>, options: StandardHandlerOptions<T>);
|
|
85
|
+
handle(request: StandardLazyRequest, { context, prefix }: StandardHandlerHandleOptions<T>): Promise<StandardHandlerHandleResult>;
|
|
86
|
+
}
|
|
87
|
+
declare class OtelHandlerPlugin implements StandardHandlerPlugin<any> {
|
|
88
|
+
name: string;
|
|
89
|
+
init(options: StandardHandlerOptions<any>): StandardHandlerOptions<any>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface StandardHandlerCodecResolvedProcedure {
|
|
93
|
+
path: string[];
|
|
94
|
+
procedure: AnyProcedure;
|
|
95
|
+
decodeInput: () => Promise<unknown>;
|
|
96
|
+
}
|
|
97
|
+
interface StandardHandlerCodec<T extends Context> {
|
|
98
|
+
resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promisable<StandardHandlerCodecResolvedProcedure | undefined>;
|
|
99
|
+
encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
100
|
+
encodeError(error: AnyORPCError, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export { CompositeStandardHandlerPlugin as C, OtelHandlerPlugin as O, StandardHandler as S };
|
|
104
|
+
export type { StandardHandlerOptions as a, StandardHandlerHandleOptions as b, StandardHandlerCodec as c, StandardHandlerCodecResolvedProcedure as d, StandardHandlerPlugin as e, StandardHandlerRoutingInterceptorOptions as f, StandardHandlerInterceptorOptions as g, StandardHandlerHandleResult as h, StandardHandlerInterceptor as i, StandardHandlerRoutingInterceptor as j };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { AnyORPCError } from '@orpc/client';
|
|
2
|
+
import { OrderablePlugin, Interceptor, Promisable } from '@orpc/shared';
|
|
3
|
+
import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
|
|
4
|
+
import { C as Context, c as ProcedureClientInterceptor, A as AnyProcedure } from './server.BL22TloH.mjs';
|
|
5
|
+
import { Schema, ErrorMap } from '@orpc/contract';
|
|
6
|
+
|
|
7
|
+
interface StandardHandlerPlugin<T extends Context> extends OrderablePlugin {
|
|
8
|
+
/**
|
|
9
|
+
* Initializes the plugin and returns new handler options.
|
|
10
|
+
* Called once per plugin instance during composition.
|
|
11
|
+
*
|
|
12
|
+
* This method allows plugins to wrap, extend, or transform handler options
|
|
13
|
+
* such as interceptors, or configuration.
|
|
14
|
+
*
|
|
15
|
+
* @param options - The current handler options from previous plugins or base configuration
|
|
16
|
+
* @returns Transformed handler options with plugin's modifications applied
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* init(options) {
|
|
21
|
+
* return {
|
|
22
|
+
* ...options,
|
|
23
|
+
* interceptors: [...(options.interceptors || []), myInterceptor]
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
init?(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
29
|
+
}
|
|
30
|
+
declare class CompositeStandardHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
31
|
+
readonly name = "~composite";
|
|
32
|
+
protected readonly plugins: StandardHandlerPlugin<T>[];
|
|
33
|
+
constructor(plugins?: StandardHandlerPlugin<T>[]);
|
|
34
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface StandardHandlerHandleOptions<T extends Context> {
|
|
38
|
+
prefix?: `/${string}` | undefined;
|
|
39
|
+
context: T;
|
|
40
|
+
}
|
|
41
|
+
type StandardHandlerHandleResult = {
|
|
42
|
+
matched: true;
|
|
43
|
+
response: StandardResponse;
|
|
44
|
+
} | {
|
|
45
|
+
matched: false;
|
|
46
|
+
response?: undefined;
|
|
47
|
+
};
|
|
48
|
+
interface StandardHandlerInterceptorOptions<T extends Context> extends StandardHandlerCodecResolvedProcedure, StandardHandlerHandleOptions<T> {
|
|
49
|
+
request: StandardLazyRequest;
|
|
50
|
+
}
|
|
51
|
+
type StandardHandlerInterceptor<T extends Context> = Interceptor<StandardHandlerInterceptorOptions<T>, Promise<StandardResponse>>;
|
|
52
|
+
interface StandardHandlerRoutingInterceptorOptions<T extends Context> extends StandardHandlerHandleOptions<T> {
|
|
53
|
+
request: StandardLazyRequest;
|
|
54
|
+
}
|
|
55
|
+
type StandardHandlerRoutingInterceptor<T extends Context> = Interceptor<StandardHandlerRoutingInterceptorOptions<T>, Promise<StandardHandlerHandleResult>>;
|
|
56
|
+
interface StandardHandlerOptions<TContext extends Context> {
|
|
57
|
+
/**
|
|
58
|
+
* Fired on every request before routing, useful when you want
|
|
59
|
+
* to intercept all requests regardless of whether they match a procedure or not.
|
|
60
|
+
*
|
|
61
|
+
* @examples
|
|
62
|
+
* - batch plugins - separate one request into multiple and call multiple next
|
|
63
|
+
* - openapi spec plugin - to intercept a request and early response
|
|
64
|
+
*/
|
|
65
|
+
routingInterceptors?: StandardHandlerRoutingInterceptor<TContext>[];
|
|
66
|
+
/**
|
|
67
|
+
* interceptor run after routing and before error handler,
|
|
68
|
+
* useful for error handling, logging, metrics, etc.
|
|
69
|
+
*/
|
|
70
|
+
interceptors?: StandardHandlerInterceptor<TContext>[];
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* ClientInterceptor equivalent with createRouterClient.interceptors / createProcedure.interceptors
|
|
74
|
+
* useful for error handling, logging, metrics, etc. (not counting encoding/decoding)
|
|
75
|
+
*/
|
|
76
|
+
clientInterceptors?: ProcedureClientInterceptor<TContext, Schema<unknown>, ErrorMap, any>[];
|
|
77
|
+
plugins?: StandardHandlerPlugin<TContext>[];
|
|
78
|
+
}
|
|
79
|
+
declare class StandardHandler<T extends Context> {
|
|
80
|
+
private readonly codec;
|
|
81
|
+
private readonly routingInterceptors;
|
|
82
|
+
private readonly interceptors;
|
|
83
|
+
private readonly clientInterceptors;
|
|
84
|
+
constructor(codec: StandardHandlerCodec<T>, options: StandardHandlerOptions<T>);
|
|
85
|
+
handle(request: StandardLazyRequest, { context, prefix }: StandardHandlerHandleOptions<T>): Promise<StandardHandlerHandleResult>;
|
|
86
|
+
}
|
|
87
|
+
declare class OtelHandlerPlugin implements StandardHandlerPlugin<any> {
|
|
88
|
+
name: string;
|
|
89
|
+
init(options: StandardHandlerOptions<any>): StandardHandlerOptions<any>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface StandardHandlerCodecResolvedProcedure {
|
|
93
|
+
path: string[];
|
|
94
|
+
procedure: AnyProcedure;
|
|
95
|
+
decodeInput: () => Promise<unknown>;
|
|
96
|
+
}
|
|
97
|
+
interface StandardHandlerCodec<T extends Context> {
|
|
98
|
+
resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promisable<StandardHandlerCodecResolvedProcedure | undefined>;
|
|
99
|
+
encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
100
|
+
encodeError(error: AnyORPCError, procedure: AnyProcedure, path: string[], options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export { CompositeStandardHandlerPlugin as C, OtelHandlerPlugin as O, StandardHandler as S };
|
|
104
|
+
export type { StandardHandlerOptions as a, StandardHandlerHandleOptions as b, StandardHandlerCodec as c, StandardHandlerCodecResolvedProcedure as d, StandardHandlerPlugin as e, StandardHandlerRoutingInterceptorOptions as f, StandardHandlerInterceptorOptions as g, StandardHandlerHandleResult as h, StandardHandlerInterceptor as i, StandardHandlerRoutingInterceptor as j };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ORPCError } from '@orpc/client';
|
|
2
|
+
import { toArray } from '@orpc/shared';
|
|
3
|
+
import { flattenStandardHeader } from '@standardserver/core';
|
|
4
|
+
|
|
5
|
+
class CSRFGuardHandlerPlugin {
|
|
6
|
+
name = "~csrf-guard";
|
|
7
|
+
init(options) {
|
|
8
|
+
const interceptor = async (interceptorOptions) => {
|
|
9
|
+
const mode = flattenStandardHeader(
|
|
10
|
+
interceptorOptions.request.headers["sec-fetch-mode"]
|
|
11
|
+
)?.toLowerCase();
|
|
12
|
+
if (mode === void 0) {
|
|
13
|
+
return interceptorOptions.next();
|
|
14
|
+
}
|
|
15
|
+
if (mode === "cors" || mode === "same-origin") {
|
|
16
|
+
return interceptorOptions.next();
|
|
17
|
+
}
|
|
18
|
+
throw new ORPCError("FORBIDDEN", {
|
|
19
|
+
message: "Request blocked by CSRF protection."
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
...options,
|
|
24
|
+
// appended last so user's interceptors can catch ORPCError
|
|
25
|
+
interceptors: [...toArray(options.interceptors), interceptor]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { CSRFGuardHandlerPlugin as C };
|