@orpc/standard-server-peer 0.0.0 → 1.3.0
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 +1 -0
- package/dist/index.d.mts +61 -47
- package/dist/index.d.ts +61 -47
- package/dist/index.mjs +156 -279
- package/package.json +3 -3
package/README.md
CHANGED
@@ -49,6 +49,7 @@ You can find the full documentation [here](https://orpc.unnoq.com).
|
|
49
49
|
- [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Build your API contract.
|
50
50
|
- [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build your API or implement API contract.
|
51
51
|
- [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API on the client with type-safety.
|
52
|
+
- [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with NestJS.
|
52
53
|
- [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
|
53
54
|
- [@orpc/react-query](https://www.npmjs.com/package/@orpc/react-query): Integration with [React Query](https://tanstack.com/query/latest/docs/framework/react/overview).
|
54
55
|
- [@orpc/vue-query](https://www.npmjs.com/package/@orpc/vue-query): Integration with [Vue Query](https://tanstack.com/query/latest/docs/framework/vue/overview).
|
package/dist/index.d.mts
CHANGED
@@ -1,5 +1,32 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
1
|
+
import { Promisable, AsyncIdQueueCloseOptions as AsyncIdQueueCloseOptions$1, CreateAsyncIteratorObjectCleanupFn } from '@orpc/shared';
|
2
|
+
import { StandardRequest, StandardResponse, EventMeta, StandardHeaders } from '@orpc/standard-server';
|
3
|
+
|
4
|
+
type EncodedMessage = string | ArrayBufferLike | Blob;
|
5
|
+
interface EncodedMessageSendFn {
|
6
|
+
(message: EncodedMessage): Promisable<void>;
|
7
|
+
}
|
8
|
+
|
9
|
+
interface ClientPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
|
10
|
+
/**
|
11
|
+
* Should abort or not?
|
12
|
+
*
|
13
|
+
* @default true
|
14
|
+
*/
|
15
|
+
abort?: boolean;
|
16
|
+
}
|
17
|
+
declare class ClientPeer {
|
18
|
+
private readonly idGenerator;
|
19
|
+
private readonly responseQueue;
|
20
|
+
private readonly serverEventIteratorQueue;
|
21
|
+
private readonly serverControllers;
|
22
|
+
private readonly send;
|
23
|
+
constructor(send: EncodedMessageSendFn);
|
24
|
+
get length(): number;
|
25
|
+
open(id: number): AbortController;
|
26
|
+
request(request: StandardRequest): Promise<StandardResponse>;
|
27
|
+
message(raw: EncodedMessage): Promise<void>;
|
28
|
+
close(options?: AsyncIdQueueCloseOptions$1): void;
|
29
|
+
}
|
3
30
|
|
4
31
|
declare enum MessageType {
|
5
32
|
REQUEST = 1,
|
@@ -7,7 +34,6 @@ declare enum MessageType {
|
|
7
34
|
EVENT_ITERATOR = 3,
|
8
35
|
ABORT_SIGNAL = 4
|
9
36
|
}
|
10
|
-
type RawMessage = string | ArrayBufferLike | Blob;
|
11
37
|
type EventIteratorEvent = 'message' | 'error' | 'done';
|
12
38
|
interface EventIteratorPayload {
|
13
39
|
event: EventIteratorEvent;
|
@@ -29,63 +55,51 @@ type DecodedMessageUnion<TMap extends RequestMessageMap | ResponseMessageMap> =
|
|
29
55
|
}[keyof TMap];
|
30
56
|
type DecodedRequestMessage = DecodedMessageUnion<RequestMessageMap>;
|
31
57
|
type DecodedResponseMessage = DecodedMessageUnion<ResponseMessageMap>;
|
32
|
-
declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: number, type: T, payload: RequestMessageMap[T]): Promise<
|
33
|
-
declare function decodeRequestMessage(raw:
|
34
|
-
declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: number, type: T, payload: ResponseMessageMap[T]): Promise<
|
35
|
-
declare function decodeResponseMessage(raw:
|
58
|
+
declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: number, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
|
59
|
+
declare function decodeRequestMessage(raw: EncodedMessage): Promise<DecodedRequestMessage>;
|
60
|
+
declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: number, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
|
61
|
+
declare function decodeResponseMessage(raw: EncodedMessage): Promise<DecodedResponseMessage>;
|
36
62
|
declare function isEventIteratorHeaders(headers: StandardHeaders): boolean;
|
37
63
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
private readonly clientEventIteratorQueue;
|
42
|
-
private readonly clientSignalQueue;
|
43
|
-
private readonly serverResponseQueue;
|
44
|
-
private readonly serverEventIterator;
|
45
|
-
private readonly serverSignalQueue;
|
46
|
-
constructor(send: (message: RawMessage) => void);
|
47
|
-
request(request: StandardRequest): Promise<StandardResponse>;
|
48
|
-
message(raw: RawMessage): Promise<void>;
|
49
|
-
open(id: number): void;
|
50
|
-
close(id?: number, reason?: any): void;
|
64
|
+
interface AsyncIdQueueCloseOptions {
|
65
|
+
id?: number;
|
66
|
+
reason?: Error;
|
51
67
|
}
|
52
|
-
|
53
|
-
declare abstract class AsyncIdQueue<T> {
|
68
|
+
declare class AsyncIdQueue<T> {
|
54
69
|
private readonly openIds;
|
55
|
-
abstract push(id: number, item: T): void;
|
56
|
-
open(id: number): void;
|
57
|
-
close(id: number): void;
|
58
|
-
closeAll(): void;
|
59
|
-
isOpen(id: number): boolean;
|
60
|
-
assertOpen(id: number): void;
|
61
|
-
}
|
62
|
-
declare class PullableAsyncIdQueue<T> extends AsyncIdQueue<T> {
|
63
70
|
private readonly items;
|
64
71
|
private readonly pendingPulls;
|
72
|
+
get length(): number;
|
73
|
+
open(id: number): void;
|
74
|
+
isOpen(id: number): boolean;
|
65
75
|
push(id: number, item: T): void;
|
66
76
|
pull(id: number): Promise<T>;
|
67
|
-
close(id
|
77
|
+
close({ id, reason }?: AsyncIdQueueCloseOptions): void;
|
78
|
+
assertOpen(id: number): void;
|
68
79
|
}
|
69
80
|
|
70
|
-
declare function toEventIterator(queue:
|
71
|
-
declare function
|
72
|
-
onComplete?: () => void;
|
73
|
-
}): Promise<void>;
|
81
|
+
declare function toEventIterator(queue: AsyncIdQueue<EventIteratorPayload>, id: number, cleanup: CreateAsyncIteratorObjectCleanupFn): AsyncGenerator;
|
82
|
+
declare function resolveEventIterator(iterator: AsyncIterator<any>, callback: (payload: EventIteratorPayload) => Promise<'next' | 'abort'>): Promise<void>;
|
74
83
|
|
84
|
+
interface ServerPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
|
85
|
+
/**
|
86
|
+
* Should abort or not?
|
87
|
+
*
|
88
|
+
* @default true
|
89
|
+
*/
|
90
|
+
abort?: boolean;
|
91
|
+
}
|
75
92
|
declare class ServerPeer {
|
76
|
-
private readonly serverResponseQueue;
|
77
|
-
private readonly serverEventIteratorQueue;
|
78
|
-
private readonly serverSignalQueue;
|
79
93
|
private readonly clientEventIteratorQueue;
|
80
|
-
private readonly
|
81
|
-
|
82
|
-
|
94
|
+
private readonly clientControllers;
|
95
|
+
private readonly send;
|
96
|
+
constructor(send: EncodedMessageSendFn);
|
97
|
+
get length(): number;
|
98
|
+
open(id: number): AbortController;
|
99
|
+
message(raw: EncodedMessage): Promise<[id: number, StandardRequest | undefined]>;
|
83
100
|
response(id: number, response: StandardResponse): Promise<void>;
|
84
|
-
|
85
|
-
close(id?: number, reason?: any): void;
|
101
|
+
close({ abort, ...options }?: ServerPeerCloseOptions): void;
|
86
102
|
}
|
87
103
|
|
88
|
-
|
89
|
-
|
90
|
-
export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, isEventIteratorHeaders, sendEventIterator, toAbortSignal, toEventIterator };
|
91
|
-
export type { DecodedRequestMessage, DecodedResponseMessage, EventIteratorEvent, EventIteratorPayload, RawMessage, RequestMessageMap, ResponseMessageMap };
|
104
|
+
export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, isEventIteratorHeaders, resolveEventIterator, toEventIterator };
|
105
|
+
export type { ClientPeerCloseOptions, DecodedRequestMessage, DecodedResponseMessage, EncodedMessage, EncodedMessageSendFn, EventIteratorEvent, EventIteratorPayload, RequestMessageMap, ResponseMessageMap, ServerPeerCloseOptions };
|
package/dist/index.d.ts
CHANGED
@@ -1,5 +1,32 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
1
|
+
import { Promisable, AsyncIdQueueCloseOptions as AsyncIdQueueCloseOptions$1, CreateAsyncIteratorObjectCleanupFn } from '@orpc/shared';
|
2
|
+
import { StandardRequest, StandardResponse, EventMeta, StandardHeaders } from '@orpc/standard-server';
|
3
|
+
|
4
|
+
type EncodedMessage = string | ArrayBufferLike | Blob;
|
5
|
+
interface EncodedMessageSendFn {
|
6
|
+
(message: EncodedMessage): Promisable<void>;
|
7
|
+
}
|
8
|
+
|
9
|
+
interface ClientPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
|
10
|
+
/**
|
11
|
+
* Should abort or not?
|
12
|
+
*
|
13
|
+
* @default true
|
14
|
+
*/
|
15
|
+
abort?: boolean;
|
16
|
+
}
|
17
|
+
declare class ClientPeer {
|
18
|
+
private readonly idGenerator;
|
19
|
+
private readonly responseQueue;
|
20
|
+
private readonly serverEventIteratorQueue;
|
21
|
+
private readonly serverControllers;
|
22
|
+
private readonly send;
|
23
|
+
constructor(send: EncodedMessageSendFn);
|
24
|
+
get length(): number;
|
25
|
+
open(id: number): AbortController;
|
26
|
+
request(request: StandardRequest): Promise<StandardResponse>;
|
27
|
+
message(raw: EncodedMessage): Promise<void>;
|
28
|
+
close(options?: AsyncIdQueueCloseOptions$1): void;
|
29
|
+
}
|
3
30
|
|
4
31
|
declare enum MessageType {
|
5
32
|
REQUEST = 1,
|
@@ -7,7 +34,6 @@ declare enum MessageType {
|
|
7
34
|
EVENT_ITERATOR = 3,
|
8
35
|
ABORT_SIGNAL = 4
|
9
36
|
}
|
10
|
-
type RawMessage = string | ArrayBufferLike | Blob;
|
11
37
|
type EventIteratorEvent = 'message' | 'error' | 'done';
|
12
38
|
interface EventIteratorPayload {
|
13
39
|
event: EventIteratorEvent;
|
@@ -29,63 +55,51 @@ type DecodedMessageUnion<TMap extends RequestMessageMap | ResponseMessageMap> =
|
|
29
55
|
}[keyof TMap];
|
30
56
|
type DecodedRequestMessage = DecodedMessageUnion<RequestMessageMap>;
|
31
57
|
type DecodedResponseMessage = DecodedMessageUnion<ResponseMessageMap>;
|
32
|
-
declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: number, type: T, payload: RequestMessageMap[T]): Promise<
|
33
|
-
declare function decodeRequestMessage(raw:
|
34
|
-
declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: number, type: T, payload: ResponseMessageMap[T]): Promise<
|
35
|
-
declare function decodeResponseMessage(raw:
|
58
|
+
declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: number, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
|
59
|
+
declare function decodeRequestMessage(raw: EncodedMessage): Promise<DecodedRequestMessage>;
|
60
|
+
declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: number, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
|
61
|
+
declare function decodeResponseMessage(raw: EncodedMessage): Promise<DecodedResponseMessage>;
|
36
62
|
declare function isEventIteratorHeaders(headers: StandardHeaders): boolean;
|
37
63
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
private readonly clientEventIteratorQueue;
|
42
|
-
private readonly clientSignalQueue;
|
43
|
-
private readonly serverResponseQueue;
|
44
|
-
private readonly serverEventIterator;
|
45
|
-
private readonly serverSignalQueue;
|
46
|
-
constructor(send: (message: RawMessage) => void);
|
47
|
-
request(request: StandardRequest): Promise<StandardResponse>;
|
48
|
-
message(raw: RawMessage): Promise<void>;
|
49
|
-
open(id: number): void;
|
50
|
-
close(id?: number, reason?: any): void;
|
64
|
+
interface AsyncIdQueueCloseOptions {
|
65
|
+
id?: number;
|
66
|
+
reason?: Error;
|
51
67
|
}
|
52
|
-
|
53
|
-
declare abstract class AsyncIdQueue<T> {
|
68
|
+
declare class AsyncIdQueue<T> {
|
54
69
|
private readonly openIds;
|
55
|
-
abstract push(id: number, item: T): void;
|
56
|
-
open(id: number): void;
|
57
|
-
close(id: number): void;
|
58
|
-
closeAll(): void;
|
59
|
-
isOpen(id: number): boolean;
|
60
|
-
assertOpen(id: number): void;
|
61
|
-
}
|
62
|
-
declare class PullableAsyncIdQueue<T> extends AsyncIdQueue<T> {
|
63
70
|
private readonly items;
|
64
71
|
private readonly pendingPulls;
|
72
|
+
get length(): number;
|
73
|
+
open(id: number): void;
|
74
|
+
isOpen(id: number): boolean;
|
65
75
|
push(id: number, item: T): void;
|
66
76
|
pull(id: number): Promise<T>;
|
67
|
-
close(id
|
77
|
+
close({ id, reason }?: AsyncIdQueueCloseOptions): void;
|
78
|
+
assertOpen(id: number): void;
|
68
79
|
}
|
69
80
|
|
70
|
-
declare function toEventIterator(queue:
|
71
|
-
declare function
|
72
|
-
onComplete?: () => void;
|
73
|
-
}): Promise<void>;
|
81
|
+
declare function toEventIterator(queue: AsyncIdQueue<EventIteratorPayload>, id: number, cleanup: CreateAsyncIteratorObjectCleanupFn): AsyncGenerator;
|
82
|
+
declare function resolveEventIterator(iterator: AsyncIterator<any>, callback: (payload: EventIteratorPayload) => Promise<'next' | 'abort'>): Promise<void>;
|
74
83
|
|
84
|
+
interface ServerPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
|
85
|
+
/**
|
86
|
+
* Should abort or not?
|
87
|
+
*
|
88
|
+
* @default true
|
89
|
+
*/
|
90
|
+
abort?: boolean;
|
91
|
+
}
|
75
92
|
declare class ServerPeer {
|
76
|
-
private readonly serverResponseQueue;
|
77
|
-
private readonly serverEventIteratorQueue;
|
78
|
-
private readonly serverSignalQueue;
|
79
93
|
private readonly clientEventIteratorQueue;
|
80
|
-
private readonly
|
81
|
-
|
82
|
-
|
94
|
+
private readonly clientControllers;
|
95
|
+
private readonly send;
|
96
|
+
constructor(send: EncodedMessageSendFn);
|
97
|
+
get length(): number;
|
98
|
+
open(id: number): AbortController;
|
99
|
+
message(raw: EncodedMessage): Promise<[id: number, StandardRequest | undefined]>;
|
83
100
|
response(id: number, response: StandardResponse): Promise<void>;
|
84
|
-
|
85
|
-
close(id?: number, reason?: any): void;
|
101
|
+
close({ abort, ...options }?: ServerPeerCloseOptions): void;
|
86
102
|
}
|
87
103
|
|
88
|
-
|
89
|
-
|
90
|
-
export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, isEventIteratorHeaders, sendEventIterator, toAbortSignal, toEventIterator };
|
91
|
-
export type { DecodedRequestMessage, DecodedResponseMessage, EventIteratorEvent, EventIteratorPayload, RawMessage, RequestMessageMap, ResponseMessageMap };
|
104
|
+
export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, isEventIteratorHeaders, resolveEventIterator, toEventIterator };
|
105
|
+
export type { ClientPeerCloseOptions, DecodedRequestMessage, DecodedResponseMessage, EncodedMessage, EncodedMessageSendFn, EventIteratorEvent, EventIteratorPayload, RequestMessageMap, ResponseMessageMap, ServerPeerCloseOptions };
|
package/dist/index.mjs
CHANGED
@@ -1,88 +1,5 @@
|
|
1
|
-
import {
|
2
|
-
import { getFilenameFromContentDisposition, generateContentDisposition, withEventMeta, ErrorEvent, getEventMeta } from '@orpc/standard-server';
|
3
|
-
|
4
|
-
class AsyncIdQueue {
|
5
|
-
openIds = /* @__PURE__ */ new Set();
|
6
|
-
open(id) {
|
7
|
-
this.openIds.add(id);
|
8
|
-
}
|
9
|
-
close(id) {
|
10
|
-
this.openIds.delete(id);
|
11
|
-
}
|
12
|
-
closeAll() {
|
13
|
-
this.openIds.forEach((id) => this.close(id));
|
14
|
-
}
|
15
|
-
isOpen(id) {
|
16
|
-
return this.openIds.has(id);
|
17
|
-
}
|
18
|
-
assertOpen(id) {
|
19
|
-
if (!this.isOpen(id)) {
|
20
|
-
throw new Error(`[AsyncIdQueue] Cannot access queue[${id}] because it is not open.`);
|
21
|
-
}
|
22
|
-
}
|
23
|
-
}
|
24
|
-
class PullableAsyncIdQueue extends AsyncIdQueue {
|
25
|
-
items = /* @__PURE__ */ new Map();
|
26
|
-
pendingPulls = /* @__PURE__ */ new Map();
|
27
|
-
push(id, item) {
|
28
|
-
this.assertOpen(id);
|
29
|
-
const pending = this.pendingPulls.get(id);
|
30
|
-
if (pending?.length) {
|
31
|
-
pending.shift()[0](item);
|
32
|
-
if (pending.length === 0) {
|
33
|
-
this.pendingPulls.delete(id);
|
34
|
-
}
|
35
|
-
} else {
|
36
|
-
const items = this.items.get(id);
|
37
|
-
if (items) {
|
38
|
-
items.push(item);
|
39
|
-
} else {
|
40
|
-
this.items.set(id, [item]);
|
41
|
-
}
|
42
|
-
}
|
43
|
-
}
|
44
|
-
async pull(id) {
|
45
|
-
this.assertOpen(id);
|
46
|
-
const items = this.items.get(id);
|
47
|
-
if (items?.length) {
|
48
|
-
const item = items.shift();
|
49
|
-
if (items.length === 0) {
|
50
|
-
this.items.delete(id);
|
51
|
-
}
|
52
|
-
return item;
|
53
|
-
}
|
54
|
-
return new Promise((resolve, reject) => {
|
55
|
-
const waitingPulls = this.pendingPulls.get(id);
|
56
|
-
const pending = [resolve, reject];
|
57
|
-
if (waitingPulls) {
|
58
|
-
waitingPulls.push(pending);
|
59
|
-
} else {
|
60
|
-
this.pendingPulls.set(id, [pending]);
|
61
|
-
}
|
62
|
-
});
|
63
|
-
}
|
64
|
-
close(id, reason) {
|
65
|
-
const pendingPulls = this.pendingPulls.get(id);
|
66
|
-
if (pendingPulls) {
|
67
|
-
pendingPulls.forEach(([, reject]) => {
|
68
|
-
reject(reason ?? new Error(`[PullableAsyncIdQueue] Queue[${id}] was closed while waiting for pulling.`));
|
69
|
-
});
|
70
|
-
this.pendingPulls.delete(id);
|
71
|
-
}
|
72
|
-
super.close(id);
|
73
|
-
this.items.delete(id);
|
74
|
-
}
|
75
|
-
}
|
76
|
-
class ConsumableAsyncIdQueue extends AsyncIdQueue {
|
77
|
-
constructor(consume) {
|
78
|
-
super();
|
79
|
-
this.consume = consume;
|
80
|
-
}
|
81
|
-
push(id, item) {
|
82
|
-
this.assertOpen(id);
|
83
|
-
this.consume(id, item);
|
84
|
-
}
|
85
|
-
}
|
1
|
+
import { isAsyncIteratorObject, stringifyJSON, createAsyncIteratorObject, isTypescriptObject, SequentialIdGenerator, AsyncIdQueue } from '@orpc/shared';
|
2
|
+
import { flattenHeader, getFilenameFromContentDisposition, generateContentDisposition, withEventMeta, ErrorEvent, getEventMeta } from '@orpc/standard-server';
|
86
3
|
|
87
4
|
var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
88
5
|
MessageType2[MessageType2["REQUEST"] = 1] = "REQUEST";
|
@@ -138,9 +55,9 @@ async function decodeRequestMessage(raw) {
|
|
138
55
|
const payload = message.p;
|
139
56
|
const headers = payload.h ?? {};
|
140
57
|
let body = payload.b;
|
141
|
-
const contentType =
|
58
|
+
const contentType = flattenHeader(headers["content-type"]);
|
142
59
|
if (blobData) {
|
143
|
-
const contentDisposition =
|
60
|
+
const contentDisposition = flattenHeader(headers["content-disposition"]);
|
144
61
|
if (contentDisposition === void 0 && contentType?.startsWith("multipart/form-data")) {
|
145
62
|
const tempRes = new Response(blobData, { headers: { "content-type": contentType } });
|
146
63
|
body = await tempRes.formData();
|
@@ -199,9 +116,9 @@ async function decodeResponseMessage(raw) {
|
|
199
116
|
const payload = message.p;
|
200
117
|
const headers = payload.h ?? {};
|
201
118
|
let body = payload.b;
|
202
|
-
const contentType =
|
119
|
+
const contentType = flattenHeader(headers["content-type"]);
|
203
120
|
if (blobData) {
|
204
|
-
const contentDisposition =
|
121
|
+
const contentDisposition = flattenHeader(headers["content-disposition"]);
|
205
122
|
if (contentDisposition === void 0 && contentType?.startsWith("multipart/form-data")) {
|
206
123
|
const tempRes = new Response(blobData, { headers: { "content-type": contentType } });
|
207
124
|
body = await tempRes.formData();
|
@@ -228,8 +145,8 @@ async function prepareBodyAndHeadersForSerialization(body, originalHeaders) {
|
|
228
145
|
}
|
229
146
|
if (body instanceof FormData) {
|
230
147
|
const tempRes = new Response(body);
|
231
|
-
const formDataBlob = await tempRes.blob();
|
232
148
|
headers["content-type"] = tempRes.headers.get("content-type");
|
149
|
+
const formDataBlob = await tempRes.blob();
|
233
150
|
return { body: formDataBlob, headers };
|
234
151
|
}
|
235
152
|
if (body instanceof URLSearchParams) {
|
@@ -243,7 +160,7 @@ async function prepareBodyAndHeadersForSerialization(body, originalHeaders) {
|
|
243
160
|
return { body, headers };
|
244
161
|
}
|
245
162
|
function isEventIteratorHeaders(headers) {
|
246
|
-
return Boolean(
|
163
|
+
return Boolean(flattenHeader(headers["content-type"])?.startsWith("text/event-stream") && headers["content-disposition"] === void 0);
|
247
164
|
}
|
248
165
|
const JSON_AND_BINARY_DELIMITER = 255;
|
249
166
|
async function encodeRawMessage(data, blobData) {
|
@@ -275,7 +192,7 @@ async function decodeRawMessage(raw) {
|
|
275
192
|
};
|
276
193
|
}
|
277
194
|
|
278
|
-
function toEventIterator(queue, id,
|
195
|
+
function toEventIterator(queue, id, cleanup) {
|
279
196
|
return createAsyncIteratorObject(async () => {
|
280
197
|
const item = await queue.pull(id);
|
281
198
|
switch (item.event) {
|
@@ -303,216 +220,174 @@ function toEventIterator(queue, id, options = {}) {
|
|
303
220
|
return { value: data, done: true };
|
304
221
|
}
|
305
222
|
}
|
306
|
-
},
|
223
|
+
}, cleanup);
|
307
224
|
}
|
308
|
-
async function
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
if (!queue.isOpen(id)) {
|
316
|
-
if (!done) {
|
317
|
-
isInternal = false;
|
318
|
-
await iterator.return?.();
|
319
|
-
isInternal = true;
|
225
|
+
async function resolveEventIterator(iterator, callback) {
|
226
|
+
while (true) {
|
227
|
+
const payload = await (async () => {
|
228
|
+
try {
|
229
|
+
const { value, done } = await iterator.next();
|
230
|
+
if (done) {
|
231
|
+
return { event: "done", data: value, meta: getEventMeta(value) };
|
320
232
|
}
|
233
|
+
return { event: "message", data: value, meta: getEventMeta(value) };
|
234
|
+
} catch (err) {
|
235
|
+
return {
|
236
|
+
meta: getEventMeta(err),
|
237
|
+
event: "error",
|
238
|
+
data: err instanceof ErrorEvent ? err.data : void 0
|
239
|
+
};
|
240
|
+
}
|
241
|
+
})();
|
242
|
+
try {
|
243
|
+
const direction = await callback(payload);
|
244
|
+
if (payload.event === "done" || payload.event === "error") {
|
321
245
|
return;
|
322
246
|
}
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
if (done) {
|
247
|
+
if (direction === "abort") {
|
248
|
+
try {
|
249
|
+
await iterator.return?.();
|
250
|
+
} catch {
|
251
|
+
}
|
329
252
|
return;
|
330
253
|
}
|
331
|
-
}
|
332
|
-
} catch (err) {
|
333
|
-
let currentError = err;
|
334
|
-
if (isInternal) {
|
254
|
+
} catch (err) {
|
335
255
|
try {
|
336
|
-
await iterator.
|
337
|
-
} catch
|
338
|
-
currentError = err2;
|
256
|
+
await iterator.return?.();
|
257
|
+
} catch {
|
339
258
|
}
|
259
|
+
throw err;
|
340
260
|
}
|
341
|
-
if (queue.isOpen(id)) {
|
342
|
-
queue.push(id, {
|
343
|
-
meta: getEventMeta(currentError),
|
344
|
-
event: "error",
|
345
|
-
data: currentError instanceof ErrorEvent ? currentError.data : void 0
|
346
|
-
});
|
347
|
-
}
|
348
|
-
} finally {
|
349
|
-
options.onComplete?.();
|
350
261
|
}
|
351
262
|
}
|
352
263
|
|
353
|
-
function toAbortSignal(queue, id) {
|
354
|
-
const controller = new AbortController();
|
355
|
-
queue.pull(id).then(() => {
|
356
|
-
controller.abort();
|
357
|
-
}).catch(() => {
|
358
|
-
});
|
359
|
-
return controller.signal;
|
360
|
-
}
|
361
|
-
|
362
264
|
class ClientPeer {
|
363
265
|
idGenerator = new SequentialIdGenerator();
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
serverEventIterator = new PullableAsyncIdQueue();
|
369
|
-
serverSignalQueue = new PullableAsyncIdQueue();
|
266
|
+
responseQueue = new AsyncIdQueue();
|
267
|
+
serverEventIteratorQueue = new AsyncIdQueue();
|
268
|
+
serverControllers = /* @__PURE__ */ new Map();
|
269
|
+
send;
|
370
270
|
constructor(send) {
|
371
|
-
this.
|
372
|
-
|
373
|
-
send(raw);
|
374
|
-
|
375
|
-
if (signal.aborted) {
|
376
|
-
this.clientSignalQueue.push(id);
|
377
|
-
this.close(id, signal.reason);
|
378
|
-
}
|
379
|
-
signal.addEventListener("abort", () => {
|
380
|
-
this.clientSignalQueue.push(id);
|
381
|
-
this.close(id, signal.reason);
|
382
|
-
}, { once: true });
|
383
|
-
}
|
384
|
-
if (isAsyncIteratorObject(request.body)) {
|
385
|
-
sendEventIterator(this.clientEventIteratorQueue, id, request.body);
|
386
|
-
const serverSignal = toAbortSignal(this.serverSignalQueue, id);
|
387
|
-
serverSignal.addEventListener("abort", () => {
|
388
|
-
this.clientEventIteratorQueue.close(id);
|
389
|
-
}, { once: true });
|
390
|
-
}
|
391
|
-
}).catch((err) => {
|
392
|
-
this.close(id, err);
|
393
|
-
});
|
394
|
-
});
|
395
|
-
this.clientEventIteratorQueue = new ConsumableAsyncIdQueue((id, payload) => {
|
396
|
-
encodeRequestMessage(id, MessageType.EVENT_ITERATOR, payload).then(send).catch((err) => {
|
397
|
-
this.close(id, err);
|
398
|
-
});
|
399
|
-
});
|
400
|
-
this.clientSignalQueue = new ConsumableAsyncIdQueue((id, payload) => {
|
401
|
-
encodeRequestMessage(id, MessageType.ABORT_SIGNAL, payload).then(send).catch((err) => {
|
402
|
-
this.close(id, err);
|
403
|
-
});
|
271
|
+
this.send = async (id, ...rest) => encodeRequestMessage(id, ...rest).then(async (raw) => {
|
272
|
+
if (this.serverControllers.has(id)) {
|
273
|
+
await send(raw);
|
274
|
+
}
|
404
275
|
});
|
405
276
|
}
|
277
|
+
get length() {
|
278
|
+
return (+this.responseQueue.length + this.serverEventIteratorQueue.length + this.serverControllers.size) / 3;
|
279
|
+
}
|
280
|
+
open(id) {
|
281
|
+
this.serverEventIteratorQueue.open(id);
|
282
|
+
this.responseQueue.open(id);
|
283
|
+
const controller = new AbortController();
|
284
|
+
this.serverControllers.set(id, controller);
|
285
|
+
return controller;
|
286
|
+
}
|
406
287
|
async request(request) {
|
407
288
|
const signal = request.signal;
|
408
289
|
if (signal?.aborted) {
|
409
290
|
throw signal.reason;
|
410
291
|
}
|
411
292
|
const id = this.idGenerator.generate();
|
412
|
-
this.open(id);
|
413
|
-
this.clientRequestQueue.push(id, request);
|
293
|
+
const serverController = this.open(id);
|
414
294
|
return new Promise((resolve, reject) => {
|
415
|
-
this.
|
295
|
+
this.send(id, MessageType.REQUEST, request).then(async () => {
|
296
|
+
if (signal?.aborted) {
|
297
|
+
await this.send(id, MessageType.ABORT_SIGNAL, void 0);
|
298
|
+
this.close({ id, reason: signal.reason });
|
299
|
+
return;
|
300
|
+
}
|
301
|
+
signal?.addEventListener("abort", async () => {
|
302
|
+
await this.send(id, MessageType.ABORT_SIGNAL, void 0);
|
303
|
+
this.close({ id, reason: signal.reason });
|
304
|
+
}, { once: true });
|
305
|
+
if (isAsyncIteratorObject(request.body)) {
|
306
|
+
await resolveEventIterator(request.body, async (payload) => {
|
307
|
+
if (serverController.signal.aborted) {
|
308
|
+
return "abort";
|
309
|
+
}
|
310
|
+
await this.send(id, MessageType.EVENT_ITERATOR, payload);
|
311
|
+
return "next";
|
312
|
+
});
|
313
|
+
}
|
314
|
+
}).catch((err) => {
|
315
|
+
this.close({ id, reason: err });
|
316
|
+
reject(err);
|
317
|
+
});
|
318
|
+
this.responseQueue.pull(id).then(resolve).catch(reject);
|
416
319
|
});
|
417
320
|
}
|
418
321
|
async message(raw) {
|
419
322
|
const [id, type, payload] = await decodeResponseMessage(raw);
|
323
|
+
if (type === MessageType.ABORT_SIGNAL) {
|
324
|
+
this.serverControllers.get(id)?.abort();
|
325
|
+
return;
|
326
|
+
}
|
420
327
|
if (type === MessageType.EVENT_ITERATOR) {
|
421
|
-
if (this.
|
422
|
-
this.
|
328
|
+
if (this.serverEventIteratorQueue.isOpen(id)) {
|
329
|
+
this.serverEventIteratorQueue.push(id, payload);
|
423
330
|
}
|
424
331
|
return;
|
425
332
|
}
|
426
|
-
if (
|
427
|
-
if (this.serverSignalQueue.isOpen(id)) {
|
428
|
-
this.serverSignalQueue.push(id, payload);
|
429
|
-
}
|
333
|
+
if (!this.responseQueue.isOpen(id)) {
|
430
334
|
return;
|
431
335
|
}
|
432
336
|
if (isEventIteratorHeaders(payload.headers)) {
|
433
|
-
this.
|
337
|
+
this.responseQueue.push(id, {
|
434
338
|
...payload,
|
435
|
-
body: toEventIterator(this.
|
436
|
-
|
339
|
+
body: toEventIterator(this.serverEventIteratorQueue, id, async (reason) => {
|
340
|
+
try {
|
437
341
|
if (reason !== "next") {
|
438
|
-
this.
|
342
|
+
await this.send(id, MessageType.ABORT_SIGNAL, void 0);
|
439
343
|
}
|
440
|
-
|
344
|
+
} finally {
|
345
|
+
this.close({ id });
|
441
346
|
}
|
442
347
|
})
|
443
348
|
});
|
444
349
|
} else {
|
445
|
-
this.
|
446
|
-
this.close(id);
|
350
|
+
this.responseQueue.push(id, payload);
|
351
|
+
this.close({ id });
|
447
352
|
}
|
448
353
|
}
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
this.serverSignalQueue.open(id);
|
454
|
-
this.serverEventIterator.open(id);
|
455
|
-
this.serverResponseQueue.open(id);
|
456
|
-
}
|
457
|
-
close(id, reason) {
|
458
|
-
if (id !== void 0) {
|
459
|
-
this.clientRequestQueue.close(id);
|
460
|
-
this.clientEventIteratorQueue.close(id);
|
461
|
-
this.clientSignalQueue.close(id);
|
462
|
-
this.serverResponseQueue.close(id, reason);
|
463
|
-
this.serverEventIterator.close(id, reason);
|
464
|
-
this.serverResponseQueue.close(id, reason);
|
354
|
+
close(options = {}) {
|
355
|
+
if (options.id !== void 0) {
|
356
|
+
this.serverControllers.get(options.id)?.abort(options.reason);
|
357
|
+
this.serverControllers.delete(options.id);
|
465
358
|
} else {
|
466
|
-
this.
|
467
|
-
this.
|
468
|
-
this.clientSignalQueue.closeAll();
|
469
|
-
this.serverResponseQueue.closeAll();
|
470
|
-
this.serverEventIterator.closeAll();
|
471
|
-
this.serverResponseQueue.closeAll();
|
359
|
+
this.serverControllers.forEach((c) => c.abort(options.reason));
|
360
|
+
this.serverControllers.clear();
|
472
361
|
}
|
362
|
+
this.responseQueue.close(options);
|
363
|
+
this.serverEventIteratorQueue.close(options);
|
473
364
|
}
|
474
365
|
}
|
475
366
|
|
476
367
|
class ServerPeer {
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
clientEventIteratorQueue = new PullableAsyncIdQueue$1();
|
481
|
-
clientSignalQueue = new PullableAsyncIdQueue$1();
|
368
|
+
clientEventIteratorQueue = new AsyncIdQueue();
|
369
|
+
clientControllers = /* @__PURE__ */ new Map();
|
370
|
+
send;
|
482
371
|
constructor(send) {
|
483
|
-
this.
|
484
|
-
|
485
|
-
send(raw);
|
486
|
-
|
487
|
-
await sendEventIterator(this.serverEventIteratorQueue, id, response.body, {
|
488
|
-
onComplete: () => {
|
489
|
-
this.close(id);
|
490
|
-
}
|
491
|
-
});
|
492
|
-
} else {
|
493
|
-
this.close(id);
|
494
|
-
}
|
495
|
-
}).catch((err) => {
|
496
|
-
this.close(id, err);
|
497
|
-
});
|
498
|
-
});
|
499
|
-
this.serverEventIteratorQueue = new ConsumableAsyncIdQueue$1((id, payload) => {
|
500
|
-
encodeResponseMessage(id, MessageType.EVENT_ITERATOR, payload).then(send).catch((err) => {
|
501
|
-
this.close(id, err);
|
502
|
-
});
|
503
|
-
});
|
504
|
-
this.serverSignalQueue = new ConsumableAsyncIdQueue$1((id, payload) => {
|
505
|
-
encodeResponseMessage(id, MessageType.ABORT_SIGNAL, payload).then(send).catch((err) => {
|
506
|
-
this.close(id, err);
|
507
|
-
});
|
372
|
+
this.send = (id, ...rest) => encodeResponseMessage(id, ...rest).then(async (raw) => {
|
373
|
+
if (this.clientControllers.has(id)) {
|
374
|
+
await send(raw);
|
375
|
+
}
|
508
376
|
});
|
509
377
|
}
|
378
|
+
get length() {
|
379
|
+
return (this.clientEventIteratorQueue.length + this.clientControllers.size) / 2;
|
380
|
+
}
|
381
|
+
open(id) {
|
382
|
+
this.clientEventIteratorQueue.open(id);
|
383
|
+
const controller = new AbortController();
|
384
|
+
this.clientControllers.set(id, controller);
|
385
|
+
return controller;
|
386
|
+
}
|
510
387
|
async message(raw) {
|
511
388
|
const [id, type, payload] = await decodeRequestMessage(raw);
|
512
389
|
if (type === MessageType.ABORT_SIGNAL) {
|
513
|
-
|
514
|
-
this.clientSignalQueue.push(id, payload);
|
515
|
-
}
|
390
|
+
this.close({ id });
|
516
391
|
return [id, void 0];
|
517
392
|
}
|
518
393
|
if (type === MessageType.EVENT_ITERATOR) {
|
@@ -521,51 +396,53 @@ class ServerPeer {
|
|
521
396
|
}
|
522
397
|
return [id, void 0];
|
523
398
|
}
|
524
|
-
this.open(id);
|
525
|
-
const clientSignal = toAbortSignal(this.clientSignalQueue, id);
|
526
|
-
clientSignal.addEventListener("abort", () => {
|
527
|
-
this.close(id, clientSignal.reason);
|
528
|
-
}, { once: true });
|
399
|
+
const clientController = this.open(id);
|
529
400
|
const request = {
|
530
401
|
...payload,
|
531
|
-
signal:
|
532
|
-
body: isEventIteratorHeaders(payload.headers) ? toEventIterator(this.clientEventIteratorQueue, id, {
|
533
|
-
|
534
|
-
|
535
|
-
this.serverSignalQueue.push(id);
|
536
|
-
}
|
402
|
+
signal: clientController.signal,
|
403
|
+
body: isEventIteratorHeaders(payload.headers) ? toEventIterator(this.clientEventIteratorQueue, id, async (reason) => {
|
404
|
+
if (reason !== "next") {
|
405
|
+
await this.send(id, MessageType.ABORT_SIGNAL, void 0);
|
537
406
|
}
|
538
407
|
}) : payload.body
|
539
408
|
};
|
540
409
|
return [id, request];
|
541
410
|
}
|
542
411
|
async response(id, response) {
|
543
|
-
|
544
|
-
|
412
|
+
const signal = this.clientControllers.get(id)?.signal;
|
413
|
+
if (!signal || signal.aborted) {
|
414
|
+
return;
|
545
415
|
}
|
416
|
+
await this.send(id, MessageType.RESPONSE, response).then(async () => {
|
417
|
+
if (!signal.aborted && isAsyncIteratorObject(response.body)) {
|
418
|
+
await resolveEventIterator(response.body, async (payload) => {
|
419
|
+
if (signal.aborted) {
|
420
|
+
return "abort";
|
421
|
+
}
|
422
|
+
await this.send(id, MessageType.EVENT_ITERATOR, payload);
|
423
|
+
return "next";
|
424
|
+
});
|
425
|
+
}
|
426
|
+
this.close({ id, abort: false });
|
427
|
+
}).catch((reason) => {
|
428
|
+
this.close({ id, reason, abort: false });
|
429
|
+
throw reason;
|
430
|
+
});
|
546
431
|
}
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
}
|
554
|
-
close(id, reason) {
|
555
|
-
if (id !== void 0) {
|
556
|
-
this.serverResponseQueue.close(id);
|
557
|
-
this.serverEventIteratorQueue.close(id);
|
558
|
-
this.serverResponseQueue.close(id);
|
559
|
-
this.clientEventIteratorQueue.close(id, reason);
|
560
|
-
this.clientSignalQueue.close(id, reason);
|
432
|
+
close({ abort = true, ...options } = {}) {
|
433
|
+
if (options.id === void 0) {
|
434
|
+
if (abort) {
|
435
|
+
this.clientControllers.forEach((c) => c.abort());
|
436
|
+
}
|
437
|
+
this.clientControllers.clear();
|
561
438
|
} else {
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
this.
|
566
|
-
this.clientSignalQueue.closeAll();
|
439
|
+
if (abort) {
|
440
|
+
this.clientControllers.get(options.id)?.abort();
|
441
|
+
}
|
442
|
+
this.clientControllers.delete(options.id);
|
567
443
|
}
|
444
|
+
this.clientEventIteratorQueue.close(options);
|
568
445
|
}
|
569
446
|
}
|
570
447
|
|
571
|
-
export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, isEventIteratorHeaders,
|
448
|
+
export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, isEventIteratorHeaders, resolveEventIterator, toEventIterator };
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@orpc/standard-server-peer",
|
3
3
|
"type": "module",
|
4
|
-
"version": "
|
4
|
+
"version": "1.3.0",
|
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/shared": "1.
|
27
|
-
"@orpc/standard-server": "1.
|
26
|
+
"@orpc/shared": "1.3.0",
|
27
|
+
"@orpc/standard-server": "1.3.0"
|
28
28
|
},
|
29
29
|
"scripts": {
|
30
30
|
"build": "unbuild",
|