@orpc/server 1.14.11 → 1.14.13
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 +98 -52
- package/dist/adapters/aws-lambda/index.d.mts +46 -0
- package/dist/adapters/aws-lambda/index.d.ts +46 -0
- package/dist/adapters/aws-lambda/index.mjs +40 -0
- package/dist/adapters/bun-ws/index.d.mts +36 -0
- package/dist/adapters/bun-ws/index.d.ts +36 -0
- package/dist/adapters/bun-ws/index.mjs +47 -0
- package/dist/adapters/crossws/index.d.mts +21 -45
- package/dist/adapters/crossws/index.d.ts +21 -45
- package/dist/adapters/crossws/index.mjs +18 -40
- package/dist/adapters/fastify/index.d.mts +53 -0
- package/dist/adapters/fastify/index.d.ts +53 -0
- package/dist/adapters/fastify/index.mjs +52 -0
- package/dist/adapters/fetch/index.d.mts +96 -64
- package/dist/adapters/fetch/index.d.ts +96 -64
- package/dist/adapters/fetch/index.mjs +139 -34
- package/dist/adapters/message-port/index.d.mts +34 -49
- package/dist/adapters/message-port/index.d.ts +34 -49
- package/dist/adapters/message-port/index.mjs +37 -68
- package/dist/adapters/node/index.d.mts +71 -63
- package/dist/adapters/node/index.d.ts +71 -63
- package/dist/adapters/node/index.mjs +113 -36
- package/dist/adapters/standard/index.d.mts +18 -16
- package/dist/adapters/standard/index.d.ts +18 -16
- package/dist/adapters/standard/index.mjs +5 -5
- package/dist/adapters/standard-peer/index.d.mts +14 -12
- package/dist/adapters/standard-peer/index.d.ts +14 -12
- package/dist/adapters/standard-peer/index.mjs +21 -2
- package/dist/adapters/websocket/index.d.mts +38 -53
- package/dist/adapters/websocket/index.d.ts +38 -53
- package/dist/adapters/websocket/index.mjs +42 -59
- package/dist/adapters/ws/index.d.mts +31 -0
- package/dist/adapters/ws/index.d.ts +31 -0
- package/dist/adapters/ws/index.mjs +41 -0
- package/dist/helpers/index.d.mts +4 -4
- package/dist/helpers/index.d.ts +4 -4
- package/dist/helpers/index.mjs +5 -13
- package/dist/hibernation/index.d.mts +44 -0
- package/dist/hibernation/index.d.ts +44 -0
- package/dist/hibernation/index.mjs +65 -0
- package/dist/index.d.mts +770 -166
- package/dist/index.d.ts +770 -166
- package/dist/index.mjs +399 -306
- package/dist/plugins/index.d.mts +121 -214
- package/dist/plugins/index.d.ts +121 -214
- package/dist/plugins/index.mjs +214 -576
- package/dist/shared/server.7cEtMB30.d.ts +74 -0
- package/dist/shared/server.B8gYOD5g.d.mts +12 -0
- package/dist/shared/server.BqadksTP.d.mts +74 -0
- package/dist/shared/server.C8_sRzQB.d.mts +42 -0
- package/dist/shared/server.CMf4nKky.mjs +230 -0
- package/dist/shared/server.ChyoA9XY.d.ts +42 -0
- package/dist/shared/server.D8IXzfqT.d.ts +32 -0
- package/dist/shared/server.DEBcqOjg.mjs +418 -0
- package/dist/shared/{server.W91HSRkE.mjs → server.DZ5BIITo.mjs} +2 -2
- package/dist/shared/server.DzE6WeuY.d.mts +32 -0
- package/dist/shared/server.EfTOZ2Q7.d.ts +12 -0
- package/dist/shared/server.TEVCLCFC.mjs +39 -0
- package/dist/shared/server.qKsRrdxW.d.mts +193 -0
- package/dist/shared/server.qKsRrdxW.d.ts +193 -0
- package/package.json +56 -26
- package/dist/extensions/callable.d.mts +0 -10
- package/dist/extensions/callable.d.ts +0 -10
- package/dist/extensions/callable.mjs +0 -11
- package/dist/shared/server.15O7oC1p.d.mts +0 -61
- package/dist/shared/server.B4BnEWWm.d.mts +0 -67
- package/dist/shared/server.BhsVw7m7.d.ts +0 -104
- package/dist/shared/server.BoiFpNT7.mjs +0 -224
- package/dist/shared/server.COPVXhDG.mjs +0 -271
- package/dist/shared/server.CX4vUnDk.mjs +0 -11
- package/dist/shared/server.CcR4kgje.d.mts +0 -206
- package/dist/shared/server.CcR4kgje.d.ts +0 -206
- package/dist/shared/server.CnN50DHH.d.ts +0 -67
- package/dist/shared/server.DBs0rrf9.mjs +0 -41
- package/dist/shared/server.DDFizwfU.d.mts +0 -104
- package/dist/shared/server.D_QauotT.mjs +0 -30
- package/dist/shared/server.DofEOwf-.mjs +0 -237
- package/dist/shared/server.m3szVJGU.d.ts +0 -61
|
@@ -1,44 +1,153 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import '
|
|
7
|
-
import '@
|
|
8
|
-
import '
|
|
1
|
+
import { ORPCError } from '@orpc/client';
|
|
2
|
+
import { toArray, intercept, resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
3
|
+
import { toStandardLazyRequest, toFetchResponse } from '@orpc/standard-server-fetch';
|
|
4
|
+
import { r as resolveFriendlyStandardHandleOptions } from '../../shared/server.DZ5BIITo.mjs';
|
|
5
|
+
import { C as CompositeStandardHandlerPlugin, b as StandardRPCHandler } from '../../shared/server.CMf4nKky.mjs';
|
|
6
|
+
import { S as StrictGetMethodPlugin } from '../../shared/server.TEVCLCFC.mjs';
|
|
7
|
+
import '@orpc/client/standard';
|
|
8
|
+
import '@orpc/standard-server';
|
|
9
|
+
import '../../shared/server.DEBcqOjg.mjs';
|
|
9
10
|
import '@orpc/contract';
|
|
10
|
-
import '../../shared/server.BoiFpNT7.mjs';
|
|
11
11
|
|
|
12
|
-
class
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
this.plugins = sortPlugins(plugins);
|
|
12
|
+
class BodyLimitPlugin {
|
|
13
|
+
maxBodySize;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.maxBodySize = options.maxBodySize;
|
|
17
16
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
initRuntimeAdapter(options) {
|
|
18
|
+
options.adapterInterceptors ??= [];
|
|
19
|
+
options.adapterInterceptors.push(async (options2) => {
|
|
20
|
+
if (!options2.request.body) {
|
|
21
|
+
return options2.next();
|
|
22
|
+
}
|
|
23
|
+
let currentBodySize = 0;
|
|
24
|
+
const rawReader = options2.request.body.getReader();
|
|
25
|
+
const reader = new ReadableStream({
|
|
26
|
+
start: async (controller) => {
|
|
27
|
+
try {
|
|
28
|
+
if (Number(options2.request.headers.get("content-length")) > this.maxBodySize) {
|
|
29
|
+
controller.error(new ORPCError("PAYLOAD_TOO_LARGE"));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
while (true) {
|
|
33
|
+
const { done, value } = await rawReader.read();
|
|
34
|
+
if (done) {
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
currentBodySize += value.length;
|
|
38
|
+
if (currentBodySize > this.maxBodySize) {
|
|
39
|
+
controller.error(new ORPCError("PAYLOAD_TOO_LARGE"));
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
controller.enqueue(value);
|
|
43
|
+
}
|
|
44
|
+
} finally {
|
|
45
|
+
controller.close();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const requestInit = { body: reader, duplex: "half" };
|
|
50
|
+
return options2.next({
|
|
51
|
+
...options2,
|
|
52
|
+
request: new Request(options2.request, requestInit)
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const ORDERED_SUPPORTED_ENCODINGS = ["gzip", "deflate"];
|
|
59
|
+
class CompressionPlugin {
|
|
60
|
+
encodings;
|
|
61
|
+
threshold;
|
|
62
|
+
filter;
|
|
63
|
+
constructor(options = {}) {
|
|
64
|
+
this.encodings = options.encodings ?? ORDERED_SUPPORTED_ENCODINGS;
|
|
65
|
+
this.threshold = options.threshold ?? 1024;
|
|
66
|
+
this.filter = (request, response) => {
|
|
67
|
+
const hasContentDisposition = response.headers.has("content-disposition");
|
|
68
|
+
const contentType = response.headers.get("content-type");
|
|
69
|
+
if (!hasContentDisposition && contentType?.startsWith("text/event-stream")) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return options.filter ? options.filter(request, response) : isCompressibleContentType(contentType);
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
initRuntimeAdapter(options) {
|
|
76
|
+
options.adapterInterceptors ??= [];
|
|
77
|
+
options.adapterInterceptors.unshift(async (options2) => {
|
|
78
|
+
const result = await options2.next();
|
|
79
|
+
if (!result.matched) {
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
const response = result.response;
|
|
83
|
+
if (response.headers.has("content-encoding") || response.headers.has("transfer-encoding") || isNoTransformCacheControl(response.headers.get("cache-control"))) {
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
const contentLength = response.headers.get("content-length");
|
|
87
|
+
if (contentLength && Number(contentLength) < this.threshold) {
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
const acceptEncoding = options2.request.headers.get("accept-encoding")?.split(",").map((enc) => enc.trim().split(";")[0]);
|
|
91
|
+
const encoding = this.encodings.find((enc) => acceptEncoding?.includes(enc));
|
|
92
|
+
if (!response.body || encoding === void 0) {
|
|
93
|
+
return result;
|
|
22
94
|
}
|
|
95
|
+
if (!this.filter(options2.request, response)) {
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
const compressedBody = response.body.pipeThrough(new CompressionStream(encoding));
|
|
99
|
+
const compressedHeaders = new Headers(response.headers);
|
|
100
|
+
compressedHeaders.delete("content-length");
|
|
101
|
+
compressedHeaders.set("content-encoding", encoding);
|
|
102
|
+
return {
|
|
103
|
+
...result,
|
|
104
|
+
response: new Response(compressedBody, {
|
|
105
|
+
status: response.status,
|
|
106
|
+
statusText: response.statusText,
|
|
107
|
+
headers: compressedHeaders
|
|
108
|
+
})
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/(?!event-stream(?:[;\s]|$))[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
|
|
114
|
+
function isCompressibleContentType(contentType) {
|
|
115
|
+
if (contentType === null) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return COMPRESSIBLE_CONTENT_TYPE_REGEX.test(contentType);
|
|
119
|
+
}
|
|
120
|
+
const CACHE_CONTROL_NO_TRANSFORM_REGEX = /(?:^|,)\s*no-transform\s*(?:,|$)/i;
|
|
121
|
+
function isNoTransformCacheControl(cacheControl) {
|
|
122
|
+
if (cacheControl === null) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
return CACHE_CONTROL_NO_TRANSFORM_REGEX.test(cacheControl);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
class CompositeFetchHandlerPlugin extends CompositeStandardHandlerPlugin {
|
|
129
|
+
initRuntimeAdapter(options) {
|
|
130
|
+
for (const plugin of this.plugins) {
|
|
131
|
+
plugin.initRuntimeAdapter?.(options);
|
|
23
132
|
}
|
|
24
|
-
return options;
|
|
25
133
|
}
|
|
26
134
|
}
|
|
27
135
|
|
|
28
136
|
class FetchHandler {
|
|
29
137
|
constructor(standardHandler, options = {}) {
|
|
30
138
|
this.standardHandler = standardHandler;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this.
|
|
139
|
+
const plugin = new CompositeFetchHandlerPlugin(options.plugins);
|
|
140
|
+
plugin.initRuntimeAdapter(options);
|
|
141
|
+
this.adapterInterceptors = toArray(options.adapterInterceptors);
|
|
142
|
+
this.toFetchResponseOptions = options;
|
|
34
143
|
}
|
|
35
144
|
toFetchResponseOptions;
|
|
36
|
-
|
|
145
|
+
adapterInterceptors;
|
|
37
146
|
async handle(request, ...rest) {
|
|
38
147
|
return intercept(
|
|
39
|
-
this.
|
|
148
|
+
this.adapterInterceptors,
|
|
40
149
|
{
|
|
41
|
-
...
|
|
150
|
+
...resolveFriendlyStandardHandleOptions(resolveMaybeOptionalOptions(rest)),
|
|
42
151
|
request,
|
|
43
152
|
toFetchResponseOptions: this.toFetchResponseOptions
|
|
44
153
|
},
|
|
@@ -59,16 +168,12 @@ class FetchHandler {
|
|
|
59
168
|
|
|
60
169
|
class RPCHandler extends FetchHandler {
|
|
61
170
|
constructor(router, options = {}) {
|
|
62
|
-
if (options.
|
|
63
|
-
options
|
|
64
|
-
|
|
65
|
-
plugins: [...toArray(options.plugins), new CSRFGuardHandlerPlugin()]
|
|
66
|
-
};
|
|
171
|
+
if (options.strictGetMethodPluginEnabled ?? true) {
|
|
172
|
+
options.plugins ??= [];
|
|
173
|
+
options.plugins.push(new StrictGetMethodPlugin());
|
|
67
174
|
}
|
|
68
|
-
|
|
69
|
-
const handler = new StandardHandler(codec, options);
|
|
70
|
-
super(handler, options);
|
|
175
|
+
super(new StandardRPCHandler(router, options), options);
|
|
71
176
|
}
|
|
72
177
|
}
|
|
73
178
|
|
|
74
|
-
export { CompositeFetchHandlerPlugin, FetchHandler, RPCHandler };
|
|
179
|
+
export { BodyLimitPlugin, CompositeFetchHandlerPlugin, CompressionPlugin, FetchHandler, RPCHandler };
|
|
@@ -1,71 +1,56 @@
|
|
|
1
1
|
import { SupportedMessagePort } from '@orpc/client/message-port';
|
|
2
2
|
import { Value, Promisable, MaybeOptionalOptions } from '@orpc/shared';
|
|
3
|
-
import {
|
|
4
|
-
import { C as Context } from '../../shared/server.
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { R as RPCHandlerCodecOptions } from '../../shared/server.B4BnEWWm.mjs';
|
|
3
|
+
import { DecodedResponseMessage } from '@orpc/standard-server-peer';
|
|
4
|
+
import { C as Context, R as Router } from '../../shared/server.qKsRrdxW.mjs';
|
|
5
|
+
import { f as StandardHandler } from '../../shared/server.BqadksTP.mjs';
|
|
6
|
+
import { HandleStandardServerPeerMessageOptions } from '../standard-peer/index.mjs';
|
|
7
|
+
import { S as StandardRPCHandlerOptions } from '../../shared/server.DzE6WeuY.mjs';
|
|
9
8
|
import '@orpc/client';
|
|
10
9
|
import '@orpc/contract';
|
|
11
|
-
import '@
|
|
10
|
+
import '@orpc/standard-server';
|
|
11
|
+
import '../../shared/server.B8gYOD5g.mjs';
|
|
12
|
+
import '@orpc/client/standard';
|
|
13
|
+
import '../../shared/server.C8_sRzQB.mjs';
|
|
12
14
|
|
|
13
|
-
type DecodedResponseMessage = ConstructorParameters<typeof ServerPeer>[0] extends (message: infer TMessage) => unknown ? TMessage : never;
|
|
14
15
|
interface MessagePortHandlerOptions<_T extends Context> {
|
|
15
16
|
/**
|
|
16
|
-
* By default, oRPC
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* such as transferring object ownership or supporting non-serializable objects like `OffscreenCanvas` or improving performance.
|
|
17
|
+
* By default, oRPC serializes request/response messages to string/binary data before sending over message port.
|
|
18
|
+
* If needed, you can define the this option to utilize full power of [MessagePort: postMessage() method](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage),
|
|
19
|
+
* such as transferring ownership of objects to the other side or support unserializable objects like `OffscreenCanvas`.
|
|
20
20
|
*
|
|
21
21
|
* @remarks
|
|
22
|
-
* -
|
|
22
|
+
* - return null | undefined to disable this feature
|
|
23
23
|
*
|
|
24
|
-
* @warning
|
|
24
|
+
* @warning Make sure your message port supports `transfer` before using this feature.
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* experimental_transfer: (message, port) => {
|
|
28
|
+
* const transfer = deepFindTransferableObjects(message) // implement your own logic
|
|
29
|
+
* return transfer.length ? transfer : null // only enable when needed
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @see {@link https://orpc.dev/docs/adapters/message-port#transfer Message Port Transfer Docs}
|
|
25
34
|
*/
|
|
26
35
|
experimental_transfer?: Value<Promisable<object[] | null | undefined>, [message: DecodedResponseMessage, port: SupportedMessagePort]>;
|
|
27
|
-
/**
|
|
28
|
-
* Options for encoding peer messages. such as `prefix` for distinguishing messages on the same channel..
|
|
29
|
-
*/
|
|
30
|
-
encodePeerMessage?: EncodePeerMessageOptions | undefined;
|
|
31
|
-
/**
|
|
32
|
-
* Options for decoding peer messages. such as `prefix` for distinguishing messages on the same channel..
|
|
33
|
-
*/
|
|
34
|
-
decodePeerMessage?: DecodePeerMessageOptions | undefined;
|
|
35
36
|
}
|
|
36
37
|
declare class MessagePortHandler<T extends Context> {
|
|
37
|
-
private readonly
|
|
38
|
-
private readonly peers;
|
|
38
|
+
private readonly standardHandler;
|
|
39
39
|
private readonly transfer;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
constructor(handler: StandardHandler<T>, options?: NoInfer<MessagePortHandlerOptions<T>>);
|
|
43
|
-
/**
|
|
44
|
-
* Attaches message and close listeners to a message port.
|
|
45
|
-
*
|
|
46
|
-
* Prefer this over calling `.message()` and `.close()` manually.
|
|
47
|
-
*/
|
|
48
|
-
upgrade(port: SupportedMessagePort, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): void;
|
|
49
|
-
/**
|
|
50
|
-
* Handles a single message received from a message port.
|
|
51
|
-
*
|
|
52
|
-
* @param port The message port instance. Use the same instance for all messages.
|
|
53
|
-
*/
|
|
54
|
-
message(port: SupportedMessagePort, data: unknown, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): Promise<{
|
|
55
|
-
matched: boolean;
|
|
56
|
-
}>;
|
|
57
|
-
/**
|
|
58
|
-
* Cleans up peer state for a closed message port.
|
|
59
|
-
*
|
|
60
|
-
* @param port The same message port instance passed to `.message()`.
|
|
61
|
-
*/
|
|
62
|
-
close(port: SupportedMessagePort): Promise<void>;
|
|
40
|
+
constructor(standardHandler: StandardHandler<T>, options?: NoInfer<MessagePortHandlerOptions<T>>);
|
|
41
|
+
upgrade(port: SupportedMessagePort, ...rest: MaybeOptionalOptions<HandleStandardServerPeerMessageOptions<T>>): void;
|
|
63
42
|
}
|
|
64
43
|
|
|
65
|
-
interface RPCHandlerOptions<T extends Context> extends
|
|
44
|
+
interface RPCHandlerOptions<T extends Context> extends StandardRPCHandlerOptions<T>, MessagePortHandlerOptions<T> {
|
|
66
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* RPC Handler for common message port implementations.
|
|
48
|
+
*
|
|
49
|
+
* @see {@link https://orpc.dev/docs/rpc-handler RPC Handler Docs}
|
|
50
|
+
* @see {@link https://orpc.dev/docs/adapters/message-port Message Port Adapter Docs}
|
|
51
|
+
*/
|
|
67
52
|
declare class RPCHandler<T extends Context> extends MessagePortHandler<T> {
|
|
68
|
-
constructor(router: Router<T>, options?: NoInfer<RPCHandlerOptions<T>>);
|
|
53
|
+
constructor(router: Router<any, T>, options?: NoInfer<RPCHandlerOptions<T>>);
|
|
69
54
|
}
|
|
70
55
|
|
|
71
56
|
export { MessagePortHandler, RPCHandler };
|
|
@@ -1,71 +1,56 @@
|
|
|
1
1
|
import { SupportedMessagePort } from '@orpc/client/message-port';
|
|
2
2
|
import { Value, Promisable, MaybeOptionalOptions } from '@orpc/shared';
|
|
3
|
-
import {
|
|
4
|
-
import { C as Context } from '../../shared/server.
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { R as RPCHandlerCodecOptions } from '../../shared/server.CnN50DHH.js';
|
|
3
|
+
import { DecodedResponseMessage } from '@orpc/standard-server-peer';
|
|
4
|
+
import { C as Context, R as Router } from '../../shared/server.qKsRrdxW.js';
|
|
5
|
+
import { f as StandardHandler } from '../../shared/server.7cEtMB30.js';
|
|
6
|
+
import { HandleStandardServerPeerMessageOptions } from '../standard-peer/index.js';
|
|
7
|
+
import { S as StandardRPCHandlerOptions } from '../../shared/server.D8IXzfqT.js';
|
|
9
8
|
import '@orpc/client';
|
|
10
9
|
import '@orpc/contract';
|
|
11
|
-
import '@
|
|
10
|
+
import '@orpc/standard-server';
|
|
11
|
+
import '../../shared/server.EfTOZ2Q7.js';
|
|
12
|
+
import '@orpc/client/standard';
|
|
13
|
+
import '../../shared/server.ChyoA9XY.js';
|
|
12
14
|
|
|
13
|
-
type DecodedResponseMessage = ConstructorParameters<typeof ServerPeer>[0] extends (message: infer TMessage) => unknown ? TMessage : never;
|
|
14
15
|
interface MessagePortHandlerOptions<_T extends Context> {
|
|
15
16
|
/**
|
|
16
|
-
* By default, oRPC
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* such as transferring object ownership or supporting non-serializable objects like `OffscreenCanvas` or improving performance.
|
|
17
|
+
* By default, oRPC serializes request/response messages to string/binary data before sending over message port.
|
|
18
|
+
* If needed, you can define the this option to utilize full power of [MessagePort: postMessage() method](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/postMessage),
|
|
19
|
+
* such as transferring ownership of objects to the other side or support unserializable objects like `OffscreenCanvas`.
|
|
20
20
|
*
|
|
21
21
|
* @remarks
|
|
22
|
-
* -
|
|
22
|
+
* - return null | undefined to disable this feature
|
|
23
23
|
*
|
|
24
|
-
* @warning
|
|
24
|
+
* @warning Make sure your message port supports `transfer` before using this feature.
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* experimental_transfer: (message, port) => {
|
|
28
|
+
* const transfer = deepFindTransferableObjects(message) // implement your own logic
|
|
29
|
+
* return transfer.length ? transfer : null // only enable when needed
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @see {@link https://orpc.dev/docs/adapters/message-port#transfer Message Port Transfer Docs}
|
|
25
34
|
*/
|
|
26
35
|
experimental_transfer?: Value<Promisable<object[] | null | undefined>, [message: DecodedResponseMessage, port: SupportedMessagePort]>;
|
|
27
|
-
/**
|
|
28
|
-
* Options for encoding peer messages. such as `prefix` for distinguishing messages on the same channel..
|
|
29
|
-
*/
|
|
30
|
-
encodePeerMessage?: EncodePeerMessageOptions | undefined;
|
|
31
|
-
/**
|
|
32
|
-
* Options for decoding peer messages. such as `prefix` for distinguishing messages on the same channel..
|
|
33
|
-
*/
|
|
34
|
-
decodePeerMessage?: DecodePeerMessageOptions | undefined;
|
|
35
36
|
}
|
|
36
37
|
declare class MessagePortHandler<T extends Context> {
|
|
37
|
-
private readonly
|
|
38
|
-
private readonly peers;
|
|
38
|
+
private readonly standardHandler;
|
|
39
39
|
private readonly transfer;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
constructor(handler: StandardHandler<T>, options?: NoInfer<MessagePortHandlerOptions<T>>);
|
|
43
|
-
/**
|
|
44
|
-
* Attaches message and close listeners to a message port.
|
|
45
|
-
*
|
|
46
|
-
* Prefer this over calling `.message()` and `.close()` manually.
|
|
47
|
-
*/
|
|
48
|
-
upgrade(port: SupportedMessagePort, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): void;
|
|
49
|
-
/**
|
|
50
|
-
* Handles a single message received from a message port.
|
|
51
|
-
*
|
|
52
|
-
* @param port The message port instance. Use the same instance for all messages.
|
|
53
|
-
*/
|
|
54
|
-
message(port: SupportedMessagePort, data: unknown, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): Promise<{
|
|
55
|
-
matched: boolean;
|
|
56
|
-
}>;
|
|
57
|
-
/**
|
|
58
|
-
* Cleans up peer state for a closed message port.
|
|
59
|
-
*
|
|
60
|
-
* @param port The same message port instance passed to `.message()`.
|
|
61
|
-
*/
|
|
62
|
-
close(port: SupportedMessagePort): Promise<void>;
|
|
40
|
+
constructor(standardHandler: StandardHandler<T>, options?: NoInfer<MessagePortHandlerOptions<T>>);
|
|
41
|
+
upgrade(port: SupportedMessagePort, ...rest: MaybeOptionalOptions<HandleStandardServerPeerMessageOptions<T>>): void;
|
|
63
42
|
}
|
|
64
43
|
|
|
65
|
-
interface RPCHandlerOptions<T extends Context> extends
|
|
44
|
+
interface RPCHandlerOptions<T extends Context> extends StandardRPCHandlerOptions<T>, MessagePortHandlerOptions<T> {
|
|
66
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* RPC Handler for common message port implementations.
|
|
48
|
+
*
|
|
49
|
+
* @see {@link https://orpc.dev/docs/rpc-handler RPC Handler Docs}
|
|
50
|
+
* @see {@link https://orpc.dev/docs/adapters/message-port Message Port Adapter Docs}
|
|
51
|
+
*/
|
|
67
52
|
declare class RPCHandler<T extends Context> extends MessagePortHandler<T> {
|
|
68
|
-
constructor(router: Router<T>, options?: NoInfer<RPCHandlerOptions<T>>);
|
|
53
|
+
constructor(router: Router<any, T>, options?: NoInfer<RPCHandlerOptions<T>>);
|
|
69
54
|
}
|
|
70
55
|
|
|
71
56
|
export { MessagePortHandler, RPCHandler };
|
|
@@ -1,85 +1,54 @@
|
|
|
1
|
-
import { onMessagePortMessage, onMessagePortClose
|
|
2
|
-
import { value, resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { postMessagePortMessage, onMessagePortMessage, onMessagePortClose } from '@orpc/client/message-port';
|
|
2
|
+
import { value, resolveMaybeOptionalOptions, isObject } from '@orpc/shared';
|
|
3
|
+
import { experimental_ServerPeerWithoutCodec, serializeResponseMessage, encodeResponseMessage, deserializeRequestMessage, decodeRequestMessage } from '@orpc/standard-server-peer';
|
|
4
|
+
import { createServerPeerHandleRequestFn } from '../standard-peer/index.mjs';
|
|
5
|
+
import { b as StandardRPCHandler } from '../../shared/server.CMf4nKky.mjs';
|
|
6
|
+
import '../../shared/server.DZ5BIITo.mjs';
|
|
7
|
+
import '@orpc/client/standard';
|
|
6
8
|
import '@orpc/client';
|
|
7
|
-
import '@
|
|
8
|
-
import '../../shared/server.
|
|
9
|
+
import '@orpc/standard-server';
|
|
10
|
+
import '../../shared/server.DEBcqOjg.mjs';
|
|
9
11
|
import '@orpc/contract';
|
|
10
|
-
import '../../shared/server.BoiFpNT7.mjs';
|
|
11
12
|
|
|
12
13
|
class MessagePortHandler {
|
|
13
|
-
constructor(
|
|
14
|
-
this.
|
|
14
|
+
constructor(standardHandler, options = {}) {
|
|
15
|
+
this.standardHandler = standardHandler;
|
|
15
16
|
this.transfer = options.experimental_transfer;
|
|
16
|
-
this.encodePeerMessageOptions = options.encodePeerMessage;
|
|
17
|
-
this.decodePeerMessageOptions = options.decodePeerMessage;
|
|
18
17
|
}
|
|
19
|
-
peers = /* @__PURE__ */ new WeakMap();
|
|
20
18
|
transfer;
|
|
21
|
-
encodePeerMessageOptions;
|
|
22
|
-
decodePeerMessageOptions;
|
|
23
|
-
/**
|
|
24
|
-
* Attaches message and close listeners to a message port.
|
|
25
|
-
*
|
|
26
|
-
* Prefer this over calling `.message()` and `.close()` manually.
|
|
27
|
-
*/
|
|
28
19
|
upgrade(port, ...rest) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
*/
|
|
37
|
-
async message(port, data, ...rest) {
|
|
38
|
-
let peer = this.peers.get(port);
|
|
39
|
-
if (!peer) {
|
|
40
|
-
this.peers.set(port, peer = new ServerPeer(async (message) => {
|
|
41
|
-
const transfer = await value(this.transfer, message, port);
|
|
42
|
-
if (transfer) {
|
|
43
|
-
postMessagePortMessage(port, message, transfer);
|
|
44
|
-
} else {
|
|
45
|
-
postMessagePortMessage(port, await encodePeerMessage(message, this.encodePeerMessageOptions));
|
|
46
|
-
}
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
let peerMessage;
|
|
50
|
-
if (typeof data === "string" || data instanceof Uint8Array) {
|
|
51
|
-
const result = decodePeerMessage(data, this.decodePeerMessageOptions);
|
|
52
|
-
if (result.matched && isClientPeerSendMessage(result.message)) {
|
|
53
|
-
peerMessage = result.message;
|
|
20
|
+
const peer = new experimental_ServerPeerWithoutCodec(async (message) => {
|
|
21
|
+
const [id, type, payload] = message;
|
|
22
|
+
const transfer = await value(this.transfer, message, port);
|
|
23
|
+
if (transfer) {
|
|
24
|
+
postMessagePortMessage(port, serializeResponseMessage(id, type, payload), transfer);
|
|
25
|
+
} else {
|
|
26
|
+
postMessagePortMessage(port, await encodeResponseMessage(id, type, payload));
|
|
54
27
|
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
await peer.close();
|
|
74
|
-
}
|
|
28
|
+
});
|
|
29
|
+
onMessagePortMessage(port, async (message) => {
|
|
30
|
+
const handleFn = createServerPeerHandleRequestFn(this.standardHandler, resolveMaybeOptionalOptions(rest));
|
|
31
|
+
if (isObject(message)) {
|
|
32
|
+
await peer.message(
|
|
33
|
+
deserializeRequestMessage(message),
|
|
34
|
+
handleFn
|
|
35
|
+
);
|
|
36
|
+
} else {
|
|
37
|
+
await peer.message(
|
|
38
|
+
await decodeRequestMessage(message),
|
|
39
|
+
handleFn
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
onMessagePortClose(port, () => {
|
|
44
|
+
peer.close();
|
|
45
|
+
});
|
|
75
46
|
}
|
|
76
47
|
}
|
|
77
48
|
|
|
78
49
|
class RPCHandler extends MessagePortHandler {
|
|
79
50
|
constructor(router, options = {}) {
|
|
80
|
-
|
|
81
|
-
const handler = new StandardHandler(codec, options);
|
|
82
|
-
super(handler, options);
|
|
51
|
+
super(new StandardRPCHandler(router, options), options);
|
|
83
52
|
}
|
|
84
53
|
}
|
|
85
54
|
|