@orpc/server 2.0.0-beta.3 → 2.0.0-beta.31

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.
Files changed (56) hide show
  1. package/README.md +71 -101
  2. package/dist/adapters/aws-lambda/index.d.mts +93 -0
  3. package/dist/adapters/aws-lambda/index.d.ts +93 -0
  4. package/dist/adapters/aws-lambda/index.mjs +66 -0
  5. package/dist/adapters/crossws/index.d.mts +17 -8
  6. package/dist/adapters/crossws/index.d.ts +17 -8
  7. package/dist/adapters/crossws/index.mjs +10 -7
  8. package/dist/adapters/fastify/index.d.mts +85 -0
  9. package/dist/adapters/fastify/index.d.ts +85 -0
  10. package/dist/adapters/fastify/index.mjs +66 -0
  11. package/dist/adapters/fetch/index.d.mts +16 -67
  12. package/dist/adapters/fetch/index.d.ts +16 -67
  13. package/dist/adapters/fetch/index.mjs +8 -144
  14. package/dist/adapters/message-port/index.d.mts +19 -16
  15. package/dist/adapters/message-port/index.d.ts +19 -16
  16. package/dist/adapters/message-port/index.mjs +28 -32
  17. package/dist/adapters/node/index.d.mts +15 -49
  18. package/dist/adapters/node/index.d.ts +15 -49
  19. package/dist/adapters/node/index.mjs +9 -120
  20. package/dist/adapters/standard/index.d.mts +6 -6
  21. package/dist/adapters/standard/index.d.ts +6 -6
  22. package/dist/adapters/standard/index.mjs +3 -3
  23. package/dist/adapters/standard-peer/index.d.mts +2 -2
  24. package/dist/adapters/standard-peer/index.d.ts +2 -2
  25. package/dist/adapters/websocket/index.d.mts +42 -26
  26. package/dist/adapters/websocket/index.d.ts +42 -26
  27. package/dist/adapters/websocket/index.mjs +33 -25
  28. package/dist/extensions/callable.d.mts +2 -2
  29. package/dist/extensions/callable.d.ts +2 -2
  30. package/dist/extensions/callable.mjs +2 -2
  31. package/dist/helpers/index.d.mts +23 -6
  32. package/dist/helpers/index.d.ts +23 -6
  33. package/dist/helpers/index.mjs +13 -5
  34. package/dist/index.d.mts +311 -16
  35. package/dist/index.d.ts +311 -16
  36. package/dist/index.mjs +126 -34
  37. package/dist/plugins/index.d.mts +241 -32
  38. package/dist/plugins/index.d.ts +241 -32
  39. package/dist/plugins/index.mjs +479 -15
  40. package/dist/shared/server.BhHrioCw.d.ts +34 -0
  41. package/dist/shared/{server.T9F3bzZx.d.ts → server.C2n16pp0.d.ts} +34 -9
  42. package/dist/shared/server.Cd4Z1hpV.mjs +69 -0
  43. package/dist/shared/{server.CrlKQucM.mjs → server.CkButhNT.mjs} +21 -38
  44. package/dist/shared/{server.B_U9y00a.d.mts → server.CkNnZ5F-.d.mts} +34 -9
  45. package/dist/shared/{server.BL22TloH.d.mts → server.CwrYlF72.d.mts} +31 -41
  46. package/dist/shared/{server.BL22TloH.d.ts → server.CwrYlF72.d.ts} +31 -41
  47. package/dist/shared/server.D0Ipbmdv.d.mts +34 -0
  48. package/dist/shared/{server.BwHnWUuN.mjs → server.Dh77P3ii.mjs} +17 -10
  49. package/dist/shared/{server.Pa0F03f_.d.ts → server.Dm0os-OP.d.mts} +24 -12
  50. package/dist/shared/{server.GDpX6Df8.mjs → server.DpUGXBi2.mjs} +84 -51
  51. package/dist/shared/{server.EOHJ3NJr.d.ts → server.DrN1Pj1-.d.ts} +3 -3
  52. package/dist/shared/{server.BsNNjG5J.d.mts → server.DtfwuV6U.d.ts} +24 -12
  53. package/dist/shared/{server.BB_Ik9Ph.d.mts → server.JbCIPL4P.d.mts} +3 -3
  54. package/dist/shared/{server.CjOb6ItT.mjs → server.eCTV8Vpp.mjs} +1 -1
  55. package/package.json +46 -12
  56. package/dist/shared/server.D_QauotT.mjs +0 -30
@@ -1,122 +1,17 @@
1
- import compression from '@orpc/interop/compression';
2
- import { toArray, sortPlugins, intercept, resolveMaybeOptionalOptions } from '@orpc/shared';
3
- import { ORPCError } from '@orpc/client';
1
+ export { R as BodyLimitPlugin } from '../../shared/server.Cd4Z1hpV.mjs';
2
+ import { sortPlugins, intercept, resolveMaybeOptionalOptions } from '@orpc/shared';
4
3
  import { toStandardLazyRequest, sendStandardResponse } from '@standardserver/node';
5
4
  import { r as resolveFriendlyStandardHandlerHandleOptions } from '../../shared/server.W91HSRkE.mjs';
6
- import { C as CSRFGuardHandlerPlugin } from '../../shared/server.D_QauotT.mjs';
7
- import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.GDpX6Df8.mjs';
5
+ import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.DpUGXBi2.mjs';
6
+ import '@orpc/client';
8
7
  import '@standardserver/core';
9
- import '../../shared/server.CrlKQucM.mjs';
8
+ import '@standardserver/fetch';
9
+ import '../../shared/server.CkButhNT.mjs';
10
10
  import '@orpc/contract';
11
- import '../../shared/server.BwHnWUuN.mjs';
12
-
13
- class BodyCompressionHandlerPlugin {
14
- name = "~body-compression";
15
- compressionHandler;
16
- constructor(options = {}) {
17
- this.compressionHandler = compression({
18
- ...options,
19
- filter: (request, response) => {
20
- const hasContentDisposition = response.hasHeader("content-disposition");
21
- const contentType = response.getHeader("content-type")?.toString();
22
- if (!hasContentDisposition && contentType?.startsWith("text/event-stream")) {
23
- return false;
24
- }
25
- return options.filter ? options.filter(request, response) : compression.filter(request, response);
26
- }
27
- });
28
- }
29
- initNodeHttpHandlerOptions(options) {
30
- return {
31
- ...options,
32
- nodeHttpInterceptors: [
33
- async (interceptorOptions) => {
34
- let resolve;
35
- let reject;
36
- const promise = new Promise((res, rej) => {
37
- resolve = res;
38
- reject = rej;
39
- });
40
- const originalWrite = interceptorOptions.response.write;
41
- const originalEnd = interceptorOptions.response.end;
42
- const originalOn = interceptorOptions.response.on;
43
- this.compressionHandler(
44
- interceptorOptions.request,
45
- interceptorOptions.response,
46
- async (error) => {
47
- if (error) {
48
- reject(error);
49
- } else {
50
- try {
51
- resolve(await interceptorOptions.next(interceptorOptions));
52
- } catch (nextError) {
53
- reject(nextError);
54
- }
55
- }
56
- }
57
- );
58
- try {
59
- return await promise;
60
- } finally {
61
- interceptorOptions.response.write = originalWrite;
62
- interceptorOptions.response.end = originalEnd;
63
- interceptorOptions.response.on = originalOn;
64
- }
65
- },
66
- ...toArray(options.nodeHttpInterceptors)
67
- ]
68
- };
69
- }
70
- }
71
-
72
- class BodyLimitHandlerPlugin {
73
- name = "~body-limit";
74
- maxBodySize;
75
- constructor(options) {
76
- this.maxBodySize = options.maxBodySize;
77
- }
78
- initNodeHttpHandlerOptions(options) {
79
- return {
80
- ...options,
81
- nodeHttpInterceptors: [
82
- async (interceptorOptions) => {
83
- let isHeaderChecked = false;
84
- const checkHeader = () => {
85
- if (isHeaderChecked) {
86
- return;
87
- }
88
- isHeaderChecked = true;
89
- const contentLength = interceptorOptions.request.headers["content-length"];
90
- if (contentLength && Number(contentLength) > this.maxBodySize) {
91
- throw new ORPCError("PAYLOAD_TOO_LARGE");
92
- }
93
- };
94
- const originalEmit = interceptorOptions.request.emit;
95
- let currentBodySize = 0;
96
- interceptorOptions.request.emit = (event, ...args) => {
97
- if (event === "data") {
98
- checkHeader();
99
- currentBodySize += args[0]?.length ?? 0;
100
- if (currentBodySize > this.maxBodySize) {
101
- throw new ORPCError("PAYLOAD_TOO_LARGE");
102
- }
103
- }
104
- return originalEmit.call(interceptorOptions.request, event, ...args);
105
- };
106
- try {
107
- return await interceptorOptions.next(interceptorOptions);
108
- } finally {
109
- interceptorOptions.request.emit = originalEmit;
110
- }
111
- },
112
- ...toArray(options.nodeHttpInterceptors)
113
- ]
114
- };
115
- }
116
- }
11
+ import '../../shared/server.Dh77P3ii.mjs';
117
12
 
118
13
  class CompositeNodeHttpHandlerPlugin {
119
- name = "~composite/node-http-handler";
14
+ name = "~composite/node-http";
120
15
  plugins;
121
16
  constructor(plugins = []) {
122
17
  this.plugins = sortPlugins(plugins);
@@ -164,16 +59,10 @@ class NodeHttpHandler {
164
59
 
165
60
  class RPCHandler extends NodeHttpHandler {
166
61
  constructor(router, options = {}) {
167
- if (options.csrfGuardPlugin?.enabled !== false) {
168
- options = {
169
- ...options,
170
- plugins: [...toArray(options.plugins), new CSRFGuardHandlerPlugin()]
171
- };
172
- }
173
62
  const codec = new RPCHandlerCodec(router, options);
174
63
  const handler = new StandardHandler(codec, options);
175
64
  super(handler, options);
176
65
  }
177
66
  }
178
67
 
179
- export { BodyCompressionHandlerPlugin, BodyLimitHandlerPlugin, CompositeNodeHttpHandlerPlugin, NodeHttpHandler, RPCHandler };
68
+ export { CompositeNodeHttpHandlerPlugin, NodeHttpHandler, RPCHandler };
@@ -1,12 +1,12 @@
1
- import { b as StandardHandlerHandleOptions } from '../../shared/server.BB_Ik9Ph.mjs';
2
- export { C as CompositeStandardHandlerPlugin, O as OtelHandlerPlugin, S as StandardHandler, c as StandardHandlerCodec, d as StandardHandlerCodecResolvedProcedure, g as StandardHandlerHandleResult, h as StandardHandlerInterceptor, i as StandardHandlerInterceptorOptions, a as StandardHandlerOptions, e as StandardHandlerPlugin, j as StandardHandlerRoutingInterceptor, f as StandardHandlerRoutingInterceptorOptions } from '../../shared/server.BB_Ik9Ph.mjs';
3
- export { a as RPCHandlerCodec, R as RPCHandlerCodecOptions, b as RPCMatcher, c as RPCMatcherOptions } from '../../shared/server.B_U9y00a.mjs';
4
- import { C as Context } from '../../shared/server.BL22TloH.mjs';
5
- export { StandardBody, StandardBodyHint, StandardHeaders, StandardLazyRequest, StandardLazyResponse, StandardMethod, StandardRequest, StandardResponse, StandardUrl } from '@standardserver/core';
1
+ import { c as StandardHandlerHandleOptions } from '../../shared/server.JbCIPL4P.mjs';
2
+ export { C as CompositeStandardHandlerPlugin, O as OtelHandlerPlugin, b as StandardHandler, d as StandardHandlerCodec, e as StandardHandlerCodecResolvedProcedure, h as StandardHandlerHandleResult, i as StandardHandlerInterceptor, g as StandardHandlerInterceptorOptions, a as StandardHandlerOptions, S as StandardHandlerPlugin, j as StandardHandlerRoutingInterceptor, f as StandardHandlerRoutingInterceptorOptions } from '../../shared/server.JbCIPL4P.mjs';
3
+ export { a as RPCHandlerCodec, R as RPCHandlerCodecOptions, b as RPCMatcher, c as RPCMatcherOptions, d as RPC_DEFAULT_ALLOW_METHODS } from '../../shared/server.CkNnZ5F-.mjs';
4
+ import { Context } from '../../index.mjs';
6
5
  import '@orpc/client';
7
6
  import '@orpc/shared';
7
+ import '@standardserver/core';
8
8
  import '@orpc/contract';
9
- import '../../shared/server.BsNNjG5J.mjs';
9
+ import '../../shared/server.Dm0os-OP.mjs';
10
10
 
11
11
  type FriendlyStandardHandlerHandleOptions<T extends Context> = Omit<StandardHandlerHandleOptions<T>, 'context'> & (object extends T ? {
12
12
  context?: T;
@@ -1,12 +1,12 @@
1
- import { b as StandardHandlerHandleOptions } from '../../shared/server.EOHJ3NJr.js';
2
- export { C as CompositeStandardHandlerPlugin, O as OtelHandlerPlugin, S as StandardHandler, c as StandardHandlerCodec, d as StandardHandlerCodecResolvedProcedure, g as StandardHandlerHandleResult, h as StandardHandlerInterceptor, i as StandardHandlerInterceptorOptions, a as StandardHandlerOptions, e as StandardHandlerPlugin, j as StandardHandlerRoutingInterceptor, f as StandardHandlerRoutingInterceptorOptions } from '../../shared/server.EOHJ3NJr.js';
3
- export { a as RPCHandlerCodec, R as RPCHandlerCodecOptions, b as RPCMatcher, c as RPCMatcherOptions } from '../../shared/server.T9F3bzZx.js';
4
- import { C as Context } from '../../shared/server.BL22TloH.js';
5
- export { StandardBody, StandardBodyHint, StandardHeaders, StandardLazyRequest, StandardLazyResponse, StandardMethod, StandardRequest, StandardResponse, StandardUrl } from '@standardserver/core';
1
+ import { c as StandardHandlerHandleOptions } from '../../shared/server.DrN1Pj1-.js';
2
+ export { C as CompositeStandardHandlerPlugin, O as OtelHandlerPlugin, b as StandardHandler, d as StandardHandlerCodec, e as StandardHandlerCodecResolvedProcedure, h as StandardHandlerHandleResult, i as StandardHandlerInterceptor, g as StandardHandlerInterceptorOptions, a as StandardHandlerOptions, S as StandardHandlerPlugin, j as StandardHandlerRoutingInterceptor, f as StandardHandlerRoutingInterceptorOptions } from '../../shared/server.DrN1Pj1-.js';
3
+ export { a as RPCHandlerCodec, R as RPCHandlerCodecOptions, b as RPCMatcher, c as RPCMatcherOptions, d as RPC_DEFAULT_ALLOW_METHODS } from '../../shared/server.C2n16pp0.js';
4
+ import { Context } from '../../index.js';
6
5
  import '@orpc/client';
7
6
  import '@orpc/shared';
7
+ import '@standardserver/core';
8
8
  import '@orpc/contract';
9
- import '../../shared/server.Pa0F03f_.js';
9
+ import '../../shared/server.DtfwuV6U.js';
10
10
 
11
11
  type FriendlyStandardHandlerHandleOptions<T extends Context> = Omit<StandardHandlerHandleOptions<T>, 'context'> & (object extends T ? {
12
12
  context?: T;
@@ -1,8 +1,8 @@
1
- export { C as CompositeStandardHandlerPlugin, O as OtelHandlerPlugin, R as RPCHandlerCodec, a as RPCMatcher, S as StandardHandler } from '../../shared/server.GDpX6Df8.mjs';
1
+ export { C as CompositeStandardHandlerPlugin, O as OtelHandlerPlugin, R as RPCHandlerCodec, a as RPCMatcher, b as RPC_DEFAULT_ALLOW_METHODS, S as StandardHandler } from '../../shared/server.DpUGXBi2.mjs';
2
2
  export { r as resolveFriendlyStandardHandlerHandleOptions } from '../../shared/server.W91HSRkE.mjs';
3
3
  import '@orpc/client';
4
4
  import '@orpc/shared';
5
5
  import '@standardserver/core';
6
- import '../../shared/server.CrlKQucM.mjs';
6
+ import '../../shared/server.CkButhNT.mjs';
7
7
  import '@orpc/contract';
8
- import '../../shared/server.BwHnWUuN.mjs';
8
+ import '../../shared/server.Dh77P3ii.mjs';
@@ -1,7 +1,7 @@
1
1
  import { Value, Promisable } from '@orpc/shared';
2
2
  import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
3
- import { C as Context } from '../../shared/server.BL22TloH.mjs';
4
- import { b as StandardHandlerHandleOptions, S as StandardHandler } from '../../shared/server.BB_Ik9Ph.mjs';
3
+ import { Context } from '../../index.mjs';
4
+ import { StandardHandlerHandleOptions, StandardHandler } from '../standard/index.mjs';
5
5
  import '@orpc/client';
6
6
  import '@orpc/contract';
7
7
 
@@ -1,7 +1,7 @@
1
1
  import { Value, Promisable } from '@orpc/shared';
2
2
  import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
3
- import { C as Context } from '../../shared/server.BL22TloH.js';
4
- import { b as StandardHandlerHandleOptions, S as StandardHandler } from '../../shared/server.EOHJ3NJr.js';
3
+ import { Context } from '../../index.js';
4
+ import { StandardHandlerHandleOptions, StandardHandler } from '../standard/index.js';
5
5
  import '@orpc/client';
6
6
  import '@orpc/contract';
7
7
 
@@ -1,16 +1,22 @@
1
- import { MaybeOptionalOptions } from '@orpc/shared';
1
+ import { Arrayable, MaybeOptionalOptions } from '@orpc/shared';
2
2
  import { EncodePeerMessageOptions, DecodePeerMessageOptions } from '@standardserver/peer';
3
- import { C as Context } from '../../shared/server.BL22TloH.mjs';
4
- import { S as StandardHandler, a as StandardHandlerOptions } from '../../shared/server.BB_Ik9Ph.mjs';
3
+ import { Context } from '../../index.mjs';
4
+ import { StandardHandler, StandardHandlerOptions } from '../standard/index.mjs';
5
5
  import { StandardPeerRequestHandlerOptions } from '../standard-peer/index.mjs';
6
- import { R as Router } from '../../shared/server.BsNNjG5J.mjs';
7
- import { R as RPCHandlerCodecOptions } from '../../shared/server.B_U9y00a.mjs';
6
+ import { Router } from '../../index.mjs';
7
+ import { RPCHandlerCodecOptions } from '../standard/index.mjs';
8
8
  import '@orpc/client';
9
9
  import '@orpc/contract';
10
10
  import '@standardserver/core';
11
11
 
12
- type WebsocketLike = Pick<WebSocket, 'addEventListener' | 'removeEventListener' | 'send'>;
13
- interface WebsocketHandlerOptions<_T extends Context> {
12
+ /**
13
+ * Supports standard WebSocket instances, Bun ServerWebSocket, "ws" ServerWebSocket,
14
+ * Cloudflare WebSocket Hibernation, and similar implementations.
15
+ */
16
+ type WebSocketLike = {
17
+ send: (data: string | Uint8Array<ArrayBuffer>) => unknown;
18
+ };
19
+ interface WebSocketHandlerOptions<_T extends Context> {
14
20
  /**
15
21
  * Options for encoding peer messages. such as `prefix` for distinguishing messages on the same channel..
16
22
  */
@@ -20,42 +26,52 @@ interface WebsocketHandlerOptions<_T extends Context> {
20
26
  */
21
27
  decodePeerMessage?: DecodePeerMessageOptions | undefined;
22
28
  }
23
- declare class WebsocketHandler<T extends Context> {
29
+ declare class WebSocketHandler<T extends Context> {
24
30
  private readonly handler;
25
31
  private readonly peers;
26
32
  private readonly encodePeerMessageOptions;
27
33
  private readonly decodePeerMessageOptions;
28
- constructor(handler: StandardHandler<T>, options?: NoInfer<WebsocketHandlerOptions<T>>);
34
+ constructor(handler: StandardHandler<T>, options?: NoInfer<WebSocketHandlerOptions<T>>);
29
35
  /**
30
- * Attaches necessary event listeners to a WebSocket to handle incoming messages and peer management.
31
- */
32
- upgrade(ws: WebsocketLike, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): void;
33
- /**
34
- * Handles a single message received from a WebSocket.
36
+ * Handles a single WebSocket message.
37
+ *
38
+ * Message order matters. Call this immediately after receiving a message,
39
+ * before any other async work, to preserve ordering.
35
40
  *
36
- * @warning AVOID calling this method, if `.upgrade()` is used, as `.upgrade()` already sets up necessary event listeners to call this method for incoming messages and manage peer lifecycle.
41
+ * To avoid async Blob reads, configure `ws.binaryType` to return binary data
42
+ * directly (for example, `arraybuffer`).
37
43
  *
38
- * @param ws The WebSocket instance, require consistent instance across messages for proper peer management
39
- * @param data The message data received from the WebSocket, can be string, ArrayBuffer, Blob, ...
44
+ * @param ws The WebSocket instance. Use the same instance for all messages.
45
+ * @param data The received message. Binary data should already be loaded (not a `Blob`).
40
46
  */
41
- message(ws: WebsocketLike, data: string | ArrayBuffer | Blob | Exclude<ConstructorParameters<typeof Blob>[0], undefined>[0][] | Pick<Uint8Array<ArrayBuffer>, 'buffer' | 'byteOffset' | 'byteLength'>, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): Promise<{
47
+ message(ws: WebSocketLike, data: Arrayable<string | ArrayBuffer | Pick<Uint8Array<ArrayBuffer>, 'buffer' | 'byteOffset' | 'byteLength'>>, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): Promise<{
42
48
  matched: boolean;
43
49
  }>;
44
50
  /**
45
- * Called when a websocket is closed, to clean up any associated peer state.
51
+ * Cleans up peer state for a closed WebSocket.
46
52
  *
47
- * @warning AVOID calling this method, if `.upgrade()` is used, as `.upgrade()` already sets up necessary event listeners to call this method for incoming messages and manage peer lifecycle.
53
+ * @param ws The same WebSocket instance passed to `.message()`.
54
+ */
55
+ close(ws: WebSocketLike): Promise<void>;
56
+ /**
57
+ * Attaches message and close event listeners to a WebSocket.
48
58
  *
49
- * @param ws The WebSocket instance to clean up, must be the same instance used in `.message()` calls to properly clean up
59
+ * Prefer this over calling `.message()` and `.close()` manually.
50
60
  */
51
- close(ws: WebsocketLike): Promise<void>;
61
+ upgrade(ws: Pick<WebSocket, 'send' | 'addEventListener' | 'removeEventListener'>, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): void;
52
62
  }
53
63
 
54
- interface RPCHandlerOptions<T extends Context> extends StandardHandlerOptions<T>, RPCHandlerCodecOptions<T>, WebsocketHandlerOptions<T> {
64
+ interface RPCHandlerOptions<T extends Context> extends StandardHandlerOptions<T>, RPCHandlerCodecOptions<T>, WebSocketHandlerOptions<T> {
55
65
  }
56
- declare class RPCHandler<T extends Context> extends WebsocketHandler<T> {
66
+ /**
67
+ * Serves an oRPC router over the RPC protocol on a standard WebSocket
68
+ * connection (Deno, Bun, Cloudflare Durable Objects, and more).
69
+ *
70
+ * @see {@link https://orpc.dev/docs/adapters/websocket | WebSocket Adapters}
71
+ */
72
+ declare class RPCHandler<T extends Context> extends WebSocketHandler<T> {
57
73
  constructor(router: Router<T>, options?: NoInfer<RPCHandlerOptions<T>>);
58
74
  }
59
75
 
60
- export { RPCHandler, WebsocketHandler };
61
- export type { RPCHandlerOptions, WebsocketHandlerOptions, WebsocketLike };
76
+ export { RPCHandler, WebSocketHandler };
77
+ export type { RPCHandlerOptions, WebSocketHandlerOptions, WebSocketLike };
@@ -1,16 +1,22 @@
1
- import { MaybeOptionalOptions } from '@orpc/shared';
1
+ import { Arrayable, MaybeOptionalOptions } from '@orpc/shared';
2
2
  import { EncodePeerMessageOptions, DecodePeerMessageOptions } from '@standardserver/peer';
3
- import { C as Context } from '../../shared/server.BL22TloH.js';
4
- import { S as StandardHandler, a as StandardHandlerOptions } from '../../shared/server.EOHJ3NJr.js';
3
+ import { Context } from '../../index.js';
4
+ import { StandardHandler, StandardHandlerOptions } from '../standard/index.js';
5
5
  import { StandardPeerRequestHandlerOptions } from '../standard-peer/index.js';
6
- import { R as Router } from '../../shared/server.Pa0F03f_.js';
7
- import { R as RPCHandlerCodecOptions } from '../../shared/server.T9F3bzZx.js';
6
+ import { Router } from '../../index.js';
7
+ import { RPCHandlerCodecOptions } from '../standard/index.js';
8
8
  import '@orpc/client';
9
9
  import '@orpc/contract';
10
10
  import '@standardserver/core';
11
11
 
12
- type WebsocketLike = Pick<WebSocket, 'addEventListener' | 'removeEventListener' | 'send'>;
13
- interface WebsocketHandlerOptions<_T extends Context> {
12
+ /**
13
+ * Supports standard WebSocket instances, Bun ServerWebSocket, "ws" ServerWebSocket,
14
+ * Cloudflare WebSocket Hibernation, and similar implementations.
15
+ */
16
+ type WebSocketLike = {
17
+ send: (data: string | Uint8Array<ArrayBuffer>) => unknown;
18
+ };
19
+ interface WebSocketHandlerOptions<_T extends Context> {
14
20
  /**
15
21
  * Options for encoding peer messages. such as `prefix` for distinguishing messages on the same channel..
16
22
  */
@@ -20,42 +26,52 @@ interface WebsocketHandlerOptions<_T extends Context> {
20
26
  */
21
27
  decodePeerMessage?: DecodePeerMessageOptions | undefined;
22
28
  }
23
- declare class WebsocketHandler<T extends Context> {
29
+ declare class WebSocketHandler<T extends Context> {
24
30
  private readonly handler;
25
31
  private readonly peers;
26
32
  private readonly encodePeerMessageOptions;
27
33
  private readonly decodePeerMessageOptions;
28
- constructor(handler: StandardHandler<T>, options?: NoInfer<WebsocketHandlerOptions<T>>);
34
+ constructor(handler: StandardHandler<T>, options?: NoInfer<WebSocketHandlerOptions<T>>);
29
35
  /**
30
- * Attaches necessary event listeners to a WebSocket to handle incoming messages and peer management.
31
- */
32
- upgrade(ws: WebsocketLike, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): void;
33
- /**
34
- * Handles a single message received from a WebSocket.
36
+ * Handles a single WebSocket message.
37
+ *
38
+ * Message order matters. Call this immediately after receiving a message,
39
+ * before any other async work, to preserve ordering.
35
40
  *
36
- * @warning AVOID calling this method, if `.upgrade()` is used, as `.upgrade()` already sets up necessary event listeners to call this method for incoming messages and manage peer lifecycle.
41
+ * To avoid async Blob reads, configure `ws.binaryType` to return binary data
42
+ * directly (for example, `arraybuffer`).
37
43
  *
38
- * @param ws The WebSocket instance, require consistent instance across messages for proper peer management
39
- * @param data The message data received from the WebSocket, can be string, ArrayBuffer, Blob, ...
44
+ * @param ws The WebSocket instance. Use the same instance for all messages.
45
+ * @param data The received message. Binary data should already be loaded (not a `Blob`).
40
46
  */
41
- message(ws: WebsocketLike, data: string | ArrayBuffer | Blob | Exclude<ConstructorParameters<typeof Blob>[0], undefined>[0][] | Pick<Uint8Array<ArrayBuffer>, 'buffer' | 'byteOffset' | 'byteLength'>, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): Promise<{
47
+ message(ws: WebSocketLike, data: Arrayable<string | ArrayBuffer | Pick<Uint8Array<ArrayBuffer>, 'buffer' | 'byteOffset' | 'byteLength'>>, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): Promise<{
42
48
  matched: boolean;
43
49
  }>;
44
50
  /**
45
- * Called when a websocket is closed, to clean up any associated peer state.
51
+ * Cleans up peer state for a closed WebSocket.
46
52
  *
47
- * @warning AVOID calling this method, if `.upgrade()` is used, as `.upgrade()` already sets up necessary event listeners to call this method for incoming messages and manage peer lifecycle.
53
+ * @param ws The same WebSocket instance passed to `.message()`.
54
+ */
55
+ close(ws: WebSocketLike): Promise<void>;
56
+ /**
57
+ * Attaches message and close event listeners to a WebSocket.
48
58
  *
49
- * @param ws The WebSocket instance to clean up, must be the same instance used in `.message()` calls to properly clean up
59
+ * Prefer this over calling `.message()` and `.close()` manually.
50
60
  */
51
- close(ws: WebsocketLike): Promise<void>;
61
+ upgrade(ws: Pick<WebSocket, 'send' | 'addEventListener' | 'removeEventListener'>, ...rest: MaybeOptionalOptions<StandardPeerRequestHandlerOptions<T>>): void;
52
62
  }
53
63
 
54
- interface RPCHandlerOptions<T extends Context> extends StandardHandlerOptions<T>, RPCHandlerCodecOptions<T>, WebsocketHandlerOptions<T> {
64
+ interface RPCHandlerOptions<T extends Context> extends StandardHandlerOptions<T>, RPCHandlerCodecOptions<T>, WebSocketHandlerOptions<T> {
55
65
  }
56
- declare class RPCHandler<T extends Context> extends WebsocketHandler<T> {
66
+ /**
67
+ * Serves an oRPC router over the RPC protocol on a standard WebSocket
68
+ * connection (Deno, Bun, Cloudflare Durable Objects, and more).
69
+ *
70
+ * @see {@link https://orpc.dev/docs/adapters/websocket | WebSocket Adapters}
71
+ */
72
+ declare class RPCHandler<T extends Context> extends WebSocketHandler<T> {
57
73
  constructor(router: Router<T>, options?: NoInfer<RPCHandlerOptions<T>>);
58
74
  }
59
75
 
60
- export { RPCHandler, WebsocketHandler };
61
- export type { RPCHandlerOptions, WebsocketHandlerOptions, WebsocketLike };
76
+ export { RPCHandler, WebSocketHandler };
77
+ export type { RPCHandlerOptions, WebSocketHandlerOptions, WebSocketLike };
@@ -1,14 +1,14 @@
1
- import { toStringOrBytes, resolveMaybeOptionalOptions } from '@orpc/shared';
1
+ import { toStringOrBytes, resolveMaybeOptionalOptions, sequential, loadBytes } from '@orpc/shared';
2
2
  import { ServerPeer, encodePeerMessage, decodePeerMessage, isClientPeerSendMessage } from '@standardserver/peer';
3
3
  import { c as createStandardPeerRequestHandler } from '../../shared/server.CX4vUnDk.mjs';
4
- import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.GDpX6Df8.mjs';
4
+ import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.DpUGXBi2.mjs';
5
5
  import '@orpc/client';
6
6
  import '@standardserver/core';
7
- import '../../shared/server.CrlKQucM.mjs';
7
+ import '../../shared/server.CkButhNT.mjs';
8
8
  import '@orpc/contract';
9
- import '../../shared/server.BwHnWUuN.mjs';
9
+ import '../../shared/server.Dh77P3ii.mjs';
10
10
 
11
- class WebsocketHandler {
11
+ class WebSocketHandler {
12
12
  constructor(handler, options = {}) {
13
13
  this.handler = handler;
14
14
  this.encodePeerMessageOptions = options.encodePeerMessage;
@@ -18,28 +18,26 @@ class WebsocketHandler {
18
18
  encodePeerMessageOptions;
19
19
  decodePeerMessageOptions;
20
20
  /**
21
- * Attaches necessary event listeners to a WebSocket to handle incoming messages and peer management.
22
- */
23
- upgrade(ws, ...rest) {
24
- ws.addEventListener("message", (event) => this.message(ws, event.data, ...rest));
25
- ws.addEventListener("close", () => this.close(ws));
26
- }
27
- /**
28
- * Handles a single message received from a WebSocket.
21
+ * Handles a single WebSocket message.
22
+ *
23
+ * Message order matters. Call this immediately after receiving a message,
24
+ * before any other async work, to preserve ordering.
29
25
  *
30
- * @warning AVOID calling this method, if `.upgrade()` is used, as `.upgrade()` already sets up necessary event listeners to call this method for incoming messages and manage peer lifecycle.
26
+ * To avoid async Blob reads, configure `ws.binaryType` to return binary data
27
+ * directly (for example, `arraybuffer`).
31
28
  *
32
- * @param ws The WebSocket instance, require consistent instance across messages for proper peer management
33
- * @param data The message data received from the WebSocket, can be string, ArrayBuffer, Blob, ...
29
+ * @param ws The WebSocket instance. Use the same instance for all messages.
30
+ * @param data The received message. Binary data should already be loaded (not a `Blob`).
34
31
  */
35
32
  async message(ws, data, ...rest) {
36
33
  let peer = this.peers.get(ws);
37
34
  if (!peer) {
38
35
  this.peers.set(ws, peer = new ServerPeer(async (message) => {
39
- return ws.send(await encodePeerMessage(message, this.encodePeerMessageOptions));
36
+ const encoded2 = await encodePeerMessage(message, this.encodePeerMessageOptions);
37
+ await ws.send(encoded2);
40
38
  }));
41
39
  }
42
- const encoded = await toStringOrBytes(data);
40
+ const encoded = toStringOrBytes(data);
43
41
  const result = decodePeerMessage(encoded, this.decodePeerMessageOptions);
44
42
  if (result.matched && isClientPeerSendMessage(result.message)) {
45
43
  await peer.message(
@@ -50,22 +48,32 @@ class WebsocketHandler {
50
48
  return result;
51
49
  }
52
50
  /**
53
- * Called when a websocket is closed, to clean up any associated peer state.
51
+ * Cleans up peer state for a closed WebSocket.
54
52
  *
55
- * @warning AVOID calling this method, if `.upgrade()` is used, as `.upgrade()` already sets up necessary event listeners to call this method for incoming messages and manage peer lifecycle.
56
- *
57
- * @param ws The WebSocket instance to clean up, must be the same instance used in `.message()` calls to properly clean up
53
+ * @param ws The same WebSocket instance passed to `.message()`.
58
54
  */
59
55
  async close(ws) {
60
56
  const peer = this.peers.get(ws);
61
57
  if (peer) {
62
- await peer.close();
63
58
  this.peers.delete(ws);
59
+ await peer.close();
64
60
  }
65
61
  }
62
+ /**
63
+ * Attaches message and close event listeners to a WebSocket.
64
+ *
65
+ * Prefer this over calling `.message()` and `.close()` manually.
66
+ */
67
+ upgrade(ws, ...rest) {
68
+ ws.addEventListener("message", sequential(async (event) => {
69
+ const data = event.data instanceof Blob ? await loadBytes(event.data) : event.data;
70
+ this.message(ws, data, ...rest);
71
+ }));
72
+ ws.addEventListener("close", () => this.close(ws));
73
+ }
66
74
  }
67
75
 
68
- class RPCHandler extends WebsocketHandler {
76
+ class RPCHandler extends WebSocketHandler {
69
77
  constructor(router, options = {}) {
70
78
  const codec = new RPCHandlerCodec(router, options);
71
79
  const handler = new StandardHandler(codec, options);
@@ -73,4 +81,4 @@ class RPCHandler extends WebsocketHandler {
73
81
  }
74
82
  }
75
83
 
76
- export { RPCHandler, WebsocketHandler };
84
+ export { RPCHandler, WebSocketHandler };
@@ -1,9 +1,9 @@
1
1
  import { AnyORPCError, ClientContext } from '@orpc/client';
2
2
  import { AnySchema, ErrorMap } from '@orpc/contract';
3
3
  import { MaybeOptionalOptions } from '@orpc/shared';
4
- import { C as Context, P as ProcedureClientOptions, a as Procedure, b as ProcedureClient } from '../shared/server.BL22TloH.mjs';
4
+ import { Context, ProcedureClientOptions, Procedure, ProcedureClient } from '../index.mjs';
5
5
 
6
- declare module "../index" {
6
+ declare module '@orpc/server' {
7
7
  interface DecoratedProcedure<TInitialContext extends Context, TInjectedContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError> {
8
8
  callable<TClientContext extends ClientContext>(...rest: MaybeOptionalOptions<ProcedureClientOptions<TInitialContext, TOutputSchema, TErrorMap, TReturnedError, TClientContext>>): Procedure<TInitialContext, TInjectedContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError> & ProcedureClient<TClientContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>;
9
9
  }
@@ -1,9 +1,9 @@
1
1
  import { AnyORPCError, ClientContext } from '@orpc/client';
2
2
  import { AnySchema, ErrorMap } from '@orpc/contract';
3
3
  import { MaybeOptionalOptions } from '@orpc/shared';
4
- import { C as Context, P as ProcedureClientOptions, a as Procedure, b as ProcedureClient } from '../shared/server.BL22TloH.js';
4
+ import { Context, ProcedureClientOptions, Procedure, ProcedureClient } from '../index.js';
5
5
 
6
- declare module "../index" {
6
+ declare module '@orpc/server' {
7
7
  interface DecoratedProcedure<TInitialContext extends Context, TInjectedContext extends Context, TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap, TReturnedError extends AnyORPCError> {
8
8
  callable<TClientContext extends ClientContext>(...rest: MaybeOptionalOptions<ProcedureClientOptions<TInitialContext, TOutputSchema, TErrorMap, TReturnedError, TClientContext>>): Procedure<TInitialContext, TInjectedContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError> & ProcedureClient<TClientContext, TInputSchema, TOutputSchema, TErrorMap, TReturnedError>;
9
9
  }
@@ -1,5 +1,5 @@
1
- import { c as createProcedureClient } from '../shared/server.CrlKQucM.mjs';
2
- import { D as DecoratedProcedure } from '../shared/server.CjOb6ItT.mjs';
1
+ import { c as createProcedureClient } from '../shared/server.CkButhNT.mjs';
2
+ import { D as DecoratedProcedure } from '../shared/server.eCTV8Vpp.mjs';
3
3
  import '@orpc/client';
4
4
  import '@orpc/contract';
5
5
  import '@orpc/shared';