@orpc/standard-server-peer 0.0.0-next.f9e0a4c → 0.0.0-next.f9e5dec

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 CHANGED
@@ -17,6 +17,9 @@
17
17
  <a href="https://discord.gg/TXEbwRBvQn">
18
18
  <img alt="Discord" src="https://img.shields.io/discord/1308966753044398161?color=7389D8&label&logo=discord&logoColor=ffffff" />
19
19
  </a>
20
+ <a href="https://deepwiki.com/unnoq/orpc">
21
+ <img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki">
22
+ </a>
20
23
  </div>
21
24
 
22
25
  <h3 align="center">Typesafe APIs Made Simple 🪄</h3>
@@ -31,7 +34,7 @@
31
34
  - **📘 First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard.
32
35
  - **📝 Contract-First Development**: Optionally define your API contract before implementation.
33
36
  - **🔍 First-Class OpenTelemetry**: Seamlessly integrate with OpenTelemetry for observability.
34
- - **⚙️ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), Pinia Colada, and more.
37
+ - **⚙️ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), SWR, Pinia Colada, and more.
35
38
  - **🚀 Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
36
39
  - **🔠 Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
37
40
  - **🗃️ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more.
@@ -54,6 +57,7 @@ You can find the full documentation [here](https://orpc.unnoq.com).
54
57
  - [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with [NestJS](https://nestjs.com/).
55
58
  - [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
56
59
  - [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query): [TanStack Query](https://tanstack.com/query/latest) integration.
60
+ - [@orpc/experimental-react-swr](https://www.npmjs.com/package/@orpc/experimental-react-swr): [SWR](https://swr.vercel.app/) integration.
57
61
  - [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
58
62
  - [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
59
63
  - [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
package/dist/index.d.mts CHANGED
@@ -1,11 +1,100 @@
1
1
  import { Promisable, AsyncIdQueueCloseOptions as AsyncIdQueueCloseOptions$1, SetSpanErrorOptions, AsyncIteratorClassCleanupFn, AsyncIteratorClass } from '@orpc/shared';
2
- import { StandardRequest, StandardResponse, EventMeta } from '@orpc/standard-server';
2
+ import { StandardRequest, EventMeta, StandardResponse, StandardBody, StandardHeaders } from '@orpc/standard-server';
3
3
 
4
4
  type EncodedMessage = string | ArrayBufferLike | Uint8Array;
5
5
  interface EncodedMessageSendFn {
6
6
  (message: EncodedMessage): Promisable<void>;
7
7
  }
8
8
 
9
+ declare enum MessageType {
10
+ REQUEST = 1,
11
+ RESPONSE = 2,
12
+ EVENT_ITERATOR = 3,
13
+ ABORT_SIGNAL = 4
14
+ }
15
+ type EventIteratorEvent = 'message' | 'error' | 'done';
16
+ interface EventIteratorPayload {
17
+ event: EventIteratorEvent;
18
+ data: unknown;
19
+ meta?: EventMeta;
20
+ }
21
+ interface RequestMessageMap {
22
+ [MessageType.REQUEST]: Omit<StandardRequest, 'signal'>;
23
+ [MessageType.EVENT_ITERATOR]: EventIteratorPayload;
24
+ [MessageType.ABORT_SIGNAL]: void;
25
+ }
26
+ interface ResponseMessageMap {
27
+ [MessageType.RESPONSE]: StandardResponse;
28
+ [MessageType.EVENT_ITERATOR]: EventIteratorPayload;
29
+ [MessageType.ABORT_SIGNAL]: void;
30
+ }
31
+ interface BaseMessageFormat<P = unknown> {
32
+ /**
33
+ * Client-guaranteed unique identifier
34
+ */
35
+ i: string;
36
+ /**
37
+ * @default REQUEST | RESPONSE
38
+ */
39
+ t?: MessageType;
40
+ p: P;
41
+ }
42
+ interface SerializedEventIteratorPayload {
43
+ e: EventIteratorEvent;
44
+ d: unknown;
45
+ m?: EventMeta;
46
+ }
47
+ interface SerializedRequestPayload {
48
+ /**
49
+ * The url of the request
50
+ *
51
+ * might be relative path if origin is `orpc://localhost`
52
+ */
53
+ u: string;
54
+ b: StandardBody;
55
+ /**
56
+ * @default {}
57
+ */
58
+ h?: StandardHeaders;
59
+ /**
60
+ * @default POST
61
+ */
62
+ m?: string;
63
+ }
64
+ interface SerializedResponsePayload {
65
+ /**
66
+ * @default 200
67
+ */
68
+ s?: number;
69
+ /**
70
+ * @default {}
71
+ */
72
+ h?: StandardHeaders;
73
+ b: StandardBody;
74
+ }
75
+ type DecodedMessageUnion<TMap extends RequestMessageMap | ResponseMessageMap> = {
76
+ [K in keyof TMap]: [id: string, type: K, payload: TMap[K]];
77
+ }[keyof TMap];
78
+ type DecodedRequestMessage = DecodedMessageUnion<RequestMessageMap>;
79
+ type DecodedResponseMessage = DecodedMessageUnion<ResponseMessageMap>;
80
+ /**
81
+ * New serialization functions without Blob handling
82
+ */
83
+ declare function serializeRequestMessage<T extends keyof RequestMessageMap>(id: string, type: T, payload: RequestMessageMap[T]): BaseMessageFormat;
84
+ declare function deserializeRequestMessage(message: BaseMessageFormat): DecodedRequestMessage;
85
+ declare function serializeResponseMessage<T extends keyof ResponseMessageMap>(id: string, type: T, payload: ResponseMessageMap[T]): BaseMessageFormat;
86
+ declare function deserializeResponseMessage(message: BaseMessageFormat): DecodedResponseMessage;
87
+ /**
88
+ * Original encode/decode functions now using the new serialize/deserialize functions
89
+ */
90
+ declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: string, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
91
+ declare function decodeRequestMessage(raw: EncodedMessage): Promise<DecodedRequestMessage>;
92
+ declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: string, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
93
+ declare function decodeResponseMessage(raw: EncodedMessage): Promise<DecodedResponseMessage>;
94
+
95
+ interface experimental_RequestMessageSendFn {
96
+ (message: DecodedRequestMessage): Promisable<void>;
97
+ }
9
98
  interface ClientPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
10
99
  /**
11
100
  * Should abort or not?
@@ -15,6 +104,15 @@ interface ClientPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
15
104
  abort?: boolean;
16
105
  }
17
106
  declare class ClientPeer {
107
+ private readonly peer;
108
+ constructor(send: EncodedMessageSendFn);
109
+ get length(): number;
110
+ open(id: string): AbortController;
111
+ request(request: StandardRequest): Promise<StandardResponse>;
112
+ message(raw: EncodedMessage): Promise<void>;
113
+ close(options?: AsyncIdQueueCloseOptions$1): void;
114
+ }
115
+ declare class experimental_ClientPeerWithoutCodec {
18
116
  private readonly idGenerator;
19
117
  /**
20
118
  * Queue of responses sent from server, awaiting consumption
@@ -33,55 +131,25 @@ declare class ClientPeer {
33
131
  */
34
132
  private readonly cleanupFns;
35
133
  private readonly send;
36
- constructor(send: EncodedMessageSendFn);
134
+ constructor(send: experimental_RequestMessageSendFn);
37
135
  get length(): number;
38
136
  open(id: string): AbortController;
39
137
  request(request: StandardRequest): Promise<StandardResponse>;
40
- message(raw: EncodedMessage): Promise<void>;
138
+ message([id, type, payload]: DecodedResponseMessage): Promise<void>;
41
139
  close(options?: AsyncIdQueueCloseOptions$1): void;
42
140
  }
43
141
 
44
- declare enum MessageType {
45
- REQUEST = 1,
46
- RESPONSE = 2,
47
- EVENT_ITERATOR = 3,
48
- ABORT_SIGNAL = 4
49
- }
50
- type EventIteratorEvent = 'message' | 'error' | 'done';
51
- interface EventIteratorPayload {
52
- event: EventIteratorEvent;
53
- data: unknown;
54
- meta?: EventMeta;
55
- }
56
- interface RequestMessageMap {
57
- [MessageType.REQUEST]: Omit<StandardRequest, 'signal'>;
58
- [MessageType.EVENT_ITERATOR]: EventIteratorPayload;
59
- [MessageType.ABORT_SIGNAL]: void;
60
- }
61
- interface ResponseMessageMap {
62
- [MessageType.RESPONSE]: StandardResponse;
63
- [MessageType.EVENT_ITERATOR]: EventIteratorPayload;
64
- [MessageType.ABORT_SIGNAL]: void;
65
- }
66
- type DecodedMessageUnion<TMap extends RequestMessageMap | ResponseMessageMap> = {
67
- [K in keyof TMap]: [id: string, type: K, payload: TMap[K]];
68
- }[keyof TMap];
69
- type DecodedRequestMessage = DecodedMessageUnion<RequestMessageMap>;
70
- type DecodedResponseMessage = DecodedMessageUnion<ResponseMessageMap>;
71
- declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: string, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
72
- declare function decodeRequestMessage(raw: EncodedMessage): Promise<DecodedRequestMessage>;
73
- declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: string, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
74
- declare function decodeResponseMessage(raw: EncodedMessage): Promise<DecodedResponseMessage>;
75
-
76
142
  interface AsyncIdQueueCloseOptions {
77
143
  id?: string;
78
144
  reason?: unknown;
79
145
  }
80
146
  declare class AsyncIdQueue<T> {
81
147
  private readonly openIds;
82
- private readonly items;
83
- private readonly pendingPulls;
148
+ private readonly queues;
149
+ private readonly waiters;
84
150
  get length(): number;
151
+ get waiterIds(): string[];
152
+ hasBufferedItems(id: string): boolean;
85
153
  open(id: string): void;
86
154
  isOpen(id: string): boolean;
87
155
  push(id: string, item: T): void;
@@ -95,6 +163,9 @@ interface ToEventIteratorOptions extends SetSpanErrorOptions {
95
163
  declare function toEventIterator(queue: AsyncIdQueue<EventIteratorPayload>, id: string, cleanup: AsyncIteratorClassCleanupFn, options?: ToEventIteratorOptions): AsyncIteratorClass<unknown>;
96
164
  declare function resolveEventIterator(iterator: AsyncIterator<any>, callback: (payload: EventIteratorPayload) => Promise<'next' | 'abort'>): Promise<void>;
97
165
 
166
+ interface experimental_ResponseMessageSendFn {
167
+ (message: DecodedResponseMessage): Promisable<void>;
168
+ }
98
169
  interface ServerPeerHandleRequestFn {
99
170
  (request: StandardRequest): Promise<StandardResponse>;
100
171
  }
@@ -107,6 +178,21 @@ interface ServerPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
107
178
  abort?: boolean;
108
179
  }
109
180
  declare class ServerPeer {
181
+ private readonly peer;
182
+ constructor(send: EncodedMessageSendFn);
183
+ get length(): number;
184
+ open(id: string): AbortController;
185
+ /**
186
+ * @todo This method will return Promise<void> in the next major version.
187
+ */
188
+ message(raw: EncodedMessage, handleRequest?: ServerPeerHandleRequestFn): Promise<[id: string, StandardRequest | undefined]>;
189
+ /**
190
+ * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
191
+ */
192
+ response(id: string, response: StandardResponse): Promise<void>;
193
+ close({ abort, ...options }?: ServerPeerCloseOptions): void;
194
+ }
195
+ declare class experimental_ServerPeerWithoutCodec {
110
196
  /**
111
197
  * Queue of event iterator messages sent from client, awaiting consumption
112
198
  */
@@ -116,13 +202,13 @@ declare class ServerPeer {
116
202
  */
117
203
  private readonly clientControllers;
118
204
  private readonly send;
119
- constructor(send: EncodedMessageSendFn);
205
+ constructor(send: experimental_ResponseMessageSendFn);
120
206
  get length(): number;
121
207
  open(id: string): AbortController;
122
208
  /**
123
209
  * @todo This method will return Promise<void> in the next major version.
124
210
  */
125
- message(raw: EncodedMessage, handleRequest?: ServerPeerHandleRequestFn): Promise<[id: string, StandardRequest | undefined]>;
211
+ message([id, type, payload]: DecodedRequestMessage, handleRequest?: ServerPeerHandleRequestFn): Promise<[id: string, StandardRequest | undefined]>;
126
212
  /**
127
213
  * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
128
214
  */
@@ -130,5 +216,5 @@ declare class ServerPeer {
130
216
  close({ abort, ...options }?: ServerPeerCloseOptions): void;
131
217
  }
132
218
 
133
- export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, resolveEventIterator, toEventIterator };
134
- export type { ClientPeerCloseOptions, DecodedRequestMessage, DecodedResponseMessage, EncodedMessage, EncodedMessageSendFn, EventIteratorEvent, EventIteratorPayload, RequestMessageMap, ResponseMessageMap, ServerPeerCloseOptions, ServerPeerHandleRequestFn, ToEventIteratorOptions };
219
+ export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, deserializeRequestMessage, deserializeResponseMessage, encodeRequestMessage, encodeResponseMessage, experimental_ClientPeerWithoutCodec, experimental_ServerPeerWithoutCodec, resolveEventIterator, serializeRequestMessage, serializeResponseMessage, toEventIterator };
220
+ export type { BaseMessageFormat, ClientPeerCloseOptions, DecodedMessageUnion, DecodedRequestMessage, DecodedResponseMessage, EncodedMessage, EncodedMessageSendFn, EventIteratorEvent, EventIteratorPayload, RequestMessageMap, ResponseMessageMap, SerializedEventIteratorPayload, SerializedRequestPayload, SerializedResponsePayload, ServerPeerCloseOptions, ServerPeerHandleRequestFn, ToEventIteratorOptions, experimental_RequestMessageSendFn, experimental_ResponseMessageSendFn };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,100 @@
1
1
  import { Promisable, AsyncIdQueueCloseOptions as AsyncIdQueueCloseOptions$1, SetSpanErrorOptions, AsyncIteratorClassCleanupFn, AsyncIteratorClass } from '@orpc/shared';
2
- import { StandardRequest, StandardResponse, EventMeta } from '@orpc/standard-server';
2
+ import { StandardRequest, EventMeta, StandardResponse, StandardBody, StandardHeaders } from '@orpc/standard-server';
3
3
 
4
4
  type EncodedMessage = string | ArrayBufferLike | Uint8Array;
5
5
  interface EncodedMessageSendFn {
6
6
  (message: EncodedMessage): Promisable<void>;
7
7
  }
8
8
 
9
+ declare enum MessageType {
10
+ REQUEST = 1,
11
+ RESPONSE = 2,
12
+ EVENT_ITERATOR = 3,
13
+ ABORT_SIGNAL = 4
14
+ }
15
+ type EventIteratorEvent = 'message' | 'error' | 'done';
16
+ interface EventIteratorPayload {
17
+ event: EventIteratorEvent;
18
+ data: unknown;
19
+ meta?: EventMeta;
20
+ }
21
+ interface RequestMessageMap {
22
+ [MessageType.REQUEST]: Omit<StandardRequest, 'signal'>;
23
+ [MessageType.EVENT_ITERATOR]: EventIteratorPayload;
24
+ [MessageType.ABORT_SIGNAL]: void;
25
+ }
26
+ interface ResponseMessageMap {
27
+ [MessageType.RESPONSE]: StandardResponse;
28
+ [MessageType.EVENT_ITERATOR]: EventIteratorPayload;
29
+ [MessageType.ABORT_SIGNAL]: void;
30
+ }
31
+ interface BaseMessageFormat<P = unknown> {
32
+ /**
33
+ * Client-guaranteed unique identifier
34
+ */
35
+ i: string;
36
+ /**
37
+ * @default REQUEST | RESPONSE
38
+ */
39
+ t?: MessageType;
40
+ p: P;
41
+ }
42
+ interface SerializedEventIteratorPayload {
43
+ e: EventIteratorEvent;
44
+ d: unknown;
45
+ m?: EventMeta;
46
+ }
47
+ interface SerializedRequestPayload {
48
+ /**
49
+ * The url of the request
50
+ *
51
+ * might be relative path if origin is `orpc://localhost`
52
+ */
53
+ u: string;
54
+ b: StandardBody;
55
+ /**
56
+ * @default {}
57
+ */
58
+ h?: StandardHeaders;
59
+ /**
60
+ * @default POST
61
+ */
62
+ m?: string;
63
+ }
64
+ interface SerializedResponsePayload {
65
+ /**
66
+ * @default 200
67
+ */
68
+ s?: number;
69
+ /**
70
+ * @default {}
71
+ */
72
+ h?: StandardHeaders;
73
+ b: StandardBody;
74
+ }
75
+ type DecodedMessageUnion<TMap extends RequestMessageMap | ResponseMessageMap> = {
76
+ [K in keyof TMap]: [id: string, type: K, payload: TMap[K]];
77
+ }[keyof TMap];
78
+ type DecodedRequestMessage = DecodedMessageUnion<RequestMessageMap>;
79
+ type DecodedResponseMessage = DecodedMessageUnion<ResponseMessageMap>;
80
+ /**
81
+ * New serialization functions without Blob handling
82
+ */
83
+ declare function serializeRequestMessage<T extends keyof RequestMessageMap>(id: string, type: T, payload: RequestMessageMap[T]): BaseMessageFormat;
84
+ declare function deserializeRequestMessage(message: BaseMessageFormat): DecodedRequestMessage;
85
+ declare function serializeResponseMessage<T extends keyof ResponseMessageMap>(id: string, type: T, payload: ResponseMessageMap[T]): BaseMessageFormat;
86
+ declare function deserializeResponseMessage(message: BaseMessageFormat): DecodedResponseMessage;
87
+ /**
88
+ * Original encode/decode functions now using the new serialize/deserialize functions
89
+ */
90
+ declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: string, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
91
+ declare function decodeRequestMessage(raw: EncodedMessage): Promise<DecodedRequestMessage>;
92
+ declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: string, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
93
+ declare function decodeResponseMessage(raw: EncodedMessage): Promise<DecodedResponseMessage>;
94
+
95
+ interface experimental_RequestMessageSendFn {
96
+ (message: DecodedRequestMessage): Promisable<void>;
97
+ }
9
98
  interface ClientPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
10
99
  /**
11
100
  * Should abort or not?
@@ -15,6 +104,15 @@ interface ClientPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
15
104
  abort?: boolean;
16
105
  }
17
106
  declare class ClientPeer {
107
+ private readonly peer;
108
+ constructor(send: EncodedMessageSendFn);
109
+ get length(): number;
110
+ open(id: string): AbortController;
111
+ request(request: StandardRequest): Promise<StandardResponse>;
112
+ message(raw: EncodedMessage): Promise<void>;
113
+ close(options?: AsyncIdQueueCloseOptions$1): void;
114
+ }
115
+ declare class experimental_ClientPeerWithoutCodec {
18
116
  private readonly idGenerator;
19
117
  /**
20
118
  * Queue of responses sent from server, awaiting consumption
@@ -33,55 +131,25 @@ declare class ClientPeer {
33
131
  */
34
132
  private readonly cleanupFns;
35
133
  private readonly send;
36
- constructor(send: EncodedMessageSendFn);
134
+ constructor(send: experimental_RequestMessageSendFn);
37
135
  get length(): number;
38
136
  open(id: string): AbortController;
39
137
  request(request: StandardRequest): Promise<StandardResponse>;
40
- message(raw: EncodedMessage): Promise<void>;
138
+ message([id, type, payload]: DecodedResponseMessage): Promise<void>;
41
139
  close(options?: AsyncIdQueueCloseOptions$1): void;
42
140
  }
43
141
 
44
- declare enum MessageType {
45
- REQUEST = 1,
46
- RESPONSE = 2,
47
- EVENT_ITERATOR = 3,
48
- ABORT_SIGNAL = 4
49
- }
50
- type EventIteratorEvent = 'message' | 'error' | 'done';
51
- interface EventIteratorPayload {
52
- event: EventIteratorEvent;
53
- data: unknown;
54
- meta?: EventMeta;
55
- }
56
- interface RequestMessageMap {
57
- [MessageType.REQUEST]: Omit<StandardRequest, 'signal'>;
58
- [MessageType.EVENT_ITERATOR]: EventIteratorPayload;
59
- [MessageType.ABORT_SIGNAL]: void;
60
- }
61
- interface ResponseMessageMap {
62
- [MessageType.RESPONSE]: StandardResponse;
63
- [MessageType.EVENT_ITERATOR]: EventIteratorPayload;
64
- [MessageType.ABORT_SIGNAL]: void;
65
- }
66
- type DecodedMessageUnion<TMap extends RequestMessageMap | ResponseMessageMap> = {
67
- [K in keyof TMap]: [id: string, type: K, payload: TMap[K]];
68
- }[keyof TMap];
69
- type DecodedRequestMessage = DecodedMessageUnion<RequestMessageMap>;
70
- type DecodedResponseMessage = DecodedMessageUnion<ResponseMessageMap>;
71
- declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: string, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
72
- declare function decodeRequestMessage(raw: EncodedMessage): Promise<DecodedRequestMessage>;
73
- declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: string, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
74
- declare function decodeResponseMessage(raw: EncodedMessage): Promise<DecodedResponseMessage>;
75
-
76
142
  interface AsyncIdQueueCloseOptions {
77
143
  id?: string;
78
144
  reason?: unknown;
79
145
  }
80
146
  declare class AsyncIdQueue<T> {
81
147
  private readonly openIds;
82
- private readonly items;
83
- private readonly pendingPulls;
148
+ private readonly queues;
149
+ private readonly waiters;
84
150
  get length(): number;
151
+ get waiterIds(): string[];
152
+ hasBufferedItems(id: string): boolean;
85
153
  open(id: string): void;
86
154
  isOpen(id: string): boolean;
87
155
  push(id: string, item: T): void;
@@ -95,6 +163,9 @@ interface ToEventIteratorOptions extends SetSpanErrorOptions {
95
163
  declare function toEventIterator(queue: AsyncIdQueue<EventIteratorPayload>, id: string, cleanup: AsyncIteratorClassCleanupFn, options?: ToEventIteratorOptions): AsyncIteratorClass<unknown>;
96
164
  declare function resolveEventIterator(iterator: AsyncIterator<any>, callback: (payload: EventIteratorPayload) => Promise<'next' | 'abort'>): Promise<void>;
97
165
 
166
+ interface experimental_ResponseMessageSendFn {
167
+ (message: DecodedResponseMessage): Promisable<void>;
168
+ }
98
169
  interface ServerPeerHandleRequestFn {
99
170
  (request: StandardRequest): Promise<StandardResponse>;
100
171
  }
@@ -107,6 +178,21 @@ interface ServerPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
107
178
  abort?: boolean;
108
179
  }
109
180
  declare class ServerPeer {
181
+ private readonly peer;
182
+ constructor(send: EncodedMessageSendFn);
183
+ get length(): number;
184
+ open(id: string): AbortController;
185
+ /**
186
+ * @todo This method will return Promise<void> in the next major version.
187
+ */
188
+ message(raw: EncodedMessage, handleRequest?: ServerPeerHandleRequestFn): Promise<[id: string, StandardRequest | undefined]>;
189
+ /**
190
+ * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
191
+ */
192
+ response(id: string, response: StandardResponse): Promise<void>;
193
+ close({ abort, ...options }?: ServerPeerCloseOptions): void;
194
+ }
195
+ declare class experimental_ServerPeerWithoutCodec {
110
196
  /**
111
197
  * Queue of event iterator messages sent from client, awaiting consumption
112
198
  */
@@ -116,13 +202,13 @@ declare class ServerPeer {
116
202
  */
117
203
  private readonly clientControllers;
118
204
  private readonly send;
119
- constructor(send: EncodedMessageSendFn);
205
+ constructor(send: experimental_ResponseMessageSendFn);
120
206
  get length(): number;
121
207
  open(id: string): AbortController;
122
208
  /**
123
209
  * @todo This method will return Promise<void> in the next major version.
124
210
  */
125
- message(raw: EncodedMessage, handleRequest?: ServerPeerHandleRequestFn): Promise<[id: string, StandardRequest | undefined]>;
211
+ message([id, type, payload]: DecodedRequestMessage, handleRequest?: ServerPeerHandleRequestFn): Promise<[id: string, StandardRequest | undefined]>;
126
212
  /**
127
213
  * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
128
214
  */
@@ -130,5 +216,5 @@ declare class ServerPeer {
130
216
  close({ abort, ...options }?: ServerPeerCloseOptions): void;
131
217
  }
132
218
 
133
- export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, resolveEventIterator, toEventIterator };
134
- export type { ClientPeerCloseOptions, DecodedRequestMessage, DecodedResponseMessage, EncodedMessage, EncodedMessageSendFn, EventIteratorEvent, EventIteratorPayload, RequestMessageMap, ResponseMessageMap, ServerPeerCloseOptions, ServerPeerHandleRequestFn, ToEventIteratorOptions };
219
+ export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, deserializeRequestMessage, deserializeResponseMessage, encodeRequestMessage, encodeResponseMessage, experimental_ClientPeerWithoutCodec, experimental_ServerPeerWithoutCodec, resolveEventIterator, serializeRequestMessage, serializeResponseMessage, toEventIterator };
220
+ export type { BaseMessageFormat, ClientPeerCloseOptions, DecodedMessageUnion, DecodedRequestMessage, DecodedResponseMessage, EncodedMessage, EncodedMessageSendFn, EventIteratorEvent, EventIteratorPayload, RequestMessageMap, ResponseMessageMap, SerializedEventIteratorPayload, SerializedRequestPayload, SerializedResponsePayload, ServerPeerCloseOptions, ServerPeerHandleRequestFn, ToEventIteratorOptions, experimental_RequestMessageSendFn, experimental_ResponseMessageSendFn };
package/dist/index.mjs CHANGED
@@ -1,6 +1,8 @@
1
1
  import { isAsyncIteratorObject, stringifyJSON, readAsBuffer, AsyncIteratorClass, startSpan, runInSpanContext, isTypescriptObject, setSpanError, runWithSpan, SequentialIdGenerator, AsyncIdQueue, getGlobalOtelConfig, clone, AbortError } from '@orpc/shared';
2
2
  import { generateContentDisposition, flattenHeader, getFilenameFromContentDisposition, withEventMeta, ErrorEvent, getEventMeta, isEventIteratorHeaders, HibernationEventIterator } from '@orpc/standard-server';
3
3
 
4
+ const SHORTABLE_ORIGIN = "orpc://localhost";
5
+ const SHORTABLE_ORIGIN_MATCHER = /^orpc:\/\/localhost\//;
4
6
  var MessageType = /* @__PURE__ */ ((MessageType2) => {
5
7
  MessageType2[MessageType2["REQUEST"] = 1] = "REQUEST";
6
8
  MessageType2[MessageType2["RESPONSE"] = 2] = "RESPONSE";
@@ -8,7 +10,7 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
8
10
  MessageType2[MessageType2["ABORT_SIGNAL"] = 4] = "ABORT_SIGNAL";
9
11
  return MessageType2;
10
12
  })(MessageType || {});
11
- async function encodeRequestMessage(id, type, payload) {
13
+ function serializeRequestMessage(id, type, payload) {
12
14
  if (type === 3 /* EVENT_ITERATOR */) {
13
15
  const eventPayload = payload;
14
16
  const serializedPayload2 = {
@@ -16,35 +18,26 @@ async function encodeRequestMessage(id, type, payload) {
16
18
  d: eventPayload.data,
17
19
  m: eventPayload.meta
18
20
  };
19
- return encodeRawMessage({ i: id, t: type, p: serializedPayload2 });
21
+ return { i: id, t: type, p: serializedPayload2 };
20
22
  }
21
23
  if (type === 4 /* ABORT_SIGNAL */) {
22
- return encodeRawMessage({ i: id, t: type, p: payload });
24
+ return { i: id, t: type, p: payload };
23
25
  }
24
26
  const request = payload;
25
- const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
26
- request.body,
27
- request.headers
28
- );
29
27
  const serializedPayload = {
30
- u: request.url.toString().replace(/^orpc:\//, "/"),
31
- b: processedBody instanceof Blob ? void 0 : processedBody,
32
- h: Object.keys(processedHeaders).length > 0 ? processedHeaders : void 0,
28
+ u: request.url.toString().replace(SHORTABLE_ORIGIN_MATCHER, "/"),
29
+ b: request.body,
30
+ h: Object.keys(request.headers).length > 0 ? request.headers : void 0,
33
31
  m: request.method === "POST" ? void 0 : request.method
34
32
  };
35
- const baseMessage = {
33
+ return {
36
34
  i: id,
37
35
  p: serializedPayload
38
36
  };
39
- if (processedBody instanceof Blob) {
40
- return encodeRawMessage(baseMessage, processedBody);
41
- }
42
- return encodeRawMessage(baseMessage);
43
37
  }
44
- async function decodeRequestMessage(raw) {
45
- const { json: message, buffer } = await decodeRawMessage(raw);
38
+ function deserializeRequestMessage(message) {
46
39
  const id = message.i;
47
- const type = message.t;
40
+ const type = message.t ?? 1 /* REQUEST */;
48
41
  if (type === 3 /* EVENT_ITERATOR */) {
49
42
  const payload2 = message.p;
50
43
  return [id, type, { event: payload2.e, data: payload2.d, meta: payload2.m }];
@@ -53,11 +46,14 @@ async function decodeRequestMessage(raw) {
53
46
  return [id, type, message.p];
54
47
  }
55
48
  const payload = message.p;
56
- const headers = payload.h ?? {};
57
- const body = await deserializeBody(headers, payload.b, buffer);
58
- return [id, 1 /* REQUEST */, { url: new URL(payload.u, "orpc:/"), headers, method: payload.m ?? "POST", body }];
49
+ return [id, 1 /* REQUEST */, {
50
+ url: payload.u.startsWith("/") ? new URL(`${SHORTABLE_ORIGIN}${payload.u}`) : new URL(payload.u),
51
+ headers: payload.h ?? {},
52
+ method: payload.m ?? "POST",
53
+ body: payload.b
54
+ }];
59
55
  }
60
- async function encodeResponseMessage(id, type, payload) {
56
+ function serializeResponseMessage(id, type, payload) {
61
57
  if (type === 3 /* EVENT_ITERATOR */) {
62
58
  const eventPayload = payload;
63
59
  const serializedPayload2 = {
@@ -65,32 +61,23 @@ async function encodeResponseMessage(id, type, payload) {
65
61
  d: eventPayload.data,
66
62
  m: eventPayload.meta
67
63
  };
68
- return encodeRawMessage({ i: id, t: type, p: serializedPayload2 });
64
+ return { i: id, t: type, p: serializedPayload2 };
69
65
  }
70
66
  if (type === 4 /* ABORT_SIGNAL */) {
71
- return encodeRawMessage({ i: id, t: type, p: void 0 });
67
+ return { i: id, t: type, p: void 0 };
72
68
  }
73
69
  const response = payload;
74
- const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
75
- response.body,
76
- response.headers
77
- );
78
70
  const serializedPayload = {
79
71
  s: response.status === 200 ? void 0 : response.status,
80
- h: Object.keys(processedHeaders).length > 0 ? processedHeaders : void 0,
81
- b: processedBody instanceof Blob ? void 0 : processedBody
72
+ h: Object.keys(response.headers).length > 0 ? response.headers : void 0,
73
+ b: response.body
82
74
  };
83
- const baseMessage = {
75
+ return {
84
76
  i: id,
85
77
  p: serializedPayload
86
78
  };
87
- if (processedBody instanceof Blob) {
88
- return encodeRawMessage(baseMessage, processedBody);
89
- }
90
- return encodeRawMessage(baseMessage);
91
79
  }
92
- async function decodeResponseMessage(raw) {
93
- const { json: message, buffer } = await decodeRawMessage(raw);
80
+ function deserializeResponseMessage(message) {
94
81
  const id = message.i;
95
82
  const type = message.t;
96
83
  if (type === 3 /* EVENT_ITERATOR */) {
@@ -101,9 +88,71 @@ async function decodeResponseMessage(raw) {
101
88
  return [id, type, message.p];
102
89
  }
103
90
  const payload = message.p;
104
- const headers = payload.h ?? {};
105
- const body = await deserializeBody(headers, payload.b, buffer);
106
- return [id, 2 /* RESPONSE */, { status: payload.s ?? 200, headers, body }];
91
+ return [id, 2 /* RESPONSE */, {
92
+ status: payload.s ?? 200,
93
+ headers: payload.h ?? {},
94
+ body: payload.b
95
+ }];
96
+ }
97
+ async function encodeRequestMessage(id, type, payload) {
98
+ if (type === 3 /* EVENT_ITERATOR */ || type === 4 /* ABORT_SIGNAL */) {
99
+ return encodeRawMessage(serializeRequestMessage(id, type, payload));
100
+ }
101
+ const request = payload;
102
+ const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
103
+ request.body,
104
+ request.headers
105
+ );
106
+ const modifiedRequest = {
107
+ ...request,
108
+ body: processedBody instanceof Blob ? void 0 : processedBody,
109
+ headers: processedHeaders
110
+ };
111
+ const baseMessage = serializeRequestMessage(id, 1 /* REQUEST */, modifiedRequest);
112
+ if (processedBody instanceof Blob) {
113
+ return encodeRawMessage(baseMessage, processedBody);
114
+ }
115
+ return encodeRawMessage(baseMessage);
116
+ }
117
+ async function decodeRequestMessage(raw) {
118
+ const { json: message, buffer } = await decodeRawMessage(raw);
119
+ const [id, type, payload] = deserializeRequestMessage(message);
120
+ if (type === 3 /* EVENT_ITERATOR */ || type === 4 /* ABORT_SIGNAL */) {
121
+ return [id, type, payload];
122
+ }
123
+ const request = payload;
124
+ const body = await deserializeBody(request.headers, request.body, buffer);
125
+ return [id, type, { ...request, body }];
126
+ }
127
+ async function encodeResponseMessage(id, type, payload) {
128
+ if (type === 3 /* EVENT_ITERATOR */ || type === 4 /* ABORT_SIGNAL */) {
129
+ return encodeRawMessage(serializeResponseMessage(id, type, payload));
130
+ }
131
+ const response = payload;
132
+ const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
133
+ response.body,
134
+ response.headers
135
+ );
136
+ const modifiedResponse = {
137
+ ...response,
138
+ body: processedBody instanceof Blob ? void 0 : processedBody,
139
+ headers: processedHeaders
140
+ };
141
+ const baseMessage = serializeResponseMessage(id, 2 /* RESPONSE */, modifiedResponse);
142
+ if (processedBody instanceof Blob) {
143
+ return encodeRawMessage(baseMessage, processedBody);
144
+ }
145
+ return encodeRawMessage(baseMessage);
146
+ }
147
+ async function decodeResponseMessage(raw) {
148
+ const { json: message, buffer } = await decodeRawMessage(raw);
149
+ const [id, type, payload] = deserializeResponseMessage(message);
150
+ if (type === 3 /* EVENT_ITERATOR */ || type === 4 /* ABORT_SIGNAL */) {
151
+ return [id, type, payload];
152
+ }
153
+ const response = payload;
154
+ const body = await deserializeBody(response.headers, response.body, buffer);
155
+ return [id, type, { ...response, body }];
107
156
  }
108
157
  async function serializeBodyAndHeaders(body, originalHeaders) {
109
158
  const headers = { ...originalHeaders };
@@ -294,6 +343,29 @@ function resolveEventIterator(iterator, callback) {
294
343
  }
295
344
 
296
345
  class ClientPeer {
346
+ peer;
347
+ constructor(send) {
348
+ this.peer = new experimental_ClientPeerWithoutCodec(async ([id, type, payload]) => {
349
+ await send(await encodeRequestMessage(id, type, payload));
350
+ });
351
+ }
352
+ get length() {
353
+ return this.peer.length;
354
+ }
355
+ open(id) {
356
+ return this.peer.open(id);
357
+ }
358
+ async request(request) {
359
+ return this.peer.request(request);
360
+ }
361
+ async message(raw) {
362
+ return this.peer.message(await decodeResponseMessage(raw));
363
+ }
364
+ close(options = {}) {
365
+ return this.peer.close(options);
366
+ }
367
+ }
368
+ class experimental_ClientPeerWithoutCodec {
297
369
  idGenerator = new SequentialIdGenerator();
298
370
  /**
299
371
  * Queue of responses sent from server, awaiting consumption
@@ -313,11 +385,12 @@ class ClientPeer {
313
385
  cleanupFns = /* @__PURE__ */ new Map();
314
386
  send;
315
387
  constructor(send) {
316
- this.send = async (id, ...rest) => encodeRequestMessage(id, ...rest).then(async (raw) => {
388
+ this.send = async (message) => {
389
+ const id = message[0];
317
390
  if (this.serverControllers.has(id)) {
318
- await send(raw);
391
+ await send(message);
319
392
  }
320
- });
393
+ };
321
394
  }
322
395
  get length() {
323
396
  return (+this.responseQueue.length + this.serverEventIteratorQueue.length + this.serverControllers.size + this.cleanupFns.size) / 4;
@@ -347,14 +420,14 @@ class ClientPeer {
347
420
  otelConfig.propagation.inject(otelConfig.context.active(), headers);
348
421
  request = { ...request, headers };
349
422
  }
350
- await this.send(id, MessageType.REQUEST, request);
423
+ await this.send([id, MessageType.REQUEST, request]);
351
424
  if (signal?.aborted) {
352
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
425
+ await this.send([id, MessageType.ABORT_SIGNAL, void 0]);
353
426
  throw signal.reason;
354
427
  }
355
428
  let abortListener;
356
429
  signal?.addEventListener("abort", abortListener = async () => {
357
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
430
+ await this.send([id, MessageType.ABORT_SIGNAL, void 0]);
358
431
  this.close({ id, reason: signal.reason });
359
432
  }, { once: true });
360
433
  this.cleanupFns.get(id)?.push(() => {
@@ -366,7 +439,7 @@ class ClientPeer {
366
439
  if (serverController.signal.aborted) {
367
440
  return "abort";
368
441
  }
369
- await this.send(id, MessageType.EVENT_ITERATOR, payload);
442
+ await this.send([id, MessageType.EVENT_ITERATOR, payload]);
370
443
  return "next";
371
444
  });
372
445
  }
@@ -378,7 +451,7 @@ class ClientPeer {
378
451
  async (reason) => {
379
452
  try {
380
453
  if (reason !== "next") {
381
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
454
+ await this.send([id, MessageType.ABORT_SIGNAL, void 0]);
382
455
  }
383
456
  } finally {
384
457
  this.close({ id });
@@ -400,8 +473,7 @@ class ClientPeer {
400
473
  }
401
474
  );
402
475
  }
403
- async message(raw) {
404
- const [id, type, payload] = await decodeResponseMessage(raw);
476
+ async message([id, type, payload]) {
405
477
  if (type === MessageType.ABORT_SIGNAL) {
406
478
  this.serverControllers.get(id)?.abort();
407
479
  return;
@@ -435,6 +507,35 @@ class ClientPeer {
435
507
  }
436
508
 
437
509
  class ServerPeer {
510
+ peer;
511
+ constructor(send) {
512
+ this.peer = new experimental_ServerPeerWithoutCodec(async ([id, type, payload]) => {
513
+ await send(await encodeResponseMessage(id, type, payload));
514
+ });
515
+ }
516
+ get length() {
517
+ return this.peer.length;
518
+ }
519
+ open(id) {
520
+ return this.peer.open(id);
521
+ }
522
+ /**
523
+ * @todo This method will return Promise<void> in the next major version.
524
+ */
525
+ async message(raw, handleRequest) {
526
+ return this.peer.message(await decodeRequestMessage(raw), handleRequest);
527
+ }
528
+ /**
529
+ * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
530
+ */
531
+ async response(id, response) {
532
+ return this.peer.response(id, response);
533
+ }
534
+ close({ abort = true, ...options } = {}) {
535
+ return this.peer.close({ ...options, abort });
536
+ }
537
+ }
538
+ class experimental_ServerPeerWithoutCodec {
438
539
  /**
439
540
  * Queue of event iterator messages sent from client, awaiting consumption
440
541
  */
@@ -445,11 +546,12 @@ class ServerPeer {
445
546
  clientControllers = /* @__PURE__ */ new Map();
446
547
  send;
447
548
  constructor(send) {
448
- this.send = (id, ...rest) => encodeResponseMessage(id, ...rest).then(async (raw) => {
549
+ this.send = async (message) => {
550
+ const id = message[0];
449
551
  if (this.clientControllers.has(id)) {
450
- await send(raw);
552
+ await send(message);
451
553
  }
452
- });
554
+ };
453
555
  }
454
556
  get length() {
455
557
  return (this.clientEventIteratorQueue.length + this.clientControllers.size) / 2;
@@ -463,8 +565,7 @@ class ServerPeer {
463
565
  /**
464
566
  * @todo This method will return Promise<void> in the next major version.
465
567
  */
466
- async message(raw, handleRequest) {
467
- const [id, type, payload] = await decodeRequestMessage(raw);
568
+ async message([id, type, payload], handleRequest) {
468
569
  if (type === MessageType.ABORT_SIGNAL) {
469
570
  this.close({ id, reason: new AbortError("Client aborted the request") });
470
571
  return [id, void 0];
@@ -485,7 +586,7 @@ class ServerPeer {
485
586
  id,
486
587
  async (reason) => {
487
588
  if (reason !== "next") {
488
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
589
+ await this.send([id, MessageType.ABORT_SIGNAL, void 0]);
489
590
  }
490
591
  },
491
592
  { signal }
@@ -529,7 +630,7 @@ class ServerPeer {
529
630
  return;
530
631
  }
531
632
  try {
532
- await this.send(id, MessageType.RESPONSE, response);
633
+ await this.send([id, MessageType.RESPONSE, response]);
533
634
  if (!signal.aborted && isAsyncIteratorObject(response.body)) {
534
635
  if (response.body instanceof HibernationEventIterator) {
535
636
  response.body.hibernationCallback?.(id);
@@ -539,7 +640,7 @@ class ServerPeer {
539
640
  if (signal.aborted) {
540
641
  return "abort";
541
642
  }
542
- await this.send(id, MessageType.EVENT_ITERATOR, payload);
643
+ await this.send([id, MessageType.EVENT_ITERATOR, payload]);
543
644
  return "next";
544
645
  });
545
646
  }
@@ -566,4 +667,4 @@ class ServerPeer {
566
667
  }
567
668
  }
568
669
 
569
- export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, resolveEventIterator, toEventIterator };
670
+ export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, deserializeRequestMessage, deserializeResponseMessage, encodeRequestMessage, encodeResponseMessage, experimental_ClientPeerWithoutCodec, experimental_ServerPeerWithoutCodec, resolveEventIterator, serializeRequestMessage, serializeResponseMessage, toEventIterator };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/standard-server-peer",
3
3
  "type": "module",
4
- "version": "0.0.0-next.f9e0a4c",
4
+ "version": "0.0.0-next.f9e5dec",
5
5
  "license": "MIT",
6
6
  "homepage": "https://unnoq.com",
7
7
  "repository": {
@@ -23,8 +23,8 @@
23
23
  "dist"
24
24
  ],
25
25
  "dependencies": {
26
- "@orpc/standard-server": "0.0.0-next.f9e0a4c",
27
- "@orpc/shared": "0.0.0-next.f9e0a4c"
26
+ "@orpc/shared": "0.0.0-next.f9e5dec",
27
+ "@orpc/standard-server": "0.0.0-next.f9e5dec"
28
28
  },
29
29
  "scripts": {
30
30
  "build": "unbuild",