@orpc/standard-server-peer 0.0.0-next.fa8d145 → 0.0.0-next.fc1437c

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>
@@ -30,7 +33,8 @@
30
33
  - **🔗 End-to-End Type Safety**: Ensure type-safe inputs, outputs, and errors from client to server.
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
- - **⚙️ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte), Pinia Colada, and more.
36
+ - **🔍 First-Class OpenTelemetry**: Seamlessly integrate with OpenTelemetry for observability.
37
+ - **⚙️ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), SWR, Pinia Colada, and more.
34
38
  - **🚀 Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
35
39
  - **🔠 Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
36
40
  - **🗃️ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more.
@@ -38,7 +42,6 @@
38
42
  - **📡 SSE & Streaming**: Enjoy full type-safe support for SSE and streaming.
39
43
  - **🌍 Multi-Runtime Support**: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond.
40
44
  - **🔌 Extendability**: Easily extend functionality with plugins, middleware, and interceptors.
41
- - **🛡️ Reliability**: Well-tested, TypeScript-based, production-ready, and MIT licensed.
42
45
 
43
46
  ## Documentation
44
47
 
@@ -49,14 +52,14 @@ You can find the full documentation [here](https://orpc.unnoq.com).
49
52
  - [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Build your API contract.
50
53
  - [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build your API or implement API contract.
51
54
  - [@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.
55
+ - [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Generate OpenAPI specs and handle OpenAPI requests.
56
+ - [@orpc/otel](https://www.npmjs.com/package/@orpc/otel): [OpenTelemetry](https://opentelemetry.io/) integration for observability.
57
+ - [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with [NestJS](https://nestjs.com/).
53
58
  - [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
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).
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).
56
- - [@orpc/solid-query](https://www.npmjs.com/package/@orpc/solid-query): Integration with [Solid Query](https://tanstack.com/query/latest/docs/framework/solid/overview).
57
- - [@orpc/svelte-query](https://www.npmjs.com/package/@orpc/svelte-query): Integration with [Svelte Query](https://tanstack.com/query/latest/docs/framework/svelte/overview).
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.
58
61
  - [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
59
- - [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Generate OpenAPI specs and handle OpenAPI requests.
62
+ - [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
60
63
  - [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
61
64
  - [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): OpenAPI spec generation from [Valibot](https://valibot.dev/).
62
65
  - [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): OpenAPI spec generation from [ArkType](https://arktype.io/).
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { Promisable, AsyncIdQueueCloseOptions as AsyncIdQueueCloseOptions$1, CreateAsyncIteratorObjectCleanupFn } from '@orpc/shared';
2
- import { StandardRequest, StandardResponse, EventMeta, StandardHeaders } from '@orpc/standard-server';
1
+ import { Promisable, AsyncIdQueueCloseOptions as AsyncIdQueueCloseOptions$1, SetSpanErrorOptions, AsyncIteratorClassCleanupFn, AsyncIteratorClass } from '@orpc/shared';
2
+ import { StandardRequest, StandardResponse, EventMeta } from '@orpc/standard-server';
3
3
 
4
- type EncodedMessage = string | ArrayBufferLike | Blob;
4
+ type EncodedMessage = string | ArrayBufferLike | Uint8Array;
5
5
  interface EncodedMessageSendFn {
6
6
  (message: EncodedMessage): Promisable<void>;
7
7
  }
@@ -16,13 +16,26 @@ interface ClientPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
16
16
  }
17
17
  declare class ClientPeer {
18
18
  private readonly idGenerator;
19
+ /**
20
+ * Queue of responses sent from server, awaiting consumption
21
+ */
19
22
  private readonly responseQueue;
23
+ /**
24
+ * Queue of event iterator messages sent from server, awaiting consumption
25
+ */
20
26
  private readonly serverEventIteratorQueue;
27
+ /**
28
+ * Controllers used to signal that the client should stop sending event iterator messages
29
+ */
21
30
  private readonly serverControllers;
31
+ /**
32
+ * Cleanup functions invoked when the request/response is closed
33
+ */
34
+ private readonly cleanupFns;
22
35
  private readonly send;
23
36
  constructor(send: EncodedMessageSendFn);
24
37
  get length(): number;
25
- open(id: number): AbortController;
38
+ open(id: string): AbortController;
26
39
  request(request: StandardRequest): Promise<StandardResponse>;
27
40
  message(raw: EncodedMessage): Promise<void>;
28
41
  close(options?: AsyncIdQueueCloseOptions$1): void;
@@ -51,36 +64,42 @@ interface ResponseMessageMap {
51
64
  [MessageType.ABORT_SIGNAL]: void;
52
65
  }
53
66
  type DecodedMessageUnion<TMap extends RequestMessageMap | ResponseMessageMap> = {
54
- [K in keyof TMap]: [id: number, type: K, payload: TMap[K]];
67
+ [K in keyof TMap]: [id: string, type: K, payload: TMap[K]];
55
68
  }[keyof TMap];
56
69
  type DecodedRequestMessage = DecodedMessageUnion<RequestMessageMap>;
57
70
  type DecodedResponseMessage = DecodedMessageUnion<ResponseMessageMap>;
58
- declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: number, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
71
+ declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: string, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
59
72
  declare function decodeRequestMessage(raw: EncodedMessage): Promise<DecodedRequestMessage>;
60
- declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: number, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
73
+ declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: string, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
61
74
  declare function decodeResponseMessage(raw: EncodedMessage): Promise<DecodedResponseMessage>;
62
- declare function isEventIteratorHeaders(headers: StandardHeaders): boolean;
63
75
 
64
76
  interface AsyncIdQueueCloseOptions {
65
- id?: number;
66
- reason?: Error;
77
+ id?: string;
78
+ reason?: unknown;
67
79
  }
68
80
  declare class AsyncIdQueue<T> {
69
81
  private readonly openIds;
70
- private readonly items;
71
- private readonly pendingPulls;
82
+ private readonly queues;
83
+ private readonly waiters;
72
84
  get length(): number;
73
- open(id: number): void;
74
- isOpen(id: number): boolean;
75
- push(id: number, item: T): void;
76
- pull(id: number): Promise<T>;
85
+ get waiterIds(): string[];
86
+ hasBufferedItems(id: string): boolean;
87
+ open(id: string): void;
88
+ isOpen(id: string): boolean;
89
+ push(id: string, item: T): void;
90
+ pull(id: string): Promise<T>;
77
91
  close({ id, reason }?: AsyncIdQueueCloseOptions): void;
78
- assertOpen(id: number): void;
92
+ assertOpen(id: string): void;
79
93
  }
80
94
 
81
- declare function toEventIterator(queue: AsyncIdQueue<EventIteratorPayload>, id: number, cleanup: CreateAsyncIteratorObjectCleanupFn): AsyncGenerator;
95
+ interface ToEventIteratorOptions extends SetSpanErrorOptions {
96
+ }
97
+ declare function toEventIterator(queue: AsyncIdQueue<EventIteratorPayload>, id: string, cleanup: AsyncIteratorClassCleanupFn, options?: ToEventIteratorOptions): AsyncIteratorClass<unknown>;
82
98
  declare function resolveEventIterator(iterator: AsyncIterator<any>, callback: (payload: EventIteratorPayload) => Promise<'next' | 'abort'>): Promise<void>;
83
99
 
100
+ interface ServerPeerHandleRequestFn {
101
+ (request: StandardRequest): Promise<StandardResponse>;
102
+ }
84
103
  interface ServerPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
85
104
  /**
86
105
  * Should abort or not?
@@ -90,16 +109,28 @@ interface ServerPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
90
109
  abort?: boolean;
91
110
  }
92
111
  declare class ServerPeer {
112
+ /**
113
+ * Queue of event iterator messages sent from client, awaiting consumption
114
+ */
93
115
  private readonly clientEventIteratorQueue;
116
+ /**
117
+ * Map of active client request controllers, should be synced to request signal
118
+ */
94
119
  private readonly clientControllers;
95
120
  private readonly send;
96
121
  constructor(send: EncodedMessageSendFn);
97
122
  get length(): number;
98
- open(id: number): AbortController;
99
- message(raw: EncodedMessage): Promise<[id: number, StandardRequest | undefined]>;
100
- response(id: number, response: StandardResponse): Promise<void>;
123
+ open(id: string): AbortController;
124
+ /**
125
+ * @todo This method will return Promise<void> in the next major version.
126
+ */
127
+ message(raw: EncodedMessage, handleRequest?: ServerPeerHandleRequestFn): Promise<[id: string, StandardRequest | undefined]>;
128
+ /**
129
+ * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
130
+ */
131
+ response(id: string, response: StandardResponse): Promise<void>;
101
132
  close({ abort, ...options }?: ServerPeerCloseOptions): void;
102
133
  }
103
134
 
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 };
135
+ export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, resolveEventIterator, toEventIterator };
136
+ export type { ClientPeerCloseOptions, DecodedRequestMessage, DecodedResponseMessage, EncodedMessage, EncodedMessageSendFn, EventIteratorEvent, EventIteratorPayload, RequestMessageMap, ResponseMessageMap, ServerPeerCloseOptions, ServerPeerHandleRequestFn, ToEventIteratorOptions };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { Promisable, AsyncIdQueueCloseOptions as AsyncIdQueueCloseOptions$1, CreateAsyncIteratorObjectCleanupFn } from '@orpc/shared';
2
- import { StandardRequest, StandardResponse, EventMeta, StandardHeaders } from '@orpc/standard-server';
1
+ import { Promisable, AsyncIdQueueCloseOptions as AsyncIdQueueCloseOptions$1, SetSpanErrorOptions, AsyncIteratorClassCleanupFn, AsyncIteratorClass } from '@orpc/shared';
2
+ import { StandardRequest, StandardResponse, EventMeta } from '@orpc/standard-server';
3
3
 
4
- type EncodedMessage = string | ArrayBufferLike | Blob;
4
+ type EncodedMessage = string | ArrayBufferLike | Uint8Array;
5
5
  interface EncodedMessageSendFn {
6
6
  (message: EncodedMessage): Promisable<void>;
7
7
  }
@@ -16,13 +16,26 @@ interface ClientPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
16
16
  }
17
17
  declare class ClientPeer {
18
18
  private readonly idGenerator;
19
+ /**
20
+ * Queue of responses sent from server, awaiting consumption
21
+ */
19
22
  private readonly responseQueue;
23
+ /**
24
+ * Queue of event iterator messages sent from server, awaiting consumption
25
+ */
20
26
  private readonly serverEventIteratorQueue;
27
+ /**
28
+ * Controllers used to signal that the client should stop sending event iterator messages
29
+ */
21
30
  private readonly serverControllers;
31
+ /**
32
+ * Cleanup functions invoked when the request/response is closed
33
+ */
34
+ private readonly cleanupFns;
22
35
  private readonly send;
23
36
  constructor(send: EncodedMessageSendFn);
24
37
  get length(): number;
25
- open(id: number): AbortController;
38
+ open(id: string): AbortController;
26
39
  request(request: StandardRequest): Promise<StandardResponse>;
27
40
  message(raw: EncodedMessage): Promise<void>;
28
41
  close(options?: AsyncIdQueueCloseOptions$1): void;
@@ -51,36 +64,42 @@ interface ResponseMessageMap {
51
64
  [MessageType.ABORT_SIGNAL]: void;
52
65
  }
53
66
  type DecodedMessageUnion<TMap extends RequestMessageMap | ResponseMessageMap> = {
54
- [K in keyof TMap]: [id: number, type: K, payload: TMap[K]];
67
+ [K in keyof TMap]: [id: string, type: K, payload: TMap[K]];
55
68
  }[keyof TMap];
56
69
  type DecodedRequestMessage = DecodedMessageUnion<RequestMessageMap>;
57
70
  type DecodedResponseMessage = DecodedMessageUnion<ResponseMessageMap>;
58
- declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: number, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
71
+ declare function encodeRequestMessage<T extends keyof RequestMessageMap>(id: string, type: T, payload: RequestMessageMap[T]): Promise<EncodedMessage>;
59
72
  declare function decodeRequestMessage(raw: EncodedMessage): Promise<DecodedRequestMessage>;
60
- declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: number, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
73
+ declare function encodeResponseMessage<T extends keyof ResponseMessageMap>(id: string, type: T, payload: ResponseMessageMap[T]): Promise<EncodedMessage>;
61
74
  declare function decodeResponseMessage(raw: EncodedMessage): Promise<DecodedResponseMessage>;
62
- declare function isEventIteratorHeaders(headers: StandardHeaders): boolean;
63
75
 
64
76
  interface AsyncIdQueueCloseOptions {
65
- id?: number;
66
- reason?: Error;
77
+ id?: string;
78
+ reason?: unknown;
67
79
  }
68
80
  declare class AsyncIdQueue<T> {
69
81
  private readonly openIds;
70
- private readonly items;
71
- private readonly pendingPulls;
82
+ private readonly queues;
83
+ private readonly waiters;
72
84
  get length(): number;
73
- open(id: number): void;
74
- isOpen(id: number): boolean;
75
- push(id: number, item: T): void;
76
- pull(id: number): Promise<T>;
85
+ get waiterIds(): string[];
86
+ hasBufferedItems(id: string): boolean;
87
+ open(id: string): void;
88
+ isOpen(id: string): boolean;
89
+ push(id: string, item: T): void;
90
+ pull(id: string): Promise<T>;
77
91
  close({ id, reason }?: AsyncIdQueueCloseOptions): void;
78
- assertOpen(id: number): void;
92
+ assertOpen(id: string): void;
79
93
  }
80
94
 
81
- declare function toEventIterator(queue: AsyncIdQueue<EventIteratorPayload>, id: number, cleanup: CreateAsyncIteratorObjectCleanupFn): AsyncGenerator;
95
+ interface ToEventIteratorOptions extends SetSpanErrorOptions {
96
+ }
97
+ declare function toEventIterator(queue: AsyncIdQueue<EventIteratorPayload>, id: string, cleanup: AsyncIteratorClassCleanupFn, options?: ToEventIteratorOptions): AsyncIteratorClass<unknown>;
82
98
  declare function resolveEventIterator(iterator: AsyncIterator<any>, callback: (payload: EventIteratorPayload) => Promise<'next' | 'abort'>): Promise<void>;
83
99
 
100
+ interface ServerPeerHandleRequestFn {
101
+ (request: StandardRequest): Promise<StandardResponse>;
102
+ }
84
103
  interface ServerPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
85
104
  /**
86
105
  * Should abort or not?
@@ -90,16 +109,28 @@ interface ServerPeerCloseOptions extends AsyncIdQueueCloseOptions$1 {
90
109
  abort?: boolean;
91
110
  }
92
111
  declare class ServerPeer {
112
+ /**
113
+ * Queue of event iterator messages sent from client, awaiting consumption
114
+ */
93
115
  private readonly clientEventIteratorQueue;
116
+ /**
117
+ * Map of active client request controllers, should be synced to request signal
118
+ */
94
119
  private readonly clientControllers;
95
120
  private readonly send;
96
121
  constructor(send: EncodedMessageSendFn);
97
122
  get length(): number;
98
- open(id: number): AbortController;
99
- message(raw: EncodedMessage): Promise<[id: number, StandardRequest | undefined]>;
100
- response(id: number, response: StandardResponse): Promise<void>;
123
+ open(id: string): AbortController;
124
+ /**
125
+ * @todo This method will return Promise<void> in the next major version.
126
+ */
127
+ message(raw: EncodedMessage, handleRequest?: ServerPeerHandleRequestFn): Promise<[id: string, StandardRequest | undefined]>;
128
+ /**
129
+ * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
130
+ */
131
+ response(id: string, response: StandardResponse): Promise<void>;
101
132
  close({ abort, ...options }?: ServerPeerCloseOptions): void;
102
133
  }
103
134
 
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 };
135
+ export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, resolveEventIterator, toEventIterator };
136
+ export type { ClientPeerCloseOptions, DecodedRequestMessage, DecodedResponseMessage, EncodedMessage, EncodedMessageSendFn, EventIteratorEvent, EventIteratorPayload, RequestMessageMap, ResponseMessageMap, ServerPeerCloseOptions, ServerPeerHandleRequestFn, ToEventIteratorOptions };
package/dist/index.mjs CHANGED
@@ -1,6 +1,8 @@
1
- import { isAsyncIteratorObject, stringifyJSON, createAsyncIteratorObject, isTypescriptObject, SequentialIdGenerator, AsyncIdQueue } from '@orpc/shared';
2
- import { flattenHeader, getFilenameFromContentDisposition, generateContentDisposition, withEventMeta, ErrorEvent, getEventMeta } from '@orpc/standard-server';
1
+ import { isAsyncIteratorObject, stringifyJSON, readAsBuffer, AsyncIteratorClass, startSpan, runInSpanContext, isTypescriptObject, setSpanError, runWithSpan, SequentialIdGenerator, AsyncIdQueue, getGlobalOtelConfig, clone, AbortError } from '@orpc/shared';
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";
@@ -22,12 +24,12 @@ async function encodeRequestMessage(id, type, payload) {
22
24
  return encodeRawMessage({ i: id, t: type, p: payload });
23
25
  }
24
26
  const request = payload;
25
- const { body: processedBody, headers: processedHeaders } = await prepareBodyAndHeadersForSerialization(
27
+ const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
26
28
  request.body,
27
29
  request.headers
28
30
  );
29
31
  const serializedPayload = {
30
- u: request.url.toString().replace(/^orpc:\//, "/"),
32
+ u: request.url.toString().replace(SHORTABLE_ORIGIN_MATCHER, "/"),
31
33
  b: processedBody instanceof Blob ? void 0 : processedBody,
32
34
  h: Object.keys(processedHeaders).length > 0 ? processedHeaders : void 0,
33
35
  m: request.method === "POST" ? void 0 : request.method
@@ -42,7 +44,7 @@ async function encodeRequestMessage(id, type, payload) {
42
44
  return encodeRawMessage(baseMessage);
43
45
  }
44
46
  async function decodeRequestMessage(raw) {
45
- const { json: message, blobData } = await decodeRawMessage(raw);
47
+ const { json: message, buffer } = await decodeRawMessage(raw);
46
48
  const id = message.i;
47
49
  const type = message.t;
48
50
  if (type === 3 /* EVENT_ITERATOR */) {
@@ -54,21 +56,13 @@ async function decodeRequestMessage(raw) {
54
56
  }
55
57
  const payload = message.p;
56
58
  const headers = payload.h ?? {};
57
- let body = payload.b;
58
- const contentType = flattenHeader(headers["content-type"]);
59
- if (blobData) {
60
- const contentDisposition = flattenHeader(headers["content-disposition"]);
61
- if (contentDisposition === void 0 && contentType?.startsWith("multipart/form-data")) {
62
- const tempRes = new Response(blobData, { headers: { "content-type": contentType } });
63
- body = await tempRes.formData();
64
- } else {
65
- const filename = getFilenameFromContentDisposition(contentDisposition) ?? "blob";
66
- body = new File([blobData], filename, { type: contentType });
67
- }
68
- } else if (contentType?.startsWith("application/x-www-form-urlencoded") && typeof body === "string") {
69
- body = new URLSearchParams(body);
70
- }
71
- return [id, 1 /* REQUEST */, { url: new URL(payload.u, "orpc:/"), headers, method: payload.m ?? "POST", body }];
59
+ const body = await deserializeBody(headers, payload.b, buffer);
60
+ return [id, 1 /* REQUEST */, {
61
+ url: payload.u.startsWith("/") ? new URL(`${SHORTABLE_ORIGIN}${payload.u}`) : new URL(payload.u),
62
+ headers,
63
+ method: payload.m ?? "POST",
64
+ body
65
+ }];
72
66
  }
73
67
  async function encodeResponseMessage(id, type, payload) {
74
68
  if (type === 3 /* EVENT_ITERATOR */) {
@@ -84,7 +78,7 @@ async function encodeResponseMessage(id, type, payload) {
84
78
  return encodeRawMessage({ i: id, t: type, p: void 0 });
85
79
  }
86
80
  const response = payload;
87
- const { body: processedBody, headers: processedHeaders } = await prepareBodyAndHeadersForSerialization(
81
+ const { body: processedBody, headers: processedHeaders } = await serializeBodyAndHeaders(
88
82
  response.body,
89
83
  response.headers
90
84
  );
@@ -103,7 +97,7 @@ async function encodeResponseMessage(id, type, payload) {
103
97
  return encodeRawMessage(baseMessage);
104
98
  }
105
99
  async function decodeResponseMessage(raw) {
106
- const { json: message, blobData } = await decodeRawMessage(raw);
100
+ const { json: message, buffer } = await decodeRawMessage(raw);
107
101
  const id = message.i;
108
102
  const type = message.t;
109
103
  if (type === 3 /* EVENT_ITERATOR */) {
@@ -115,23 +109,10 @@ async function decodeResponseMessage(raw) {
115
109
  }
116
110
  const payload = message.p;
117
111
  const headers = payload.h ?? {};
118
- let body = payload.b;
119
- const contentType = flattenHeader(headers["content-type"]);
120
- if (blobData) {
121
- const contentDisposition = flattenHeader(headers["content-disposition"]);
122
- if (contentDisposition === void 0 && contentType?.startsWith("multipart/form-data")) {
123
- const tempRes = new Response(blobData, { headers: { "content-type": contentType } });
124
- body = await tempRes.formData();
125
- } else {
126
- const filename = getFilenameFromContentDisposition(contentDisposition) ?? "blob";
127
- body = new File([blobData], filename, { type: contentType });
128
- }
129
- } else if (contentType?.startsWith("application/x-www-form-urlencoded") && typeof body === "string") {
130
- body = new URLSearchParams(body);
131
- }
112
+ const body = await deserializeBody(headers, payload.b, buffer);
132
113
  return [id, 2 /* RESPONSE */, { status: payload.s ?? 200, headers, body }];
133
114
  }
134
- async function prepareBodyAndHeadersForSerialization(body, originalHeaders) {
115
+ async function serializeBodyAndHeaders(body, originalHeaders) {
135
116
  const headers = { ...originalHeaders };
136
117
  const originalContentDisposition = headers["content-disposition"];
137
118
  delete headers["content-type"];
@@ -159,113 +140,184 @@ async function prepareBodyAndHeadersForSerialization(body, originalHeaders) {
159
140
  }
160
141
  return { body, headers };
161
142
  }
162
- function isEventIteratorHeaders(headers) {
163
- return Boolean(flattenHeader(headers["content-type"])?.startsWith("text/event-stream") && headers["content-disposition"] === void 0);
143
+ async function deserializeBody(headers, body, buffer) {
144
+ const contentType = flattenHeader(headers["content-type"]);
145
+ const contentDisposition = flattenHeader(headers["content-disposition"]);
146
+ if (typeof contentDisposition === "string") {
147
+ const filename = getFilenameFromContentDisposition(contentDisposition) ?? "blob";
148
+ return new File(buffer === void 0 ? [] : [buffer], filename, { type: contentType });
149
+ }
150
+ if (contentType?.startsWith("multipart/form-data")) {
151
+ const tempRes = new Response(buffer, { headers: { "content-type": contentType } });
152
+ return tempRes.formData();
153
+ }
154
+ if (contentType?.startsWith("application/x-www-form-urlencoded") && typeof body === "string") {
155
+ return new URLSearchParams(body);
156
+ }
157
+ return body;
164
158
  }
165
159
  const JSON_AND_BINARY_DELIMITER = 255;
166
- async function encodeRawMessage(data, blobData) {
160
+ async function encodeRawMessage(data, blob) {
167
161
  const json = stringifyJSON(data);
168
- if (blobData === void 0) {
162
+ if (blob === void 0 || blob.size === 0) {
169
163
  return json;
170
164
  }
171
- return new Blob([
165
+ return readAsBuffer(new Blob([
172
166
  new TextEncoder().encode(json),
173
167
  new Uint8Array([JSON_AND_BINARY_DELIMITER]),
174
- blobData
175
- ]);
168
+ blob
169
+ ]));
176
170
  }
177
171
  async function decodeRawMessage(raw) {
178
172
  if (typeof raw === "string") {
179
173
  return { json: JSON.parse(raw) };
180
174
  }
181
- const buffer = new Uint8Array(raw instanceof Blob ? await raw.arrayBuffer() : raw);
175
+ const buffer = raw instanceof Uint8Array ? raw : new Uint8Array(raw);
182
176
  const delimiterIndex = buffer.indexOf(JSON_AND_BINARY_DELIMITER);
183
177
  if (delimiterIndex === -1) {
184
178
  const jsonPart2 = new TextDecoder().decode(buffer);
185
179
  return { json: JSON.parse(jsonPart2) };
186
180
  }
187
- const jsonPart = new TextDecoder().decode(buffer.slice(0, delimiterIndex));
188
- const blobData = buffer.slice(delimiterIndex + 1);
181
+ const jsonPart = new TextDecoder().decode(buffer.subarray(0, delimiterIndex));
182
+ const bufferPart = buffer.subarray(delimiterIndex + 1);
189
183
  return {
190
184
  json: JSON.parse(jsonPart),
191
- blobData
185
+ buffer: bufferPart
192
186
  };
193
187
  }
194
188
 
195
- function toEventIterator(queue, id, cleanup) {
196
- return createAsyncIteratorObject(async () => {
197
- const item = await queue.pull(id);
198
- switch (item.event) {
199
- case "message": {
200
- let data = item.data;
201
- if (item.meta && isTypescriptObject(data)) {
202
- data = withEventMeta(data, item.meta);
189
+ function toEventIterator(queue, id, cleanup, options = {}) {
190
+ let span;
191
+ return new AsyncIteratorClass(async () => {
192
+ span ??= startSpan("consume_event_iterator_stream");
193
+ try {
194
+ const item = await runInSpanContext(span, () => queue.pull(id));
195
+ switch (item.event) {
196
+ case "message": {
197
+ let data = item.data;
198
+ if (item.meta && isTypescriptObject(data)) {
199
+ data = withEventMeta(data, item.meta);
200
+ }
201
+ span?.addEvent("message");
202
+ return { value: data, done: false };
203
203
  }
204
- return { value: data, done: false };
205
- }
206
- case "error": {
207
- let error = new ErrorEvent({
208
- data: item.data
209
- });
210
- if (item.meta) {
211
- error = withEventMeta(error, item.meta);
204
+ case "error": {
205
+ let error = new ErrorEvent({
206
+ data: item.data
207
+ });
208
+ if (item.meta) {
209
+ error = withEventMeta(error, item.meta);
210
+ }
211
+ span?.addEvent("error");
212
+ throw error;
212
213
  }
213
- throw error;
214
- }
215
- case "done": {
216
- let data = item.data;
217
- if (item.meta && isTypescriptObject(data)) {
218
- data = withEventMeta(data, item.meta);
214
+ case "done": {
215
+ let data = item.data;
216
+ if (item.meta && isTypescriptObject(data)) {
217
+ data = withEventMeta(data, item.meta);
218
+ }
219
+ span?.addEvent("done");
220
+ return { value: data, done: true };
219
221
  }
220
- return { value: data, done: true };
221
222
  }
222
- }
223
- }, cleanup);
224
- }
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) };
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
- };
223
+ } catch (e) {
224
+ if (!(e instanceof ErrorEvent)) {
225
+ setSpanError(span, e, options);
240
226
  }
241
- })();
227
+ throw e;
228
+ }
229
+ }, async (reason) => {
242
230
  try {
243
- const direction = await callback(payload);
244
- if (payload.event === "done" || payload.event === "error") {
245
- return;
231
+ if (reason !== "next") {
232
+ span?.addEvent("cancelled");
246
233
  }
247
- if (direction === "abort") {
234
+ await runInSpanContext(span, () => cleanup(reason));
235
+ } catch (e) {
236
+ setSpanError(span, e, options);
237
+ throw e;
238
+ } finally {
239
+ span?.end();
240
+ }
241
+ });
242
+ }
243
+ function resolveEventIterator(iterator, callback) {
244
+ return runWithSpan(
245
+ { name: "stream_event_iterator" },
246
+ async (span) => {
247
+ while (true) {
248
+ const payload = await (async () => {
249
+ try {
250
+ const { value, done } = await iterator.next();
251
+ if (done) {
252
+ span?.addEvent("done");
253
+ return { event: "done", data: value, meta: getEventMeta(value) };
254
+ }
255
+ span?.addEvent("message");
256
+ return { event: "message", data: value, meta: getEventMeta(value) };
257
+ } catch (err) {
258
+ if (err instanceof ErrorEvent) {
259
+ span?.addEvent("error");
260
+ return {
261
+ event: "error",
262
+ data: err.data,
263
+ meta: getEventMeta(err)
264
+ };
265
+ } else {
266
+ try {
267
+ await callback({ event: "error", data: void 0 });
268
+ } catch (err2) {
269
+ setSpanError(span, err);
270
+ throw err2;
271
+ }
272
+ throw err;
273
+ }
274
+ }
275
+ })();
276
+ let isInvokeCleanupFn = false;
248
277
  try {
249
- await iterator.return?.();
250
- } catch {
278
+ const direction = await callback(payload);
279
+ if (payload.event === "done" || payload.event === "error") {
280
+ return;
281
+ }
282
+ if (direction === "abort") {
283
+ isInvokeCleanupFn = true;
284
+ await iterator.return?.();
285
+ return;
286
+ }
287
+ } catch (err) {
288
+ if (!isInvokeCleanupFn) {
289
+ try {
290
+ await iterator.return?.();
291
+ } catch (err2) {
292
+ setSpanError(span, err);
293
+ throw err2;
294
+ }
295
+ }
296
+ throw err;
251
297
  }
252
- return;
253
- }
254
- } catch (err) {
255
- try {
256
- await iterator.return?.();
257
- } catch {
258
298
  }
259
- throw err;
260
299
  }
261
- }
300
+ );
262
301
  }
263
302
 
264
303
  class ClientPeer {
265
304
  idGenerator = new SequentialIdGenerator();
305
+ /**
306
+ * Queue of responses sent from server, awaiting consumption
307
+ */
266
308
  responseQueue = new AsyncIdQueue();
309
+ /**
310
+ * Queue of event iterator messages sent from server, awaiting consumption
311
+ */
267
312
  serverEventIteratorQueue = new AsyncIdQueue();
313
+ /**
314
+ * Controllers used to signal that the client should stop sending event iterator messages
315
+ */
268
316
  serverControllers = /* @__PURE__ */ new Map();
317
+ /**
318
+ * Cleanup functions invoked when the request/response is closed
319
+ */
320
+ cleanupFns = /* @__PURE__ */ new Map();
269
321
  send;
270
322
  constructor(send) {
271
323
  this.send = async (id, ...rest) => encodeRequestMessage(id, ...rest).then(async (raw) => {
@@ -275,48 +327,85 @@ class ClientPeer {
275
327
  });
276
328
  }
277
329
  get length() {
278
- return (+this.responseQueue.length + this.serverEventIteratorQueue.length + this.serverControllers.size) / 3;
330
+ return (+this.responseQueue.length + this.serverEventIteratorQueue.length + this.serverControllers.size + this.cleanupFns.size) / 4;
279
331
  }
280
332
  open(id) {
281
333
  this.serverEventIteratorQueue.open(id);
282
334
  this.responseQueue.open(id);
283
335
  const controller = new AbortController();
284
336
  this.serverControllers.set(id, controller);
337
+ this.cleanupFns.set(id, []);
285
338
  return controller;
286
339
  }
287
340
  async request(request) {
288
341
  const signal = request.signal;
289
- if (signal?.aborted) {
290
- throw signal.reason;
291
- }
292
- const id = this.idGenerator.generate();
293
- const serverController = this.open(id);
294
- return new Promise((resolve, reject) => {
295
- this.send(id, MessageType.REQUEST, request).then(async () => {
342
+ return runWithSpan(
343
+ { name: "send_peer_request", signal },
344
+ async () => {
296
345
  if (signal?.aborted) {
297
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
298
- this.close({ id, reason: signal.reason });
299
- return;
346
+ throw signal.reason;
300
347
  }
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";
348
+ const id = this.idGenerator.generate();
349
+ const serverController = this.open(id);
350
+ try {
351
+ const otelConfig = getGlobalOtelConfig();
352
+ if (otelConfig) {
353
+ const headers = clone(request.headers);
354
+ otelConfig.propagation.inject(otelConfig.context.active(), headers);
355
+ request = { ...request, headers };
356
+ }
357
+ await this.send(id, MessageType.REQUEST, request);
358
+ if (signal?.aborted) {
359
+ await this.send(id, MessageType.ABORT_SIGNAL, void 0);
360
+ throw signal.reason;
361
+ }
362
+ let abortListener;
363
+ signal?.addEventListener("abort", abortListener = async () => {
364
+ await this.send(id, MessageType.ABORT_SIGNAL, void 0);
365
+ this.close({ id, reason: signal.reason });
366
+ }, { once: true });
367
+ this.cleanupFns.get(id)?.push(() => {
368
+ signal?.removeEventListener("abort", abortListener);
312
369
  });
370
+ if (isAsyncIteratorObject(request.body)) {
371
+ const iterator = request.body;
372
+ void resolveEventIterator(iterator, async (payload) => {
373
+ if (serverController.signal.aborted) {
374
+ return "abort";
375
+ }
376
+ await this.send(id, MessageType.EVENT_ITERATOR, payload);
377
+ return "next";
378
+ });
379
+ }
380
+ const response = await this.responseQueue.pull(id);
381
+ if (isEventIteratorHeaders(response.headers)) {
382
+ const iterator = toEventIterator(
383
+ this.serverEventIteratorQueue,
384
+ id,
385
+ async (reason) => {
386
+ try {
387
+ if (reason !== "next") {
388
+ await this.send(id, MessageType.ABORT_SIGNAL, void 0);
389
+ }
390
+ } finally {
391
+ this.close({ id });
392
+ }
393
+ },
394
+ { signal }
395
+ );
396
+ return {
397
+ ...response,
398
+ body: iterator
399
+ };
400
+ }
401
+ this.close({ id });
402
+ return response;
403
+ } catch (err) {
404
+ this.close({ id, reason: err });
405
+ throw err;
313
406
  }
314
- }).catch((err) => {
315
- this.close({ id, reason: err });
316
- reject(err);
317
- });
318
- this.responseQueue.pull(id).then(resolve).catch(reject);
319
- });
407
+ }
408
+ );
320
409
  }
321
410
  async message(raw) {
322
411
  const [id, type, payload] = await decodeResponseMessage(raw);
@@ -333,31 +422,19 @@ class ClientPeer {
333
422
  if (!this.responseQueue.isOpen(id)) {
334
423
  return;
335
424
  }
336
- if (isEventIteratorHeaders(payload.headers)) {
337
- this.responseQueue.push(id, {
338
- ...payload,
339
- body: toEventIterator(this.serverEventIteratorQueue, id, async (reason) => {
340
- try {
341
- if (reason !== "next") {
342
- await this.send(id, MessageType.ABORT_SIGNAL, void 0);
343
- }
344
- } finally {
345
- this.close({ id });
346
- }
347
- })
348
- });
349
- } else {
350
- this.responseQueue.push(id, payload);
351
- this.close({ id });
352
- }
425
+ this.responseQueue.push(id, payload);
353
426
  }
354
427
  close(options = {}) {
355
428
  if (options.id !== void 0) {
356
429
  this.serverControllers.get(options.id)?.abort(options.reason);
357
430
  this.serverControllers.delete(options.id);
431
+ this.cleanupFns.get(options.id)?.forEach((fn) => fn());
432
+ this.cleanupFns.delete(options.id);
358
433
  } else {
359
434
  this.serverControllers.forEach((c) => c.abort(options.reason));
360
435
  this.serverControllers.clear();
436
+ this.cleanupFns.forEach((fns) => fns.forEach((fn) => fn()));
437
+ this.cleanupFns.clear();
361
438
  }
362
439
  this.responseQueue.close(options);
363
440
  this.serverEventIteratorQueue.close(options);
@@ -365,7 +442,13 @@ class ClientPeer {
365
442
  }
366
443
 
367
444
  class ServerPeer {
445
+ /**
446
+ * Queue of event iterator messages sent from client, awaiting consumption
447
+ */
368
448
  clientEventIteratorQueue = new AsyncIdQueue();
449
+ /**
450
+ * Map of active client request controllers, should be synced to request signal
451
+ */
369
452
  clientControllers = /* @__PURE__ */ new Map();
370
453
  send;
371
454
  constructor(send) {
@@ -384,10 +467,13 @@ class ServerPeer {
384
467
  this.clientControllers.set(id, controller);
385
468
  return controller;
386
469
  }
387
- async message(raw) {
470
+ /**
471
+ * @todo This method will return Promise<void> in the next major version.
472
+ */
473
+ async message(raw, handleRequest) {
388
474
  const [id, type, payload] = await decodeRequestMessage(raw);
389
475
  if (type === MessageType.ABORT_SIGNAL) {
390
- this.close({ id });
476
+ this.close({ id, reason: new AbortError("Client aborted the request") });
391
477
  return [id, void 0];
392
478
  }
393
479
  if (type === MessageType.EVENT_ITERATOR) {
@@ -397,47 +483,89 @@ class ServerPeer {
397
483
  return [id, void 0];
398
484
  }
399
485
  const clientController = this.open(id);
486
+ const signal = clientController.signal;
400
487
  const request = {
401
488
  ...payload,
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);
406
- }
407
- }) : payload.body
489
+ signal,
490
+ body: isEventIteratorHeaders(payload.headers) ? toEventIterator(
491
+ this.clientEventIteratorQueue,
492
+ id,
493
+ async (reason) => {
494
+ if (reason !== "next") {
495
+ await this.send(id, MessageType.ABORT_SIGNAL, void 0);
496
+ }
497
+ },
498
+ { signal }
499
+ ) : payload.body
408
500
  };
501
+ if (handleRequest) {
502
+ let context;
503
+ const otelConfig = getGlobalOtelConfig();
504
+ if (otelConfig) {
505
+ context = otelConfig.propagation.extract(otelConfig.context.active(), request.headers);
506
+ }
507
+ await runWithSpan(
508
+ { name: "receive_peer_request", context },
509
+ async () => {
510
+ const response = await runWithSpan(
511
+ { name: "handle_request" },
512
+ async () => {
513
+ try {
514
+ return await handleRequest(request);
515
+ } catch (reason) {
516
+ this.close({ id, reason, abort: false });
517
+ throw reason;
518
+ }
519
+ }
520
+ );
521
+ await runWithSpan(
522
+ { name: "send_peer_response" },
523
+ () => this.response(id, response)
524
+ );
525
+ }
526
+ );
527
+ }
409
528
  return [id, request];
410
529
  }
530
+ /**
531
+ * @deprecated Please pass the `handleRequest` (second arg) function to the `message` method instead.
532
+ */
411
533
  async response(id, response) {
412
534
  const signal = this.clientControllers.get(id)?.signal;
413
535
  if (!signal || signal.aborted) {
414
536
  return;
415
537
  }
416
- await this.send(id, MessageType.RESPONSE, response).then(async () => {
538
+ try {
539
+ await this.send(id, MessageType.RESPONSE, response);
417
540
  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
- });
541
+ if (response.body instanceof HibernationEventIterator) {
542
+ response.body.hibernationCallback?.(id);
543
+ } else {
544
+ const iterator = response.body;
545
+ await resolveEventIterator(iterator, async (payload) => {
546
+ if (signal.aborted) {
547
+ return "abort";
548
+ }
549
+ await this.send(id, MessageType.EVENT_ITERATOR, payload);
550
+ return "next";
551
+ });
552
+ }
425
553
  }
426
554
  this.close({ id, abort: false });
427
- }).catch((reason) => {
555
+ } catch (reason) {
428
556
  this.close({ id, reason, abort: false });
429
557
  throw reason;
430
- });
558
+ }
431
559
  }
432
560
  close({ abort = true, ...options } = {}) {
433
561
  if (options.id === void 0) {
434
562
  if (abort) {
435
- this.clientControllers.forEach((c) => c.abort());
563
+ this.clientControllers.forEach((c) => c.abort(options.reason));
436
564
  }
437
565
  this.clientControllers.clear();
438
566
  } else {
439
567
  if (abort) {
440
- this.clientControllers.get(options.id)?.abort();
568
+ this.clientControllers.get(options.id)?.abort(options.reason);
441
569
  }
442
570
  this.clientControllers.delete(options.id);
443
571
  }
@@ -445,4 +573,4 @@ class ServerPeer {
445
573
  }
446
574
  }
447
575
 
448
- export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, isEventIteratorHeaders, resolveEventIterator, toEventIterator };
576
+ export { ClientPeer, MessageType, ServerPeer, decodeRequestMessage, decodeResponseMessage, encodeRequestMessage, encodeResponseMessage, 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": "0.0.0-next.fa8d145",
4
+ "version": "0.0.0-next.fc1437c",
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": "0.0.0-next.fa8d145",
27
- "@orpc/standard-server": "0.0.0-next.fa8d145"
26
+ "@orpc/shared": "0.0.0-next.fc1437c",
27
+ "@orpc/standard-server": "0.0.0-next.fc1437c"
28
28
  },
29
29
  "scripts": {
30
30
  "build": "unbuild",