@orpc/client 0.0.0-next.c8607a4 → 0.0.0-next.ca5123c

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, Angular), 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
 
@@ -50,9 +53,11 @@ You can find the full documentation [here](https://orpc.unnoq.com).
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
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.
53
57
  - [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with [NestJS](https://nestjs.com/).
54
58
  - [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
55
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.
56
61
  - [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
57
62
  - [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
58
63
  - [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
@@ -1,23 +1,36 @@
1
+ import { Interceptor } from '@orpc/shared';
1
2
  import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
2
3
  import { ToFetchRequestOptions } from '@orpc/standard-server-fetch';
3
4
  import { b as ClientContext, c as ClientOptions } from '../../shared/client.BOYsZIRq.mjs';
4
- import { f as StandardLinkClient } from '../../shared/client.C4VxIexA.mjs';
5
- import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.aTp4sII-.mjs';
6
- import '@orpc/shared';
5
+ import { a as StandardLinkPlugin, f as StandardLinkClient } from '../../shared/client.Bwgm6dgk.mjs';
6
+ import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client._Y_enhib.mjs';
7
7
 
8
- interface LinkFetchClientOptions<T extends ClientContext> extends ToFetchRequestOptions {
9
- fetch?: (request: Request, init: {
8
+ interface LinkFetchPlugin<T extends ClientContext> extends StandardLinkPlugin<T> {
9
+ initRuntimeAdapter?(options: LinkFetchClientOptions<T>): void;
10
+ }
11
+
12
+ interface LinkFetchInterceptorOptions<T extends ClientContext> extends ClientOptions<T> {
13
+ request: Request;
14
+ init: {
10
15
  redirect?: Request['redirect'];
11
- }, options: ClientOptions<T>, path: readonly string[], input: unknown) => Promise<Response>;
16
+ };
17
+ path: readonly string[];
18
+ input: unknown;
19
+ }
20
+ interface LinkFetchClientOptions<T extends ClientContext> extends ToFetchRequestOptions {
21
+ fetch?: (request: Request, init: LinkFetchInterceptorOptions<T>['init'], options: ClientOptions<T>, path: readonly string[], input: unknown) => Promise<Response>;
22
+ adapterInterceptors?: Interceptor<LinkFetchInterceptorOptions<T>, Promise<Response>>[];
23
+ plugins?: LinkFetchPlugin<T>[];
12
24
  }
13
25
  declare class LinkFetchClient<T extends ClientContext> implements StandardLinkClient<T> {
14
26
  private readonly fetch;
15
27
  private readonly toFetchRequestOptions;
28
+ private readonly adapterInterceptors;
16
29
  constructor(options: LinkFetchClientOptions<T>);
17
- call(request: StandardRequest, options: ClientOptions<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
30
+ call(standardRequest: StandardRequest, options: ClientOptions<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
18
31
  }
19
32
 
20
- interface RPCLinkOptions<T extends ClientContext> extends StandardRPCLinkOptions<T>, LinkFetchClientOptions<T> {
33
+ interface RPCLinkOptions<T extends ClientContext> extends LinkFetchClientOptions<T>, Omit<StandardRPCLinkOptions<T>, 'plugins'> {
21
34
  }
22
35
  /**
23
36
  * The RPC Link communicates with the server using the RPC protocol.
@@ -30,4 +43,4 @@ declare class RPCLink<T extends ClientContext> extends StandardRPCLink<T> {
30
43
  }
31
44
 
32
45
  export { LinkFetchClient, RPCLink };
33
- export type { LinkFetchClientOptions, RPCLinkOptions };
46
+ export type { LinkFetchClientOptions, LinkFetchInterceptorOptions, RPCLinkOptions };
@@ -1,23 +1,36 @@
1
+ import { Interceptor } from '@orpc/shared';
1
2
  import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
2
3
  import { ToFetchRequestOptions } from '@orpc/standard-server-fetch';
3
4
  import { b as ClientContext, c as ClientOptions } from '../../shared/client.BOYsZIRq.js';
4
- import { f as StandardLinkClient } from '../../shared/client.CXXEPIbK.js';
5
- import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.WCinBImJ.js';
6
- import '@orpc/shared';
5
+ import { a as StandardLinkPlugin, f as StandardLinkClient } from '../../shared/client.BG98rYdO.js';
6
+ import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.CVVVqf1Y.js';
7
7
 
8
- interface LinkFetchClientOptions<T extends ClientContext> extends ToFetchRequestOptions {
9
- fetch?: (request: Request, init: {
8
+ interface LinkFetchPlugin<T extends ClientContext> extends StandardLinkPlugin<T> {
9
+ initRuntimeAdapter?(options: LinkFetchClientOptions<T>): void;
10
+ }
11
+
12
+ interface LinkFetchInterceptorOptions<T extends ClientContext> extends ClientOptions<T> {
13
+ request: Request;
14
+ init: {
10
15
  redirect?: Request['redirect'];
11
- }, options: ClientOptions<T>, path: readonly string[], input: unknown) => Promise<Response>;
16
+ };
17
+ path: readonly string[];
18
+ input: unknown;
19
+ }
20
+ interface LinkFetchClientOptions<T extends ClientContext> extends ToFetchRequestOptions {
21
+ fetch?: (request: Request, init: LinkFetchInterceptorOptions<T>['init'], options: ClientOptions<T>, path: readonly string[], input: unknown) => Promise<Response>;
22
+ adapterInterceptors?: Interceptor<LinkFetchInterceptorOptions<T>, Promise<Response>>[];
23
+ plugins?: LinkFetchPlugin<T>[];
12
24
  }
13
25
  declare class LinkFetchClient<T extends ClientContext> implements StandardLinkClient<T> {
14
26
  private readonly fetch;
15
27
  private readonly toFetchRequestOptions;
28
+ private readonly adapterInterceptors;
16
29
  constructor(options: LinkFetchClientOptions<T>);
17
- call(request: StandardRequest, options: ClientOptions<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
30
+ call(standardRequest: StandardRequest, options: ClientOptions<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
18
31
  }
19
32
 
20
- interface RPCLinkOptions<T extends ClientContext> extends StandardRPCLinkOptions<T>, LinkFetchClientOptions<T> {
33
+ interface RPCLinkOptions<T extends ClientContext> extends LinkFetchClientOptions<T>, Omit<StandardRPCLinkOptions<T>, 'plugins'> {
21
34
  }
22
35
  /**
23
36
  * The RPC Link communicates with the server using the RPC protocol.
@@ -30,4 +43,4 @@ declare class RPCLink<T extends ClientContext> extends StandardRPCLink<T> {
30
43
  }
31
44
 
32
45
  export { LinkFetchClient, RPCLink };
33
- export type { LinkFetchClientOptions, RPCLinkOptions };
46
+ export type { LinkFetchClientOptions, LinkFetchInterceptorOptions, RPCLinkOptions };
@@ -1,20 +1,36 @@
1
+ import { toArray, intercept } from '@orpc/shared';
1
2
  import { toFetchRequest, toStandardLazyResponse } from '@orpc/standard-server-fetch';
2
- import '@orpc/shared';
3
- import { c as StandardRPCLink } from '../../shared/client.DwfV9Oyl.mjs';
3
+ import { C as CompositeStandardLinkPlugin, c as StandardRPCLink } from '../../shared/client.8idnGCEC.mjs';
4
4
  import '@orpc/standard-server';
5
- import '../../shared/client.DHOfWE0c.mjs';
5
+ import '../../shared/client.Ct2dObnC.mjs';
6
+
7
+ class CompositeLinkFetchPlugin extends CompositeStandardLinkPlugin {
8
+ initRuntimeAdapter(options) {
9
+ for (const plugin of this.plugins) {
10
+ plugin.initRuntimeAdapter?.(options);
11
+ }
12
+ }
13
+ }
6
14
 
7
15
  class LinkFetchClient {
8
16
  fetch;
9
17
  toFetchRequestOptions;
18
+ adapterInterceptors;
10
19
  constructor(options) {
11
- this.fetch = options?.fetch ?? globalThis.fetch.bind(globalThis);
20
+ const plugin = new CompositeLinkFetchPlugin(options.plugins);
21
+ plugin.initRuntimeAdapter(options);
22
+ this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
12
23
  this.toFetchRequestOptions = options;
24
+ this.adapterInterceptors = toArray(options.adapterInterceptors);
13
25
  }
14
- async call(request, options, path, input) {
15
- const fetchRequest = toFetchRequest(request, this.toFetchRequestOptions);
16
- const fetchResponse = await this.fetch(fetchRequest, { redirect: "manual" }, options, path, input);
17
- const lazyResponse = toStandardLazyResponse(fetchResponse);
26
+ async call(standardRequest, options, path, input) {
27
+ const request = toFetchRequest(standardRequest, this.toFetchRequestOptions);
28
+ const fetchResponse = await intercept(
29
+ this.adapterInterceptors,
30
+ { ...options, request, path, input, init: { redirect: "manual" } },
31
+ ({ request: request2, path: path2, input: input2, init, ...options2 }) => this.fetch(request2, init, options2, path2, input2)
32
+ );
33
+ const lazyResponse = toStandardLazyResponse(fetchResponse, { signal: request.signal });
18
34
  return lazyResponse;
19
35
  }
20
36
  }
@@ -1,7 +1,7 @@
1
1
  import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
2
2
  import { b as ClientContext, c as ClientOptions } from '../../shared/client.BOYsZIRq.mjs';
3
- import { f as StandardLinkClient } from '../../shared/client.C4VxIexA.mjs';
4
- import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.aTp4sII-.mjs';
3
+ import { f as StandardLinkClient } from '../../shared/client.Bwgm6dgk.mjs';
4
+ import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client._Y_enhib.mjs';
5
5
  import '@orpc/shared';
6
6
 
7
7
  /**
@@ -43,7 +43,7 @@ declare class LinkMessagePortClient<T extends ClientContext> implements Standard
43
43
  call(request: StandardRequest, _options: ClientOptions<T>, _path: readonly string[], _input: unknown): Promise<StandardLazyResponse>;
44
44
  }
45
45
 
46
- interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardRPCLinkOptions<T>, 'url' | 'headers' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkMessagePortClientOptions {
46
+ interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardRPCLinkOptions<T>, 'url' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkMessagePortClientOptions {
47
47
  }
48
48
  /**
49
49
  * The RPC Link for common message port implementations.
@@ -1,7 +1,7 @@
1
1
  import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
2
2
  import { b as ClientContext, c as ClientOptions } from '../../shared/client.BOYsZIRq.js';
3
- import { f as StandardLinkClient } from '../../shared/client.CXXEPIbK.js';
4
- import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.WCinBImJ.js';
3
+ import { f as StandardLinkClient } from '../../shared/client.BG98rYdO.js';
4
+ import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.CVVVqf1Y.js';
5
5
  import '@orpc/shared';
6
6
 
7
7
  /**
@@ -43,7 +43,7 @@ declare class LinkMessagePortClient<T extends ClientContext> implements Standard
43
43
  call(request: StandardRequest, _options: ClientOptions<T>, _path: readonly string[], _input: unknown): Promise<StandardLazyResponse>;
44
44
  }
45
45
 
46
- interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardRPCLinkOptions<T>, 'url' | 'headers' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkMessagePortClientOptions {
46
+ interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardRPCLinkOptions<T>, 'url' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkMessagePortClientOptions {
47
47
  }
48
48
  /**
49
49
  * The RPC Link for common message port implementations.
@@ -1,8 +1,9 @@
1
1
  import { ClientPeer } from '@orpc/standard-server-peer';
2
2
  import '@orpc/shared';
3
- import { c as StandardRPCLink } from '../../shared/client.DwfV9Oyl.mjs';
3
+ import { c as StandardRPCLink } from '../../shared/client.8idnGCEC.mjs';
4
4
  import '@orpc/standard-server';
5
- import '../../shared/client.DHOfWE0c.mjs';
5
+ import '../../shared/client.Ct2dObnC.mjs';
6
+ import '@orpc/standard-server-fetch';
6
7
 
7
8
  function postMessagePortMessage(port, data) {
8
9
  port.postMessage(data);
@@ -64,7 +65,7 @@ class LinkMessagePortClient {
64
65
  class RPCLink extends StandardRPCLink {
65
66
  constructor(options) {
66
67
  const linkClient = new LinkMessagePortClient(options);
67
- super(linkClient, { ...options, url: "orpc:/" });
68
+ super(linkClient, { ...options, url: "orpc://localhost" });
68
69
  }
69
70
  }
70
71
 
@@ -1,10 +1,11 @@
1
- export { C as CompositeStandardLinkPlugin, d as StandardLink, f as StandardLinkClient, S as StandardLinkClientInterceptorOptions, e as StandardLinkCodec, c as StandardLinkInterceptorOptions, b as StandardLinkOptions, a as StandardLinkPlugin } from '../../shared/client.C4VxIexA.mjs';
2
- export { S as STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES, c as StandardRPCCustomJsonSerializer, b as StandardRPCJsonSerialized, a as StandardRPCJsonSerializedMetaItem, e as StandardRPCJsonSerializer, d as StandardRPCJsonSerializerOptions, g as StandardRPCLink, i as StandardRPCLinkCodec, h as StandardRPCLinkCodecOptions, f as StandardRPCLinkOptions, j as StandardRPCSerializer } from '../../shared/client.aTp4sII-.mjs';
1
+ export { C as CompositeStandardLinkPlugin, d as StandardLink, f as StandardLinkClient, S as StandardLinkClientInterceptorOptions, e as StandardLinkCodec, c as StandardLinkInterceptorOptions, b as StandardLinkOptions, a as StandardLinkPlugin } from '../../shared/client.Bwgm6dgk.mjs';
2
+ export { S as STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES, c as StandardRPCCustomJsonSerializer, b as StandardRPCJsonSerialized, a as StandardRPCJsonSerializedMetaItem, e as StandardRPCJsonSerializer, d as StandardRPCJsonSerializerOptions, g as StandardRPCLink, i as StandardRPCLinkCodec, h as StandardRPCLinkCodecOptions, f as StandardRPCLinkOptions, j as StandardRPCSerializer } from '../../shared/client._Y_enhib.mjs';
3
+ import { StandardHeaders } from '@orpc/standard-server';
3
4
  import { H as HTTPPath } from '../../shared/client.BOYsZIRq.mjs';
4
5
  import '@orpc/shared';
5
- import '@orpc/standard-server';
6
6
 
7
7
  declare function toHttpPath(path: readonly string[]): HTTPPath;
8
+ declare function toStandardHeaders(headers: Headers | StandardHeaders): StandardHeaders;
8
9
  declare function getMalformedResponseErrorCode(status: number): string;
9
10
 
10
- export { getMalformedResponseErrorCode, toHttpPath };
11
+ export { getMalformedResponseErrorCode, toHttpPath, toStandardHeaders };
@@ -1,10 +1,11 @@
1
- export { C as CompositeStandardLinkPlugin, d as StandardLink, f as StandardLinkClient, S as StandardLinkClientInterceptorOptions, e as StandardLinkCodec, c as StandardLinkInterceptorOptions, b as StandardLinkOptions, a as StandardLinkPlugin } from '../../shared/client.CXXEPIbK.js';
2
- export { S as STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES, c as StandardRPCCustomJsonSerializer, b as StandardRPCJsonSerialized, a as StandardRPCJsonSerializedMetaItem, e as StandardRPCJsonSerializer, d as StandardRPCJsonSerializerOptions, g as StandardRPCLink, i as StandardRPCLinkCodec, h as StandardRPCLinkCodecOptions, f as StandardRPCLinkOptions, j as StandardRPCSerializer } from '../../shared/client.WCinBImJ.js';
1
+ export { C as CompositeStandardLinkPlugin, d as StandardLink, f as StandardLinkClient, S as StandardLinkClientInterceptorOptions, e as StandardLinkCodec, c as StandardLinkInterceptorOptions, b as StandardLinkOptions, a as StandardLinkPlugin } from '../../shared/client.BG98rYdO.js';
2
+ export { S as STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES, c as StandardRPCCustomJsonSerializer, b as StandardRPCJsonSerialized, a as StandardRPCJsonSerializedMetaItem, e as StandardRPCJsonSerializer, d as StandardRPCJsonSerializerOptions, g as StandardRPCLink, i as StandardRPCLinkCodec, h as StandardRPCLinkCodecOptions, f as StandardRPCLinkOptions, j as StandardRPCSerializer } from '../../shared/client.CVVVqf1Y.js';
3
+ import { StandardHeaders } from '@orpc/standard-server';
3
4
  import { H as HTTPPath } from '../../shared/client.BOYsZIRq.js';
4
5
  import '@orpc/shared';
5
- import '@orpc/standard-server';
6
6
 
7
7
  declare function toHttpPath(path: readonly string[]): HTTPPath;
8
+ declare function toStandardHeaders(headers: Headers | StandardHeaders): StandardHeaders;
8
9
  declare function getMalformedResponseErrorCode(status: number): string;
9
10
 
10
- export { getMalformedResponseErrorCode, toHttpPath };
11
+ export { getMalformedResponseErrorCode, toHttpPath, toStandardHeaders };
@@ -1,4 +1,5 @@
1
- export { C as CompositeStandardLinkPlugin, a as STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES, S as StandardLink, b as StandardRPCJsonSerializer, c as StandardRPCLink, d as StandardRPCLinkCodec, e as StandardRPCSerializer, g as getMalformedResponseErrorCode, t as toHttpPath } from '../../shared/client.DwfV9Oyl.mjs';
1
+ export { C as CompositeStandardLinkPlugin, a as STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES, S as StandardLink, b as StandardRPCJsonSerializer, c as StandardRPCLink, d as StandardRPCLinkCodec, e as StandardRPCSerializer, g as getMalformedResponseErrorCode, t as toHttpPath, f as toStandardHeaders } from '../../shared/client.8idnGCEC.mjs';
2
2
  import '@orpc/shared';
3
3
  import '@orpc/standard-server';
4
- import '../../shared/client.DHOfWE0c.mjs';
4
+ import '../../shared/client.Ct2dObnC.mjs';
5
+ import '@orpc/standard-server-fetch';
@@ -1,7 +1,7 @@
1
1
  import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
2
2
  import { b as ClientContext, c as ClientOptions } from '../../shared/client.BOYsZIRq.mjs';
3
- import { f as StandardLinkClient } from '../../shared/client.C4VxIexA.mjs';
4
- import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.aTp4sII-.mjs';
3
+ import { f as StandardLinkClient } from '../../shared/client.Bwgm6dgk.mjs';
4
+ import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client._Y_enhib.mjs';
5
5
  import '@orpc/shared';
6
6
 
7
7
  interface LinkWebsocketClientOptions {
@@ -13,7 +13,7 @@ declare class LinkWebsocketClient<T extends ClientContext> implements StandardLi
13
13
  call(request: StandardRequest, _options: ClientOptions<T>, _path: readonly string[], _input: unknown): Promise<StandardLazyResponse>;
14
14
  }
15
15
 
16
- interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardRPCLinkOptions<T>, 'url' | 'headers' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkWebsocketClientOptions {
16
+ interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardRPCLinkOptions<T>, 'url' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkWebsocketClientOptions {
17
17
  }
18
18
  /**
19
19
  * The RPC Link communicates with the server using the RPC protocol over WebSocket.
@@ -1,7 +1,7 @@
1
1
  import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
2
2
  import { b as ClientContext, c as ClientOptions } from '../../shared/client.BOYsZIRq.js';
3
- import { f as StandardLinkClient } from '../../shared/client.CXXEPIbK.js';
4
- import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.WCinBImJ.js';
3
+ import { f as StandardLinkClient } from '../../shared/client.BG98rYdO.js';
4
+ import { f as StandardRPCLinkOptions, g as StandardRPCLink } from '../../shared/client.CVVVqf1Y.js';
5
5
  import '@orpc/shared';
6
6
 
7
7
  interface LinkWebsocketClientOptions {
@@ -13,7 +13,7 @@ declare class LinkWebsocketClient<T extends ClientContext> implements StandardLi
13
13
  call(request: StandardRequest, _options: ClientOptions<T>, _path: readonly string[], _input: unknown): Promise<StandardLazyResponse>;
14
14
  }
15
15
 
16
- interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardRPCLinkOptions<T>, 'url' | 'headers' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkWebsocketClientOptions {
16
+ interface RPCLinkOptions<T extends ClientContext> extends Omit<StandardRPCLinkOptions<T>, 'url' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkWebsocketClientOptions {
17
17
  }
18
18
  /**
19
19
  * The RPC Link communicates with the server using the RPC protocol over WebSocket.
@@ -1,14 +1,16 @@
1
1
  import { readAsBuffer } from '@orpc/shared';
2
2
  import { ClientPeer } from '@orpc/standard-server-peer';
3
- import { c as StandardRPCLink } from '../../shared/client.DwfV9Oyl.mjs';
3
+ import { c as StandardRPCLink } from '../../shared/client.8idnGCEC.mjs';
4
4
  import '@orpc/standard-server';
5
- import '../../shared/client.DHOfWE0c.mjs';
5
+ import '../../shared/client.Ct2dObnC.mjs';
6
+ import '@orpc/standard-server-fetch';
6
7
 
8
+ const WEBSOCKET_CONNECTING = 0;
7
9
  class LinkWebsocketClient {
8
10
  peer;
9
11
  constructor(options) {
10
12
  const untilOpen = new Promise((resolve) => {
11
- if (options.websocket.readyState === 0) {
13
+ if (options.websocket.readyState === WEBSOCKET_CONNECTING) {
12
14
  options.websocket.addEventListener("open", () => {
13
15
  resolve();
14
16
  }, { once: true });
@@ -37,7 +39,7 @@ class LinkWebsocketClient {
37
39
  class RPCLink extends StandardRPCLink {
38
40
  constructor(options) {
39
41
  const linkClient = new LinkWebsocketClient(options);
40
- super(linkClient, { ...options, url: "orpc:/" });
42
+ super(linkClient, { ...options, url: "orpc://localhost" });
41
43
  }
42
44
  }
43
45
 
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { N as NestedClient, C as ClientLink, I as InferClientContext, a as ClientPromiseResult, b as ClientContext, F as FriendlyClientOptions, c as ClientOptions, d as Client, e as ClientRest } from './shared/client.BOYsZIRq.mjs';
2
2
  export { f as HTTPMethod, H as HTTPPath } from './shared/client.BOYsZIRq.mjs';
3
- import { MaybeOptionalOptions, ThrowableError, Promisable, AsyncIteratorClass } from '@orpc/shared';
4
- export { EventPublisher, EventPublisherOptions, EventPublisherSubscribeIteratorOptions, Registry, ThrowableError, onError, onFinish, onStart, onSuccess } from '@orpc/shared';
3
+ import { MaybeOptionalOptions, ThrowableError, OnFinishState, Promisable, AsyncIteratorClass } from '@orpc/shared';
4
+ export { AsyncIteratorClass, EventPublisher, EventPublisherOptions, EventPublisherSubscribeIteratorOptions, Registry, ThrowableError, asyncIteratorToStream as eventIteratorToStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@orpc/shared';
5
5
  export { ErrorEvent } from '@orpc/standard-server';
6
6
 
7
7
  interface createORPCClientOptions {
@@ -113,8 +113,21 @@ declare class ORPCError<TCode extends ORPCErrorCode, TData> extends Error {
113
113
  readonly code: TCode;
114
114
  readonly status: number;
115
115
  readonly data: TData;
116
- constructor(code: TCode, ...[options]: MaybeOptionalOptions<ORPCErrorOptions<TData>>);
116
+ constructor(code: TCode, ...rest: MaybeOptionalOptions<ORPCErrorOptions<TData>>);
117
117
  toJSON(): ORPCErrorJSON<TCode, TData>;
118
+ /**
119
+ * Workaround for Next.js where different contexts use separate
120
+ * dependency graphs, causing multiple ORPCError constructors existing and breaking
121
+ * `instanceof` checks across contexts.
122
+ *
123
+ * This is particularly problematic with "Optimized SSR", where orpc-client
124
+ * executes in one context but is invoked from another. When an error is thrown
125
+ * in the execution context, `instanceof ORPCError` checks fail in the
126
+ * invocation context due to separate class constructors.
127
+ *
128
+ * @todo Remove this and related code if Next.js resolves the multiple dependency graph issue.
129
+ */
130
+ static [Symbol.hasInstance](instance: unknown): boolean;
118
131
  }
119
132
  type ORPCErrorJSON<TCode extends string, TData> = Pick<ORPCError<TCode, TData>, 'defined' | 'code' | 'status' | 'message' | 'data'>;
120
133
  declare function isDefinedError<T>(error: T): error is Extract<T, ORPCError<any, any>>;
@@ -147,6 +160,35 @@ type SafeResult<TOutput, TError> = [error: null, data: TOutput, isDefined: false
147
160
  */
148
161
  declare function safe<TOutput, TError = ThrowableError>(promise: ClientPromiseResult<TOutput, TError>): Promise<SafeResult<TOutput, TError>>;
149
162
  declare function resolveFriendlyClientOptions<T extends ClientContext>(options: FriendlyClientOptions<T>): ClientOptions<T>;
163
+ interface ConsumeEventIteratorOptions<T, TReturn, TError> {
164
+ /**
165
+ * Called on each event
166
+ */
167
+ onEvent: (event: T) => void;
168
+ /**
169
+ * Called once error happens
170
+ */
171
+ onError?: (error: TError) => void;
172
+ /**
173
+ * Called once event iterator is done
174
+ *
175
+ * @info If iterator is canceled, `undefined` can be passed on success
176
+ */
177
+ onSuccess?: (value: TReturn | undefined) => void;
178
+ /**
179
+ * Called once after onError or onSuccess
180
+ *
181
+ * @info If iterator is canceled, `undefined` can be passed on success
182
+ */
183
+ onFinish?: (state: OnFinishState<TReturn | undefined, TError>) => void;
184
+ }
185
+ /**
186
+ * Consumes an event iterator with lifecycle callbacks
187
+ *
188
+ * @warning If no `onError` or `onFinish` is provided, unhandled rejections will be thrown
189
+ * @return unsubscribe callback
190
+ */
191
+ declare function consumeEventIterator<T, TReturn, TError = ThrowableError>(iterator: AsyncIterator<T, TReturn> | ClientPromiseResult<AsyncIterator<T, TReturn>, TError>, options: ConsumeEventIteratorOptions<T, TReturn, TError>): () => Promise<void>;
150
192
 
151
193
  type SafeClient<T extends NestedClient<any>> = T extends Client<infer UContext, infer UInput, infer UOutput, infer UError> ? (...rest: ClientRest<UContext, UInput>) => Promise<SafeResult<UOutput, UError>> : {
152
194
  [K in keyof T]: T[K] extends NestedClient<any> ? SafeClient<T[K]> : never;
@@ -164,6 +206,9 @@ type SafeClient<T extends NestedClient<any>> = T extends Client<infer UContext,
164
206
  */
165
207
  declare function createSafeClient<T extends NestedClient<any>>(client: T): SafeClient<T>;
166
208
 
209
+ declare const ORPC_CLIENT_PACKAGE_NAME = "@orpc/client";
210
+ declare const ORPC_CLIENT_PACKAGE_VERSION = "0.0.0-next.ca5123c";
211
+
167
212
  /**
168
213
  * DynamicLink provides a way to dynamically resolve and delegate calls to other ClientLinks
169
214
  * based on the request path, input, and context.
@@ -181,5 +226,5 @@ declare function mapEventIterator<TYield, TReturn, TNext, TMap = TYield | TRetur
181
226
  error: (error: unknown) => Promise<unknown>;
182
227
  }): AsyncIteratorClass<TMap, TMap, TNext>;
183
228
 
184
- export { COMMON_ORPC_ERROR_DEFS, Client, ClientContext, ClientLink, ClientOptions, ClientPromiseResult, ClientRest, DynamicLink, FriendlyClientOptions, InferClientContext, NestedClient, ORPCError, createORPCClient, createORPCErrorFromJson, createSafeClient, fallbackORPCErrorMessage, fallbackORPCErrorStatus, isDefinedError, isORPCErrorJson, isORPCErrorStatus, mapEventIterator, resolveFriendlyClientOptions, safe, toORPCError };
185
- export type { CommonORPCErrorCode, ORPCErrorCode, ORPCErrorJSON, ORPCErrorOptions, SafeClient, SafeResult, createORPCClientOptions };
229
+ export { COMMON_ORPC_ERROR_DEFS, Client, ClientContext, ClientLink, ClientOptions, ClientPromiseResult, ClientRest, DynamicLink, FriendlyClientOptions, InferClientContext, NestedClient, ORPCError, ORPC_CLIENT_PACKAGE_NAME, ORPC_CLIENT_PACKAGE_VERSION, consumeEventIterator, createORPCClient, createORPCErrorFromJson, createSafeClient, fallbackORPCErrorMessage, fallbackORPCErrorStatus, isDefinedError, isORPCErrorJson, isORPCErrorStatus, mapEventIterator, resolveFriendlyClientOptions, safe, toORPCError };
230
+ export type { CommonORPCErrorCode, ConsumeEventIteratorOptions, ORPCErrorCode, ORPCErrorJSON, ORPCErrorOptions, SafeClient, SafeResult, createORPCClientOptions };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { N as NestedClient, C as ClientLink, I as InferClientContext, a as ClientPromiseResult, b as ClientContext, F as FriendlyClientOptions, c as ClientOptions, d as Client, e as ClientRest } from './shared/client.BOYsZIRq.js';
2
2
  export { f as HTTPMethod, H as HTTPPath } from './shared/client.BOYsZIRq.js';
3
- import { MaybeOptionalOptions, ThrowableError, Promisable, AsyncIteratorClass } from '@orpc/shared';
4
- export { EventPublisher, EventPublisherOptions, EventPublisherSubscribeIteratorOptions, Registry, ThrowableError, onError, onFinish, onStart, onSuccess } from '@orpc/shared';
3
+ import { MaybeOptionalOptions, ThrowableError, OnFinishState, Promisable, AsyncIteratorClass } from '@orpc/shared';
4
+ export { AsyncIteratorClass, EventPublisher, EventPublisherOptions, EventPublisherSubscribeIteratorOptions, Registry, ThrowableError, asyncIteratorToStream as eventIteratorToStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@orpc/shared';
5
5
  export { ErrorEvent } from '@orpc/standard-server';
6
6
 
7
7
  interface createORPCClientOptions {
@@ -113,8 +113,21 @@ declare class ORPCError<TCode extends ORPCErrorCode, TData> extends Error {
113
113
  readonly code: TCode;
114
114
  readonly status: number;
115
115
  readonly data: TData;
116
- constructor(code: TCode, ...[options]: MaybeOptionalOptions<ORPCErrorOptions<TData>>);
116
+ constructor(code: TCode, ...rest: MaybeOptionalOptions<ORPCErrorOptions<TData>>);
117
117
  toJSON(): ORPCErrorJSON<TCode, TData>;
118
+ /**
119
+ * Workaround for Next.js where different contexts use separate
120
+ * dependency graphs, causing multiple ORPCError constructors existing and breaking
121
+ * `instanceof` checks across contexts.
122
+ *
123
+ * This is particularly problematic with "Optimized SSR", where orpc-client
124
+ * executes in one context but is invoked from another. When an error is thrown
125
+ * in the execution context, `instanceof ORPCError` checks fail in the
126
+ * invocation context due to separate class constructors.
127
+ *
128
+ * @todo Remove this and related code if Next.js resolves the multiple dependency graph issue.
129
+ */
130
+ static [Symbol.hasInstance](instance: unknown): boolean;
118
131
  }
119
132
  type ORPCErrorJSON<TCode extends string, TData> = Pick<ORPCError<TCode, TData>, 'defined' | 'code' | 'status' | 'message' | 'data'>;
120
133
  declare function isDefinedError<T>(error: T): error is Extract<T, ORPCError<any, any>>;
@@ -147,6 +160,35 @@ type SafeResult<TOutput, TError> = [error: null, data: TOutput, isDefined: false
147
160
  */
148
161
  declare function safe<TOutput, TError = ThrowableError>(promise: ClientPromiseResult<TOutput, TError>): Promise<SafeResult<TOutput, TError>>;
149
162
  declare function resolveFriendlyClientOptions<T extends ClientContext>(options: FriendlyClientOptions<T>): ClientOptions<T>;
163
+ interface ConsumeEventIteratorOptions<T, TReturn, TError> {
164
+ /**
165
+ * Called on each event
166
+ */
167
+ onEvent: (event: T) => void;
168
+ /**
169
+ * Called once error happens
170
+ */
171
+ onError?: (error: TError) => void;
172
+ /**
173
+ * Called once event iterator is done
174
+ *
175
+ * @info If iterator is canceled, `undefined` can be passed on success
176
+ */
177
+ onSuccess?: (value: TReturn | undefined) => void;
178
+ /**
179
+ * Called once after onError or onSuccess
180
+ *
181
+ * @info If iterator is canceled, `undefined` can be passed on success
182
+ */
183
+ onFinish?: (state: OnFinishState<TReturn | undefined, TError>) => void;
184
+ }
185
+ /**
186
+ * Consumes an event iterator with lifecycle callbacks
187
+ *
188
+ * @warning If no `onError` or `onFinish` is provided, unhandled rejections will be thrown
189
+ * @return unsubscribe callback
190
+ */
191
+ declare function consumeEventIterator<T, TReturn, TError = ThrowableError>(iterator: AsyncIterator<T, TReturn> | ClientPromiseResult<AsyncIterator<T, TReturn>, TError>, options: ConsumeEventIteratorOptions<T, TReturn, TError>): () => Promise<void>;
150
192
 
151
193
  type SafeClient<T extends NestedClient<any>> = T extends Client<infer UContext, infer UInput, infer UOutput, infer UError> ? (...rest: ClientRest<UContext, UInput>) => Promise<SafeResult<UOutput, UError>> : {
152
194
  [K in keyof T]: T[K] extends NestedClient<any> ? SafeClient<T[K]> : never;
@@ -164,6 +206,9 @@ type SafeClient<T extends NestedClient<any>> = T extends Client<infer UContext,
164
206
  */
165
207
  declare function createSafeClient<T extends NestedClient<any>>(client: T): SafeClient<T>;
166
208
 
209
+ declare const ORPC_CLIENT_PACKAGE_NAME = "@orpc/client";
210
+ declare const ORPC_CLIENT_PACKAGE_VERSION = "0.0.0-next.ca5123c";
211
+
167
212
  /**
168
213
  * DynamicLink provides a way to dynamically resolve and delegate calls to other ClientLinks
169
214
  * based on the request path, input, and context.
@@ -181,5 +226,5 @@ declare function mapEventIterator<TYield, TReturn, TNext, TMap = TYield | TRetur
181
226
  error: (error: unknown) => Promise<unknown>;
182
227
  }): AsyncIteratorClass<TMap, TMap, TNext>;
183
228
 
184
- export { COMMON_ORPC_ERROR_DEFS, Client, ClientContext, ClientLink, ClientOptions, ClientPromiseResult, ClientRest, DynamicLink, FriendlyClientOptions, InferClientContext, NestedClient, ORPCError, createORPCClient, createORPCErrorFromJson, createSafeClient, fallbackORPCErrorMessage, fallbackORPCErrorStatus, isDefinedError, isORPCErrorJson, isORPCErrorStatus, mapEventIterator, resolveFriendlyClientOptions, safe, toORPCError };
185
- export type { CommonORPCErrorCode, ORPCErrorCode, ORPCErrorJSON, ORPCErrorOptions, SafeClient, SafeResult, createORPCClientOptions };
229
+ export { COMMON_ORPC_ERROR_DEFS, Client, ClientContext, ClientLink, ClientOptions, ClientPromiseResult, ClientRest, DynamicLink, FriendlyClientOptions, InferClientContext, NestedClient, ORPCError, ORPC_CLIENT_PACKAGE_NAME, ORPC_CLIENT_PACKAGE_VERSION, consumeEventIterator, createORPCClient, createORPCErrorFromJson, createSafeClient, fallbackORPCErrorMessage, fallbackORPCErrorStatus, isDefinedError, isORPCErrorJson, isORPCErrorStatus, mapEventIterator, resolveFriendlyClientOptions, safe, toORPCError };
230
+ export type { CommonORPCErrorCode, ConsumeEventIteratorOptions, ORPCErrorCode, ORPCErrorJSON, ORPCErrorOptions, SafeClient, SafeResult, createORPCClientOptions };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { i as isDefinedError } from './shared/client.DHOfWE0c.mjs';
2
- export { C as COMMON_ORPC_ERROR_DEFS, O as ORPCError, d as createORPCErrorFromJson, a as fallbackORPCErrorMessage, f as fallbackORPCErrorStatus, c as isORPCErrorJson, b as isORPCErrorStatus, m as mapEventIterator, t as toORPCError } from './shared/client.DHOfWE0c.mjs';
3
- import { isTypescriptObject } from '@orpc/shared';
4
- export { EventPublisher, onError, onFinish, onStart, onSuccess } from '@orpc/shared';
1
+ import { preventNativeAwait, isTypescriptObject } from '@orpc/shared';
2
+ export { AsyncIteratorClass, EventPublisher, asyncIteratorToStream as eventIteratorToStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@orpc/shared';
3
+ import { i as isDefinedError } from './shared/client.Ct2dObnC.mjs';
4
+ export { C as COMMON_ORPC_ERROR_DEFS, c as ORPCError, O as ORPC_CLIENT_PACKAGE_NAME, a as ORPC_CLIENT_PACKAGE_VERSION, g as createORPCErrorFromJson, b as fallbackORPCErrorMessage, f as fallbackORPCErrorStatus, e as isORPCErrorJson, d as isORPCErrorStatus, m as mapEventIterator, t as toORPCError } from './shared/client.Ct2dObnC.mjs';
5
5
  export { ErrorEvent } from '@orpc/standard-server';
6
6
 
7
7
  async function safe(promise) {
@@ -32,6 +32,35 @@ function resolveFriendlyClientOptions(options) {
32
32
  // Context only optional if all fields are optional
33
33
  };
34
34
  }
35
+ function consumeEventIterator(iterator, options) {
36
+ void (async () => {
37
+ let onFinishState;
38
+ try {
39
+ const resolvedIterator = await iterator;
40
+ while (true) {
41
+ const { done, value } = await resolvedIterator.next();
42
+ if (done) {
43
+ const realValue = value;
44
+ onFinishState = [null, realValue, true];
45
+ options.onSuccess?.(realValue);
46
+ break;
47
+ }
48
+ options.onEvent(value);
49
+ }
50
+ } catch (error) {
51
+ onFinishState = [error, void 0, false];
52
+ if (!options.onError && !options.onFinish) {
53
+ throw error;
54
+ }
55
+ options.onError?.(error);
56
+ } finally {
57
+ options.onFinish?.(onFinishState);
58
+ }
59
+ })();
60
+ return async () => {
61
+ await (await iterator)?.return?.();
62
+ };
63
+ }
35
64
 
36
65
  function createORPCClient(link, options = {}) {
37
66
  const path = options.path ?? [];
@@ -49,7 +78,7 @@ function createORPCClient(link, options = {}) {
49
78
  });
50
79
  }
51
80
  });
52
- return recursive;
81
+ return preventNativeAwait(recursive);
53
82
  }
54
83
 
55
84
  function createSafeClient(client) {
@@ -79,4 +108,4 @@ class DynamicLink {
79
108
  }
80
109
  }
81
110
 
82
- export { DynamicLink, createORPCClient, createSafeClient, isDefinedError, resolveFriendlyClientOptions, safe };
111
+ export { DynamicLink, consumeEventIterator, createORPCClient, createSafeClient, isDefinedError, resolveFriendlyClientOptions, safe };
@@ -1,7 +1,7 @@
1
1
  import { Value, Promisable } from '@orpc/shared';
2
2
  import { StandardHeaders, StandardRequest } from '@orpc/standard-server';
3
3
  import { BatchResponseMode } from '@orpc/standard-server/batch';
4
- import { S as StandardLinkClientInterceptorOptions, a as StandardLinkPlugin, b as StandardLinkOptions, c as StandardLinkInterceptorOptions } from '../shared/client.C4VxIexA.mjs';
4
+ import { S as StandardLinkClientInterceptorOptions, a as StandardLinkPlugin, b as StandardLinkOptions, c as StandardLinkInterceptorOptions } from '../shared/client.Bwgm6dgk.mjs';
5
5
  import { b as ClientContext } from '../shared/client.BOYsZIRq.mjs';
6
6
 
7
7
  interface BatchLinkPluginGroup<T extends ClientContext> {
@@ -157,6 +157,7 @@ declare class ClientRetryPlugin<T extends ClientRetryPluginContext> implements S
157
157
  private readonly defaultRetryDelay;
158
158
  private readonly defaultShouldRetry;
159
159
  private readonly defaultOnRetry;
160
+ order: number;
160
161
  constructor(options?: ClientRetryPluginOptions);
161
162
  init(options: StandardLinkOptions<T>): void;
162
163
  }
@@ -1,7 +1,7 @@
1
1
  import { Value, Promisable } from '@orpc/shared';
2
2
  import { StandardHeaders, StandardRequest } from '@orpc/standard-server';
3
3
  import { BatchResponseMode } from '@orpc/standard-server/batch';
4
- import { S as StandardLinkClientInterceptorOptions, a as StandardLinkPlugin, b as StandardLinkOptions, c as StandardLinkInterceptorOptions } from '../shared/client.CXXEPIbK.js';
4
+ import { S as StandardLinkClientInterceptorOptions, a as StandardLinkPlugin, b as StandardLinkOptions, c as StandardLinkInterceptorOptions } from '../shared/client.BG98rYdO.js';
5
5
  import { b as ClientContext } from '../shared/client.BOYsZIRq.js';
6
6
 
7
7
  interface BatchLinkPluginGroup<T extends ClientContext> {
@@ -157,6 +157,7 @@ declare class ClientRetryPlugin<T extends ClientRetryPluginContext> implements S
157
157
  private readonly defaultRetryDelay;
158
158
  private readonly defaultShouldRetry;
159
159
  private readonly defaultOnRetry;
160
+ order: number;
160
161
  constructor(options?: ClientRetryPluginOptions);
161
162
  init(options: StandardLinkOptions<T>): void;
162
163
  }
@@ -1,4 +1,4 @@
1
- import { isAsyncIteratorObject, defer, value, splitInHalf, toArray, stringifyJSON } from '@orpc/shared';
1
+ import { isAsyncIteratorObject, defer, value, splitInHalf, toArray, stringifyJSON, overlayProxy, AsyncIteratorClass } from '@orpc/shared';
2
2
  import { toBatchRequest, parseBatchResponse, toBatchAbortSignal } from '@orpc/standard-server/batch';
3
3
  import { replicateStandardLazyResponse, getEventMeta } from '@orpc/standard-server';
4
4
 
@@ -64,7 +64,7 @@ class BatchLinkPlugin {
64
64
  });
65
65
  });
66
66
  options.clientInterceptors.push((options2) => {
67
- if (this.exclude(options2) || options2.request.body instanceof Blob || options2.request.body instanceof FormData || isAsyncIteratorObject(options2.request.body)) {
67
+ if (this.exclude(options2) || options2.request.body instanceof Blob || options2.request.body instanceof FormData || isAsyncIteratorObject(options2.request.body) || options2.request.signal?.aborted) {
68
68
  return options2.next();
69
69
  }
70
70
  const group = this.groups.find((group2) => group2.condition(options2));
@@ -130,16 +130,27 @@ class BatchLinkPlugin {
130
130
  return;
131
131
  }
132
132
  const mode = value(this.mode, options);
133
- const lazyResponse = await options[0].next({
134
- request: { ...batchRequest, headers: { ...batchRequest.headers, "x-orpc-batch": mode } },
135
- signal: batchRequest.signal,
136
- context: group.context,
137
- input: group.input,
138
- path: toArray(group.path)
139
- });
140
- const parsed = parseBatchResponse({ ...lazyResponse, body: await lazyResponse.body() });
141
- for await (const item of parsed) {
142
- batchItems[item.index]?.[1]({ ...item, body: () => Promise.resolve(item.body) });
133
+ try {
134
+ const lazyResponse = await options[0].next({
135
+ request: { ...batchRequest, headers: { ...batchRequest.headers, "x-orpc-batch": mode } },
136
+ signal: batchRequest.signal,
137
+ context: group.context,
138
+ input: group.input,
139
+ path: toArray(group.path)
140
+ });
141
+ const parsed = parseBatchResponse({ ...lazyResponse, body: await lazyResponse.body() });
142
+ for await (const item of parsed) {
143
+ batchItems[item.index]?.[1]({ ...item, body: () => Promise.resolve(item.body) });
144
+ }
145
+ } catch (err) {
146
+ if (batchRequest.signal?.aborted && batchRequest.signal.reason === err) {
147
+ for (const [{ signal }, , reject] of batchItems) {
148
+ if (signal?.aborted) {
149
+ reject(signal.reason);
150
+ }
151
+ }
152
+ }
153
+ throw err;
143
154
  }
144
155
  throw new Error("Something went wrong make batch response not contains enough responses. This can be a bug please report it.");
145
156
  } catch (error) {
@@ -252,6 +263,7 @@ class ClientRetryPlugin {
252
263
  defaultRetryDelay;
253
264
  defaultShouldRetry;
254
265
  defaultOnRetry;
266
+ order = 18e5;
255
267
  constructor(options = {}) {
256
268
  this.defaultRetry = options.default?.retry ?? 0;
257
269
  this.defaultRetryDelay = options.default?.retryDelay ?? ((o) => o.lastEventRetry ?? 2e3);
@@ -306,7 +318,7 @@ class ClientRetryPlugin {
306
318
  return await interceptorOptions.next(updatedInterceptorOptions);
307
319
  } catch (error) {
308
320
  currentError = { error };
309
- if (updatedInterceptorOptions.signal?.aborted === true) {
321
+ if (updatedInterceptorOptions.signal?.aborted) {
310
322
  throw error;
311
323
  }
312
324
  } finally {
@@ -319,19 +331,17 @@ class ClientRetryPlugin {
319
331
  if (!isAsyncIteratorObject(output)) {
320
332
  return output;
321
333
  }
322
- return async function* () {
323
- let current = output;
324
- try {
334
+ let current = output;
335
+ let isIteratorAborted = false;
336
+ return overlayProxy(() => current, new AsyncIteratorClass(
337
+ async () => {
325
338
  while (true) {
326
339
  try {
327
340
  const item = await current.next();
328
341
  const meta = getEventMeta(item.value);
329
342
  lastEventId = meta?.id ?? lastEventId;
330
343
  lastEventRetry = meta?.retry ?? lastEventRetry;
331
- if (item.done) {
332
- return item.value;
333
- }
334
- yield item.value;
344
+ return item;
335
345
  } catch (error) {
336
346
  const meta = getEventMeta(error);
337
347
  lastEventId = meta?.id ?? lastEventId;
@@ -343,12 +353,20 @@ class ClientRetryPlugin {
343
353
  );
344
354
  }
345
355
  current = maybeEventIterator;
356
+ if (isIteratorAborted) {
357
+ await current.return?.();
358
+ throw error;
359
+ }
346
360
  }
347
361
  }
348
- } finally {
349
- await current.return?.();
362
+ },
363
+ async (reason) => {
364
+ isIteratorAborted = true;
365
+ if (reason !== "next") {
366
+ await current.return?.();
367
+ }
350
368
  }
351
- }();
369
+ ));
352
370
  });
353
371
  }
354
372
  }
@@ -1,6 +1,7 @@
1
- import { toArray, intercept, isObject, value, isAsyncIteratorObject, stringifyJSON } from '@orpc/shared';
1
+ import { toArray, runWithSpan, ORPC_NAME, isAsyncIteratorObject, asyncIteratorWithSpan, intercept, getGlobalOtelConfig, isObject, value, stringifyJSON } from '@orpc/shared';
2
2
  import { mergeStandardHeaders, ErrorEvent } from '@orpc/standard-server';
3
- import { C as COMMON_ORPC_ERROR_DEFS, b as isORPCErrorStatus, c as isORPCErrorJson, d as createORPCErrorFromJson, O as ORPCError, m as mapEventIterator, t as toORPCError } from './client.DHOfWE0c.mjs';
3
+ import { C as COMMON_ORPC_ERROR_DEFS, d as isORPCErrorStatus, e as isORPCErrorJson, g as createORPCErrorFromJson, c as ORPCError, m as mapEventIterator, t as toORPCError } from './client.Ct2dObnC.mjs';
4
+ import { toStandardHeaders as toStandardHeaders$1 } from '@orpc/standard-server-fetch';
4
5
 
5
6
  class CompositeStandardLinkPlugin {
6
7
  plugins;
@@ -26,20 +27,52 @@ class StandardLink {
26
27
  interceptors;
27
28
  clientInterceptors;
28
29
  call(path, input, options) {
29
- return intercept(this.interceptors, { ...options, path, input }, async ({ path: path2, input: input2, ...options2 }) => {
30
- const output = await this.#call(path2, input2, options2);
31
- return output;
32
- });
33
- }
34
- async #call(path, input, options) {
35
- const request = await this.codec.encode(path, input, options);
36
- const response = await intercept(
37
- this.clientInterceptors,
38
- { ...options, input, path, request },
39
- ({ input: input2, path: path2, request: request2, ...options2 }) => this.sender.call(request2, options2, path2, input2)
30
+ return runWithSpan(
31
+ { name: `${ORPC_NAME}.${path.join("/")}`, signal: options.signal },
32
+ (span) => {
33
+ span?.setAttribute("rpc.system", ORPC_NAME);
34
+ span?.setAttribute("rpc.method", path.join("."));
35
+ if (isAsyncIteratorObject(input)) {
36
+ input = asyncIteratorWithSpan(
37
+ { name: "consume_event_iterator_input", signal: options.signal },
38
+ input
39
+ );
40
+ }
41
+ return intercept(this.interceptors, { ...options, path, input }, async ({ path: path2, input: input2, ...options2 }) => {
42
+ const otelConfig = getGlobalOtelConfig();
43
+ let otelContext;
44
+ const currentSpan = otelConfig?.trace.getActiveSpan() ?? span;
45
+ if (currentSpan && otelConfig) {
46
+ otelContext = otelConfig?.trace.setSpan(otelConfig.context.active(), currentSpan);
47
+ }
48
+ const request = await runWithSpan(
49
+ { name: "encode_request", context: otelContext },
50
+ () => this.codec.encode(path2, input2, options2)
51
+ );
52
+ const response = await intercept(
53
+ this.clientInterceptors,
54
+ { ...options2, input: input2, path: path2, request },
55
+ ({ input: input3, path: path3, request: request2, ...options3 }) => {
56
+ return runWithSpan(
57
+ { name: "send_request", signal: options3.signal, context: otelContext },
58
+ () => this.sender.call(request2, options3, path3, input3)
59
+ );
60
+ }
61
+ );
62
+ const output = await runWithSpan(
63
+ { name: "decode_response", context: otelContext },
64
+ () => this.codec.decode(response, options2, path2, input2)
65
+ );
66
+ if (isAsyncIteratorObject(output)) {
67
+ return asyncIteratorWithSpan(
68
+ { name: "consume_event_iterator_output", signal: options2.signal },
69
+ output
70
+ );
71
+ }
72
+ return output;
73
+ });
74
+ }
40
75
  );
41
- const output = await this.codec.decode(response, options, path, input);
42
- return output;
43
76
  }
44
77
  }
45
78
 
@@ -192,6 +225,12 @@ class StandardRPCJsonSerializer {
192
225
  function toHttpPath(path) {
193
226
  return `/${path.map(encodeURIComponent).join("/")}`;
194
227
  }
228
+ function toStandardHeaders(headers) {
229
+ if (typeof headers.forEach === "function") {
230
+ return toStandardHeaders$1(headers);
231
+ }
232
+ return headers;
233
+ }
195
234
  function getMalformedResponseErrorCode(status) {
196
235
  return Object.entries(COMMON_ORPC_ERROR_DEFS).find(([, def]) => def.status === status)?.[0] ?? "MALFORMED_ORPC_ERROR_RESPONSE";
197
236
  }
@@ -211,14 +250,14 @@ class StandardRPCLinkCodec {
211
250
  expectedMethod;
212
251
  headers;
213
252
  async encode(path, input, options) {
253
+ let headers = toStandardHeaders(await value(this.headers, options, path, input));
254
+ if (options.lastEventId !== void 0) {
255
+ headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId });
256
+ }
214
257
  const expectedMethod = await value(this.expectedMethod, options, path, input);
215
- let headers = await value(this.headers, options, path, input);
216
258
  const baseUrl = await value(this.baseUrl, options, path, input);
217
259
  const url = new URL(baseUrl);
218
260
  url.pathname = `${url.pathname.replace(/\/$/, "")}${toHttpPath(path)}`;
219
- if (options.lastEventId !== void 0) {
220
- headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId });
221
- }
222
261
  const serialized = this.serializer.serialize(input);
223
262
  if (expectedMethod === "GET" && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) {
224
263
  const maxUrlLength = await value(this.maxUrlLength, options, path, input);
@@ -330,6 +369,9 @@ class StandardRPCSerializer {
330
369
  return this.#deserialize(data);
331
370
  }
332
371
  #deserialize(data) {
372
+ if (data === void 0) {
373
+ return void 0;
374
+ }
333
375
  if (!(data instanceof FormData)) {
334
376
  return this.jsonSerializer.deserialize(data.json, data.meta ?? []);
335
377
  }
@@ -352,4 +394,4 @@ class StandardRPCLink extends StandardLink {
352
394
  }
353
395
  }
354
396
 
355
- export { CompositeStandardLinkPlugin as C, StandardLink as S, STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as a, StandardRPCJsonSerializer as b, StandardRPCLink as c, StandardRPCLinkCodec as d, StandardRPCSerializer as e, getMalformedResponseErrorCode as g, toHttpPath as t };
397
+ export { CompositeStandardLinkPlugin as C, StandardLink as S, STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as a, StandardRPCJsonSerializer as b, StandardRPCLink as c, StandardRPCLinkCodec as d, StandardRPCSerializer as e, toStandardHeaders as f, getMalformedResponseErrorCode as g, toHttpPath as t };
@@ -33,7 +33,6 @@ interface StandardLinkOptions<T extends ClientContext> {
33
33
  plugins?: StandardLinkPlugin<T>[];
34
34
  }
35
35
  declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
36
- #private;
37
36
  readonly codec: StandardLinkCodec<T>;
38
37
  readonly sender: StandardLinkClient<T>;
39
38
  private readonly interceptors;
@@ -33,7 +33,6 @@ interface StandardLinkOptions<T extends ClientContext> {
33
33
  plugins?: StandardLinkPlugin<T>[];
34
34
  }
35
35
  declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
36
- #private;
37
36
  readonly codec: StandardLinkCodec<T>;
38
37
  readonly sender: StandardLinkClient<T>;
39
38
  private readonly interceptors;
@@ -1,5 +1,5 @@
1
1
  import { b as ClientContext, c as ClientOptions, f as HTTPMethod } from './client.BOYsZIRq.js';
2
- import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.CXXEPIbK.js';
2
+ import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.BG98rYdO.js';
3
3
  import { Segment, Value, Promisable } from '@orpc/shared';
4
4
  import { StandardHeaders, StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
5
5
 
@@ -67,7 +67,7 @@ interface StandardRPCLinkCodecOptions<T extends ClientContext> {
67
67
  /**
68
68
  * Inject headers to the request.
69
69
  */
70
- headers?: Value<Promisable<StandardHeaders>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
70
+ headers?: Value<Promisable<StandardHeaders | Headers>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
71
71
  }
72
72
  declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardLinkCodec<T> {
73
73
  private readonly serializer;
@@ -1,6 +1,9 @@
1
- import { isObject, AsyncIteratorClass, isTypescriptObject } from '@orpc/shared';
1
+ import { resolveMaybeOptionalOptions, getConstructor, isObject, AsyncIteratorClass, isTypescriptObject } from '@orpc/shared';
2
2
  import { getEventMeta, withEventMeta } from '@orpc/standard-server';
3
3
 
4
+ const ORPC_CLIENT_PACKAGE_NAME = "@orpc/client";
5
+ const ORPC_CLIENT_PACKAGE_VERSION = "0.0.0-next.ca5123c";
6
+
4
7
  const COMMON_ORPC_ERROR_DEFS = {
5
8
  BAD_REQUEST: {
6
9
  status: 400,
@@ -85,21 +88,25 @@ function fallbackORPCErrorStatus(code, status) {
85
88
  function fallbackORPCErrorMessage(code, message) {
86
89
  return message || COMMON_ORPC_ERROR_DEFS[code]?.message || code;
87
90
  }
91
+ const GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL = Symbol.for(`__${ORPC_CLIENT_PACKAGE_NAME}@${ORPC_CLIENT_PACKAGE_VERSION}/error/ORPC_ERROR_CONSTRUCTORS__`);
92
+ void (globalThis[GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL] ??= /* @__PURE__ */ new WeakSet());
93
+ const globalORPCErrorConstructors = globalThis[GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL];
88
94
  class ORPCError extends Error {
89
95
  defined;
90
96
  code;
91
97
  status;
92
98
  data;
93
- constructor(code, ...[options]) {
94
- if (options?.status && !isORPCErrorStatus(options.status)) {
99
+ constructor(code, ...rest) {
100
+ const options = resolveMaybeOptionalOptions(rest);
101
+ if (options.status !== void 0 && !isORPCErrorStatus(options.status)) {
95
102
  throw new Error("[ORPCError] Invalid error status code.");
96
103
  }
97
- const message = fallbackORPCErrorMessage(code, options?.message);
104
+ const message = fallbackORPCErrorMessage(code, options.message);
98
105
  super(message, options);
99
106
  this.code = code;
100
- this.status = fallbackORPCErrorStatus(code, options?.status);
101
- this.defined = options?.defined ?? false;
102
- this.data = options?.data;
107
+ this.status = fallbackORPCErrorStatus(code, options.status);
108
+ this.defined = options.defined ?? false;
109
+ this.data = options.data;
103
110
  }
104
111
  toJSON() {
105
112
  return {
@@ -110,7 +117,29 @@ class ORPCError extends Error {
110
117
  data: this.data
111
118
  };
112
119
  }
120
+ /**
121
+ * Workaround for Next.js where different contexts use separate
122
+ * dependency graphs, causing multiple ORPCError constructors existing and breaking
123
+ * `instanceof` checks across contexts.
124
+ *
125
+ * This is particularly problematic with "Optimized SSR", where orpc-client
126
+ * executes in one context but is invoked from another. When an error is thrown
127
+ * in the execution context, `instanceof ORPCError` checks fail in the
128
+ * invocation context due to separate class constructors.
129
+ *
130
+ * @todo Remove this and related code if Next.js resolves the multiple dependency graph issue.
131
+ */
132
+ static [Symbol.hasInstance](instance) {
133
+ if (globalORPCErrorConstructors.has(this)) {
134
+ const constructor = getConstructor(instance);
135
+ if (constructor && globalORPCErrorConstructors.has(constructor)) {
136
+ return true;
137
+ }
138
+ }
139
+ return super[Symbol.hasInstance](instance);
140
+ }
113
141
  }
142
+ globalORPCErrorConstructors.add(ORPCError);
114
143
  function isDefinedError(error) {
115
144
  return error instanceof ORPCError && error.defined;
116
145
  }
@@ -141,19 +170,22 @@ function createORPCErrorFromJson(json, options = {}) {
141
170
  }
142
171
 
143
172
  function mapEventIterator(iterator, maps) {
173
+ const mapError = async (error) => {
174
+ let mappedError = await maps.error(error);
175
+ if (mappedError !== error) {
176
+ const meta = getEventMeta(error);
177
+ if (meta && isTypescriptObject(mappedError)) {
178
+ mappedError = withEventMeta(mappedError, meta);
179
+ }
180
+ }
181
+ return mappedError;
182
+ };
144
183
  return new AsyncIteratorClass(async () => {
145
184
  const { done, value } = await (async () => {
146
185
  try {
147
186
  return await iterator.next();
148
187
  } catch (error) {
149
- let mappedError = await maps.error(error);
150
- if (mappedError !== error) {
151
- const meta = getEventMeta(error);
152
- if (meta && isTypescriptObject(mappedError)) {
153
- mappedError = withEventMeta(mappedError, meta);
154
- }
155
- }
156
- throw mappedError;
188
+ throw await mapError(error);
157
189
  }
158
190
  })();
159
191
  let mappedValue = await maps.value(value, done);
@@ -165,8 +197,12 @@ function mapEventIterator(iterator, maps) {
165
197
  }
166
198
  return { done, value: mappedValue };
167
199
  }, async () => {
168
- await iterator.return?.();
200
+ try {
201
+ await iterator.return?.();
202
+ } catch (error) {
203
+ throw await mapError(error);
204
+ }
169
205
  });
170
206
  }
171
207
 
172
- export { COMMON_ORPC_ERROR_DEFS as C, ORPCError as O, fallbackORPCErrorMessage as a, isORPCErrorStatus as b, isORPCErrorJson as c, createORPCErrorFromJson as d, fallbackORPCErrorStatus as f, isDefinedError as i, mapEventIterator as m, toORPCError as t };
208
+ export { COMMON_ORPC_ERROR_DEFS as C, ORPC_CLIENT_PACKAGE_NAME as O, ORPC_CLIENT_PACKAGE_VERSION as a, fallbackORPCErrorMessage as b, ORPCError as c, isORPCErrorStatus as d, isORPCErrorJson as e, fallbackORPCErrorStatus as f, createORPCErrorFromJson as g, isDefinedError as i, mapEventIterator as m, toORPCError as t };
@@ -1,5 +1,5 @@
1
1
  import { b as ClientContext, c as ClientOptions, f as HTTPMethod } from './client.BOYsZIRq.mjs';
2
- import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.C4VxIexA.mjs';
2
+ import { e as StandardLinkCodec, b as StandardLinkOptions, d as StandardLink, f as StandardLinkClient } from './client.Bwgm6dgk.mjs';
3
3
  import { Segment, Value, Promisable } from '@orpc/shared';
4
4
  import { StandardHeaders, StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
5
5
 
@@ -67,7 +67,7 @@ interface StandardRPCLinkCodecOptions<T extends ClientContext> {
67
67
  /**
68
68
  * Inject headers to the request.
69
69
  */
70
- headers?: Value<Promisable<StandardHeaders>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
70
+ headers?: Value<Promisable<StandardHeaders | Headers>, [options: ClientOptions<T>, path: readonly string[], input: unknown]>;
71
71
  }
72
72
  declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardLinkCodec<T> {
73
73
  private readonly serializer;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/client",
3
3
  "type": "module",
4
- "version": "0.0.0-next.c8607a4",
4
+ "version": "0.0.0-next.ca5123c",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -49,13 +49,13 @@
49
49
  "dist"
50
50
  ],
51
51
  "dependencies": {
52
- "@orpc/shared": "0.0.0-next.c8607a4",
53
- "@orpc/standard-server": "0.0.0-next.c8607a4",
54
- "@orpc/standard-server-fetch": "0.0.0-next.c8607a4",
55
- "@orpc/standard-server-peer": "0.0.0-next.c8607a4"
52
+ "@orpc/shared": "0.0.0-next.ca5123c",
53
+ "@orpc/standard-server-peer": "0.0.0-next.ca5123c",
54
+ "@orpc/standard-server-fetch": "0.0.0-next.ca5123c",
55
+ "@orpc/standard-server": "0.0.0-next.ca5123c"
56
56
  },
57
57
  "devDependencies": {
58
- "zod": "^4.0.5"
58
+ "zod": "^4.1.11"
59
59
  },
60
60
  "scripts": {
61
61
  "build": "unbuild",