@orpc/client 0.45.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/fetch/index.d.mts +24 -96
- package/dist/adapters/fetch/index.d.ts +24 -96
- package/dist/adapters/fetch/index.mjs +24 -111
- package/dist/adapters/standard/index.d.mts +129 -2
- package/dist/adapters/standard/index.d.ts +129 -2
- package/dist/adapters/standard/index.mjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/shared/{client.DHJ8vRIG.mjs → client.Ch8Gzz9n.mjs} +132 -3
- package/dist/shared/{client.Ly4zGQrc.mjs → client.DcaJQZfy.mjs} +1 -1
- package/package.json +4 -4
@@ -1,103 +1,31 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
import {
|
1
|
+
import { C as ClientContext, a as ClientOptionsOut, b as ClientLink } from '../../shared/client.D_CzLDyB.mjs';
|
2
|
+
import { StandardLinkClient, StandardLinkOptions, StandardRPCLinkCodecOptions, StandardRPCLinkCodec } from '../standard/index.mjs';
|
3
|
+
import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
|
4
|
+
import { ToFetchRequestOptions } from '@orpc/standard-server-fetch';
|
5
|
+
import '@orpc/shared';
|
5
6
|
|
6
|
-
interface
|
7
|
-
(
|
7
|
+
interface LinkFetchClientOptions<T extends ClientContext> extends ToFetchRequestOptions {
|
8
|
+
fetch?: (request: Request, init: Record<never, never>, options: ClientOptionsOut<T>, path: readonly string[], input: unknown) => Promise<Response>;
|
9
|
+
}
|
10
|
+
declare class LinkFetchClient<T extends ClientContext> implements StandardLinkClient<T> {
|
11
|
+
private readonly fetch;
|
12
|
+
private readonly toFetchRequestOptions;
|
13
|
+
constructor(options: LinkFetchClientOptions<T>);
|
14
|
+
call(request: StandardRequest, options: ClientOptionsOut<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
|
8
15
|
}
|
9
16
|
|
10
|
-
|
11
|
-
|
17
|
+
interface RPCLinkOptions<T extends ClientContext> extends StandardLinkOptions<T>, StandardRPCLinkCodecOptions<T>, LinkFetchClientOptions<T> {
|
18
|
+
linkCodec?: StandardRPCLinkCodec<T>;
|
19
|
+
linkClient?: LinkFetchClient<T>;
|
12
20
|
}
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
url: string;
|
18
|
-
/**
|
19
|
-
* The maximum length of the URL.
|
20
|
-
*
|
21
|
-
* @default 2083
|
22
|
-
*/
|
23
|
-
maxUrlLength?: number;
|
24
|
-
/**
|
25
|
-
* The method used to make the request.
|
26
|
-
*
|
27
|
-
* @default 'POST'
|
28
|
-
*/
|
29
|
-
method?: Value<HTTPMethod, [
|
30
|
-
options: ClientOptionsOut<TClientContext>,
|
31
|
-
path: readonly string[],
|
32
|
-
input: unknown
|
33
|
-
]>;
|
34
|
-
/**
|
35
|
-
* The method to use when the payload cannot safely pass to the server with method return from method function.
|
36
|
-
* GET is not allowed, it's very dangerous.
|
37
|
-
*
|
38
|
-
* @default 'POST'
|
39
|
-
*/
|
40
|
-
fallbackMethod?: Exclude<HTTPMethod, 'GET'>;
|
41
|
-
/**
|
42
|
-
* Inject headers to the request.
|
43
|
-
*/
|
44
|
-
headers?: Value<[string, string][] | Record<string, string> | Headers, [
|
45
|
-
options: ClientOptionsOut<TClientContext>,
|
46
|
-
path: readonly string[],
|
47
|
-
input: unknown
|
48
|
-
]>;
|
49
|
-
/**
|
50
|
-
* Custom fetch implementation.
|
51
|
-
*
|
52
|
-
* @default globalThis.fetch.bind(globalThis)
|
53
|
-
*/
|
54
|
-
fetch?: FetchWithContext<TClientContext>;
|
55
|
-
rpcSerializer?: RPCSerializer;
|
56
|
-
/**
|
57
|
-
* Maximum number of retry attempts for EventSource errors before throwing.
|
58
|
-
*
|
59
|
-
* @default 5
|
60
|
-
*/
|
61
|
-
eventSourceMaxNumberOfRetries?: number;
|
62
|
-
/**
|
63
|
-
* Delay (in ms) before retrying an EventSource call.
|
64
|
-
*
|
65
|
-
* @default ({retryTimes, lastRetry}) => lastRetry ?? (1000 * 2 ** retryTimes)
|
66
|
-
*/
|
67
|
-
eventSourceRetryDelay?: Value<number, [
|
68
|
-
reconnectOptions: EventIteratorReconnectOptions,
|
69
|
-
options: ClientOptionsOut<TClientContext>,
|
70
|
-
path: readonly string[],
|
71
|
-
input: unknown
|
72
|
-
]>;
|
73
|
-
/**
|
74
|
-
* Function to determine if an error is retryable.
|
75
|
-
*
|
76
|
-
* @default true
|
77
|
-
*/
|
78
|
-
eventSourceRetry?: Value<boolean, [
|
79
|
-
reconnectOptions: EventIteratorReconnectOptions,
|
80
|
-
options: ClientOptionsOut<TClientContext>,
|
81
|
-
path: readonly string[],
|
82
|
-
input: unknown
|
83
|
-
]>;
|
21
|
+
declare class RPCLink<T extends ClientContext> implements ClientLink<T> {
|
22
|
+
private readonly standardLink;
|
23
|
+
constructor(options: RPCLinkOptions<T>);
|
24
|
+
call(path: readonly string[], input: unknown, options: ClientOptionsOut<T>): Promise<unknown>;
|
84
25
|
}
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
private readonly maxUrlLength;
|
89
|
-
private readonly fallbackMethod;
|
90
|
-
private readonly method;
|
91
|
-
private readonly headers;
|
92
|
-
private readonly url;
|
93
|
-
private readonly eventSourceMaxNumberOfRetries;
|
94
|
-
private readonly eventSourceRetryDelay;
|
95
|
-
private readonly eventSourceRetry;
|
96
|
-
private readonly toFetchBodyOptions;
|
97
|
-
constructor(options: RPCLinkOptions<TClientContext>);
|
98
|
-
call(path: readonly string[], input: unknown, options: ClientOptionsOut<TClientContext>): Promise<unknown>;
|
99
|
-
private performCall;
|
100
|
-
private encodeRequest;
|
26
|
+
|
27
|
+
interface FetchWithContext<TClientContext extends ClientContext> {
|
28
|
+
(url: URL, init: RequestInit, options: ClientOptionsOut<TClientContext>, path: readonly string[], input: unknown): Promise<Response>;
|
101
29
|
}
|
102
30
|
|
103
|
-
export { type FetchWithContext,
|
31
|
+
export { type FetchWithContext, RPCLink, type RPCLinkOptions };
|
@@ -1,103 +1,31 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
import {
|
1
|
+
import { C as ClientContext, a as ClientOptionsOut, b as ClientLink } from '../../shared/client.D_CzLDyB.js';
|
2
|
+
import { StandardLinkClient, StandardLinkOptions, StandardRPCLinkCodecOptions, StandardRPCLinkCodec } from '../standard/index.js';
|
3
|
+
import { StandardRequest, StandardLazyResponse } from '@orpc/standard-server';
|
4
|
+
import { ToFetchRequestOptions } from '@orpc/standard-server-fetch';
|
5
|
+
import '@orpc/shared';
|
5
6
|
|
6
|
-
interface
|
7
|
-
(
|
7
|
+
interface LinkFetchClientOptions<T extends ClientContext> extends ToFetchRequestOptions {
|
8
|
+
fetch?: (request: Request, init: Record<never, never>, options: ClientOptionsOut<T>, path: readonly string[], input: unknown) => Promise<Response>;
|
9
|
+
}
|
10
|
+
declare class LinkFetchClient<T extends ClientContext> implements StandardLinkClient<T> {
|
11
|
+
private readonly fetch;
|
12
|
+
private readonly toFetchRequestOptions;
|
13
|
+
constructor(options: LinkFetchClientOptions<T>);
|
14
|
+
call(request: StandardRequest, options: ClientOptionsOut<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
|
8
15
|
}
|
9
16
|
|
10
|
-
|
11
|
-
|
17
|
+
interface RPCLinkOptions<T extends ClientContext> extends StandardLinkOptions<T>, StandardRPCLinkCodecOptions<T>, LinkFetchClientOptions<T> {
|
18
|
+
linkCodec?: StandardRPCLinkCodec<T>;
|
19
|
+
linkClient?: LinkFetchClient<T>;
|
12
20
|
}
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
url: string;
|
18
|
-
/**
|
19
|
-
* The maximum length of the URL.
|
20
|
-
*
|
21
|
-
* @default 2083
|
22
|
-
*/
|
23
|
-
maxUrlLength?: number;
|
24
|
-
/**
|
25
|
-
* The method used to make the request.
|
26
|
-
*
|
27
|
-
* @default 'POST'
|
28
|
-
*/
|
29
|
-
method?: Value<HTTPMethod, [
|
30
|
-
options: ClientOptionsOut<TClientContext>,
|
31
|
-
path: readonly string[],
|
32
|
-
input: unknown
|
33
|
-
]>;
|
34
|
-
/**
|
35
|
-
* The method to use when the payload cannot safely pass to the server with method return from method function.
|
36
|
-
* GET is not allowed, it's very dangerous.
|
37
|
-
*
|
38
|
-
* @default 'POST'
|
39
|
-
*/
|
40
|
-
fallbackMethod?: Exclude<HTTPMethod, 'GET'>;
|
41
|
-
/**
|
42
|
-
* Inject headers to the request.
|
43
|
-
*/
|
44
|
-
headers?: Value<[string, string][] | Record<string, string> | Headers, [
|
45
|
-
options: ClientOptionsOut<TClientContext>,
|
46
|
-
path: readonly string[],
|
47
|
-
input: unknown
|
48
|
-
]>;
|
49
|
-
/**
|
50
|
-
* Custom fetch implementation.
|
51
|
-
*
|
52
|
-
* @default globalThis.fetch.bind(globalThis)
|
53
|
-
*/
|
54
|
-
fetch?: FetchWithContext<TClientContext>;
|
55
|
-
rpcSerializer?: RPCSerializer;
|
56
|
-
/**
|
57
|
-
* Maximum number of retry attempts for EventSource errors before throwing.
|
58
|
-
*
|
59
|
-
* @default 5
|
60
|
-
*/
|
61
|
-
eventSourceMaxNumberOfRetries?: number;
|
62
|
-
/**
|
63
|
-
* Delay (in ms) before retrying an EventSource call.
|
64
|
-
*
|
65
|
-
* @default ({retryTimes, lastRetry}) => lastRetry ?? (1000 * 2 ** retryTimes)
|
66
|
-
*/
|
67
|
-
eventSourceRetryDelay?: Value<number, [
|
68
|
-
reconnectOptions: EventIteratorReconnectOptions,
|
69
|
-
options: ClientOptionsOut<TClientContext>,
|
70
|
-
path: readonly string[],
|
71
|
-
input: unknown
|
72
|
-
]>;
|
73
|
-
/**
|
74
|
-
* Function to determine if an error is retryable.
|
75
|
-
*
|
76
|
-
* @default true
|
77
|
-
*/
|
78
|
-
eventSourceRetry?: Value<boolean, [
|
79
|
-
reconnectOptions: EventIteratorReconnectOptions,
|
80
|
-
options: ClientOptionsOut<TClientContext>,
|
81
|
-
path: readonly string[],
|
82
|
-
input: unknown
|
83
|
-
]>;
|
21
|
+
declare class RPCLink<T extends ClientContext> implements ClientLink<T> {
|
22
|
+
private readonly standardLink;
|
23
|
+
constructor(options: RPCLinkOptions<T>);
|
24
|
+
call(path: readonly string[], input: unknown, options: ClientOptionsOut<T>): Promise<unknown>;
|
84
25
|
}
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
private readonly maxUrlLength;
|
89
|
-
private readonly fallbackMethod;
|
90
|
-
private readonly method;
|
91
|
-
private readonly headers;
|
92
|
-
private readonly url;
|
93
|
-
private readonly eventSourceMaxNumberOfRetries;
|
94
|
-
private readonly eventSourceRetryDelay;
|
95
|
-
private readonly eventSourceRetry;
|
96
|
-
private readonly toFetchBodyOptions;
|
97
|
-
constructor(options: RPCLinkOptions<TClientContext>);
|
98
|
-
call(path: readonly string[], input: unknown, options: ClientOptionsOut<TClientContext>): Promise<unknown>;
|
99
|
-
private performCall;
|
100
|
-
private encodeRequest;
|
26
|
+
|
27
|
+
interface FetchWithContext<TClientContext extends ClientContext> {
|
28
|
+
(url: URL, init: RequestInit, options: ClientOptionsOut<TClientContext>, path: readonly string[], input: unknown): Promise<Response>;
|
101
29
|
}
|
102
30
|
|
103
|
-
export { type FetchWithContext,
|
31
|
+
export { type FetchWithContext, RPCLink, type RPCLinkOptions };
|
@@ -1,121 +1,34 @@
|
|
1
|
-
import {
|
2
|
-
import
|
3
|
-
import { c as createAutoRetryEventIterator, O as ORPCError } from '../../shared/client.Ly4zGQrc.mjs';
|
4
|
-
import { a as RPCSerializer } from '../../shared/client.DHJ8vRIG.mjs';
|
1
|
+
import { a as StandardRPCLinkCodec, S as StandardLink } from '../../shared/client.Ch8Gzz9n.mjs';
|
2
|
+
import '@orpc/shared';
|
5
3
|
import '@orpc/standard-server';
|
4
|
+
import { toFetchRequest, toStandardLazyResponse } from '@orpc/standard-server-fetch';
|
5
|
+
import '../../shared/client.DcaJQZfy.mjs';
|
6
6
|
|
7
|
-
class
|
8
|
-
}
|
9
|
-
class RPCLink {
|
7
|
+
class LinkFetchClient {
|
10
8
|
fetch;
|
11
|
-
|
12
|
-
maxUrlLength;
|
13
|
-
fallbackMethod;
|
14
|
-
method;
|
15
|
-
headers;
|
16
|
-
url;
|
17
|
-
eventSourceMaxNumberOfRetries;
|
18
|
-
eventSourceRetryDelay;
|
19
|
-
eventSourceRetry;
|
20
|
-
toFetchBodyOptions;
|
9
|
+
toFetchRequestOptions;
|
21
10
|
constructor(options) {
|
22
|
-
this.fetch = options
|
23
|
-
this.
|
24
|
-
this.maxUrlLength = options.maxUrlLength ?? 2083;
|
25
|
-
this.fallbackMethod = options.fallbackMethod ?? "POST";
|
26
|
-
this.url = options.url;
|
27
|
-
this.eventSourceMaxNumberOfRetries = options.eventSourceMaxNumberOfRetries ?? 5;
|
28
|
-
this.method = options.method ?? this.fallbackMethod;
|
29
|
-
this.headers = options.headers ?? {};
|
30
|
-
this.eventSourceRetry = options.eventSourceRetry ?? true;
|
31
|
-
this.eventSourceRetryDelay = options.eventSourceRetryDelay ?? (({ retryTimes, lastRetry }) => lastRetry ?? 1e3 * 2 ** retryTimes);
|
32
|
-
this.toFetchBodyOptions = options;
|
11
|
+
this.fetch = options?.fetch ?? globalThis.fetch.bind(globalThis);
|
12
|
+
this.toFetchRequestOptions = options;
|
33
13
|
}
|
34
|
-
async call(path, input
|
35
|
-
const
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
return createAutoRetryEventIterator(output, async (reconnectOptions) => {
|
40
|
-
if (options.signal?.aborted || reconnectOptions.retryTimes > this.eventSourceMaxNumberOfRetries) {
|
41
|
-
return null;
|
42
|
-
}
|
43
|
-
if (!await value(this.eventSourceRetry, reconnectOptions, options, path, input)) {
|
44
|
-
return null;
|
45
|
-
}
|
46
|
-
const delay = await value(this.eventSourceRetryDelay, reconnectOptions, options, path, input);
|
47
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
48
|
-
const updatedOptions = { ...options, lastEventId: reconnectOptions.lastEventId };
|
49
|
-
const maybeIterator = await this.performCall(path, input, updatedOptions);
|
50
|
-
if (!isAsyncIteratorObject(maybeIterator)) {
|
51
|
-
throw new InvalidEventSourceRetryResponse("Invalid EventSource retry response");
|
52
|
-
}
|
53
|
-
return maybeIterator;
|
54
|
-
}, void 0);
|
14
|
+
async call(request, options, path, input) {
|
15
|
+
const fetchRequest = toFetchRequest(request, this.toFetchRequestOptions);
|
16
|
+
const fetchResponse = await this.fetch(fetchRequest, {}, options, path, input);
|
17
|
+
const lazyResponse = toStandardLazyResponse(fetchResponse);
|
18
|
+
return lazyResponse;
|
55
19
|
}
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
const
|
63
|
-
|
64
|
-
headers: encoded.headers,
|
65
|
-
body: fetchBody,
|
66
|
-
signal: options.signal
|
67
|
-
}, options, path, input);
|
68
|
-
const body = await toStandardBody(response);
|
69
|
-
const deserialized = (() => {
|
70
|
-
try {
|
71
|
-
return this.rpcSerializer.deserialize(body);
|
72
|
-
} catch (error) {
|
73
|
-
if (response.ok) {
|
74
|
-
throw new ORPCError("INTERNAL_SERVER_ERROR", {
|
75
|
-
message: "Invalid RPC response",
|
76
|
-
cause: error
|
77
|
-
});
|
78
|
-
}
|
79
|
-
throw new ORPCError(response.status.toString(), {
|
80
|
-
message: response.statusText
|
81
|
-
});
|
82
|
-
}
|
83
|
-
})();
|
84
|
-
if (!response.ok) {
|
85
|
-
if (ORPCError.isValidJSON(deserialized)) {
|
86
|
-
throw ORPCError.fromJSON(deserialized);
|
87
|
-
}
|
88
|
-
throw new ORPCError("INTERNAL_SERVER_ERROR", {
|
89
|
-
message: "Invalid RPC error response",
|
90
|
-
cause: deserialized
|
91
|
-
});
|
92
|
-
}
|
93
|
-
return deserialized;
|
20
|
+
}
|
21
|
+
|
22
|
+
class RPCLink {
|
23
|
+
standardLink;
|
24
|
+
constructor(options) {
|
25
|
+
const linkCodec = options.linkCodec ?? new StandardRPCLinkCodec(options);
|
26
|
+
const linkClient = options.linkClient ?? new LinkFetchClient(options);
|
27
|
+
this.standardLink = new StandardLink(linkCodec, linkClient, options);
|
94
28
|
}
|
95
|
-
async
|
96
|
-
|
97
|
-
const headers = new Headers(await value(this.headers, options, path, input));
|
98
|
-
const url = new URL(`${trim(this.url, "/")}/${path.map(encodeURIComponent).join("/")}`);
|
99
|
-
const serialized = this.rpcSerializer.serialize(input);
|
100
|
-
if (expectedMethod === "GET" && !(serialized instanceof FormData) && !(serialized instanceof Blob) && !isAsyncIteratorObject(serialized)) {
|
101
|
-
const getUrl = new URL(url);
|
102
|
-
getUrl.searchParams.append("data", stringifyJSON(serialized) ?? "");
|
103
|
-
if (getUrl.toString().length <= this.maxUrlLength) {
|
104
|
-
return {
|
105
|
-
body: void 0,
|
106
|
-
method: expectedMethod,
|
107
|
-
headers,
|
108
|
-
url: getUrl
|
109
|
-
};
|
110
|
-
}
|
111
|
-
}
|
112
|
-
return {
|
113
|
-
url,
|
114
|
-
method: expectedMethod === "GET" ? this.fallbackMethod : expectedMethod,
|
115
|
-
headers,
|
116
|
-
body: serialized
|
117
|
-
};
|
29
|
+
async call(path, input, options) {
|
30
|
+
return this.standardLink.call(path, input, options);
|
118
31
|
}
|
119
32
|
}
|
120
33
|
|
121
|
-
export {
|
34
|
+
export { RPCLink };
|
@@ -1,4 +1,72 @@
|
|
1
|
-
import { Segment } from '@orpc/shared';
|
1
|
+
import { Value, Interceptor, Segment } from '@orpc/shared';
|
2
|
+
import { StandardRequest, StandardLazyResponse, StandardHeaders } from '@orpc/standard-server';
|
3
|
+
import { C as ClientContext, a as ClientOptionsOut, E as EventIteratorReconnectOptions, b as ClientLink } from '../../shared/client.D_CzLDyB.mjs';
|
4
|
+
|
5
|
+
interface StandardLinkCodec<T extends ClientContext> {
|
6
|
+
encode(path: readonly string[], input: unknown, options: ClientOptionsOut<any>): Promise<StandardRequest>;
|
7
|
+
decode(response: StandardLazyResponse, options: ClientOptionsOut<T>, path: readonly string[], input: unknown): Promise<unknown>;
|
8
|
+
}
|
9
|
+
interface StandardLinkClient<T extends ClientContext> {
|
10
|
+
call(request: StandardRequest, options: ClientOptionsOut<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
|
11
|
+
}
|
12
|
+
|
13
|
+
declare class InvalidEventIteratorRetryResponse extends Error {
|
14
|
+
}
|
15
|
+
interface StandardLinkOptions<T extends ClientContext> {
|
16
|
+
/**
|
17
|
+
* Maximum number of retry attempts for event iterator errors before throwing.
|
18
|
+
*
|
19
|
+
* @default 5
|
20
|
+
*/
|
21
|
+
eventIteratorMaxRetries?: Value<number, [
|
22
|
+
reconnectOptions: EventIteratorReconnectOptions,
|
23
|
+
options: ClientOptionsOut<T>,
|
24
|
+
path: readonly string[],
|
25
|
+
input: unknown
|
26
|
+
]>;
|
27
|
+
/**
|
28
|
+
* Delay (in ms) before retrying an event iterator call.
|
29
|
+
*
|
30
|
+
* @default (o) => o.lastRetry ?? (1000 * 2 ** o.retryTimes)
|
31
|
+
*/
|
32
|
+
eventIteratorRetryDelay?: Value<number, [
|
33
|
+
reconnectOptions: EventIteratorReconnectOptions,
|
34
|
+
options: ClientOptionsOut<T>,
|
35
|
+
path: readonly string[],
|
36
|
+
input: unknown
|
37
|
+
]>;
|
38
|
+
/**
|
39
|
+
* Function to determine if an error is retryable.
|
40
|
+
*
|
41
|
+
* @default true
|
42
|
+
*/
|
43
|
+
eventIteratorShouldRetry?: Value<boolean, [
|
44
|
+
reconnectOptions: EventIteratorReconnectOptions,
|
45
|
+
options: ClientOptionsOut<T>,
|
46
|
+
path: readonly string[],
|
47
|
+
input: unknown
|
48
|
+
]>;
|
49
|
+
interceptors?: Interceptor<{
|
50
|
+
path: readonly string[];
|
51
|
+
input: unknown;
|
52
|
+
options: ClientOptionsOut<T>;
|
53
|
+
}, unknown, unknown>[];
|
54
|
+
clientInterceptors?: Interceptor<{
|
55
|
+
request: StandardRequest;
|
56
|
+
}, StandardLazyResponse, unknown>[];
|
57
|
+
}
|
58
|
+
declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
|
59
|
+
#private;
|
60
|
+
readonly codec: StandardLinkCodec<T>;
|
61
|
+
readonly sender: StandardLinkClient<T>;
|
62
|
+
private readonly eventIteratorMaxRetries;
|
63
|
+
private readonly eventIteratorRetryDelay;
|
64
|
+
private readonly eventIteratorShouldRetry;
|
65
|
+
private readonly interceptors;
|
66
|
+
private readonly clientInterceptors;
|
67
|
+
constructor(codec: StandardLinkCodec<T>, sender: StandardLinkClient<T>, options: StandardLinkOptions<T>);
|
68
|
+
call(path: readonly string[], input: unknown, options: ClientOptionsOut<T>): Promise<unknown>;
|
69
|
+
}
|
2
70
|
|
3
71
|
type RPCJsonSerializedMeta = [
|
4
72
|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7,
|
@@ -19,4 +87,63 @@ declare class RPCSerializer {
|
|
19
87
|
deserialize(data: unknown): unknown;
|
20
88
|
}
|
21
89
|
|
22
|
-
|
90
|
+
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
91
|
+
interface StandardRPCLinkCodecOptions<T extends ClientContext> {
|
92
|
+
/**
|
93
|
+
* Base url for all requests.
|
94
|
+
*/
|
95
|
+
url: Value<string | URL, [
|
96
|
+
options: ClientOptionsOut<T>,
|
97
|
+
path: readonly string[],
|
98
|
+
input: unknown
|
99
|
+
]>;
|
100
|
+
/**
|
101
|
+
* The maximum length of the URL.
|
102
|
+
*
|
103
|
+
* @default 2083
|
104
|
+
*/
|
105
|
+
maxUrlLength?: Value<number, [
|
106
|
+
options: ClientOptionsOut<T>,
|
107
|
+
path: readonly string[],
|
108
|
+
input: unknown
|
109
|
+
]>;
|
110
|
+
/**
|
111
|
+
* The method used to make the request.
|
112
|
+
*
|
113
|
+
* @default 'POST'
|
114
|
+
*/
|
115
|
+
method?: Value<HTTPMethod, [
|
116
|
+
options: ClientOptionsOut<T>,
|
117
|
+
path: readonly string[],
|
118
|
+
input: unknown
|
119
|
+
]>;
|
120
|
+
/**
|
121
|
+
* The method to use when the payload cannot safely pass to the server with method return from method function.
|
122
|
+
* GET is not allowed, it's very dangerous.
|
123
|
+
*
|
124
|
+
* @default 'POST'
|
125
|
+
*/
|
126
|
+
fallbackMethod?: Exclude<HTTPMethod, 'GET'>;
|
127
|
+
/**
|
128
|
+
* Inject headers to the request.
|
129
|
+
*/
|
130
|
+
headers?: Value<StandardHeaders, [
|
131
|
+
options: ClientOptionsOut<T>,
|
132
|
+
path: readonly string[],
|
133
|
+
input: unknown
|
134
|
+
]>;
|
135
|
+
rpcSerializer?: RPCSerializer;
|
136
|
+
}
|
137
|
+
declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardLinkCodec<T> {
|
138
|
+
private readonly baseUrl;
|
139
|
+
private readonly maxUrlLength;
|
140
|
+
private readonly fallbackMethod;
|
141
|
+
private readonly expectedMethod;
|
142
|
+
private readonly headers;
|
143
|
+
private readonly rpcSerializer;
|
144
|
+
constructor(options: StandardRPCLinkCodecOptions<T>);
|
145
|
+
encode(path: readonly string[], input: unknown, options: ClientOptionsOut<any>): Promise<StandardRequest>;
|
146
|
+
decode(response: StandardLazyResponse): Promise<unknown>;
|
147
|
+
}
|
148
|
+
|
149
|
+
export { InvalidEventIteratorRetryResponse, type RPCJsonSerialized, type RPCJsonSerializedMeta, RPCJsonSerializer, RPCSerializer, StandardLink, type StandardLinkClient, type StandardLinkCodec, type StandardLinkOptions, StandardRPCLinkCodec, type StandardRPCLinkCodecOptions };
|
@@ -1,4 +1,72 @@
|
|
1
|
-
import { Segment } from '@orpc/shared';
|
1
|
+
import { Value, Interceptor, Segment } from '@orpc/shared';
|
2
|
+
import { StandardRequest, StandardLazyResponse, StandardHeaders } from '@orpc/standard-server';
|
3
|
+
import { C as ClientContext, a as ClientOptionsOut, E as EventIteratorReconnectOptions, b as ClientLink } from '../../shared/client.D_CzLDyB.js';
|
4
|
+
|
5
|
+
interface StandardLinkCodec<T extends ClientContext> {
|
6
|
+
encode(path: readonly string[], input: unknown, options: ClientOptionsOut<any>): Promise<StandardRequest>;
|
7
|
+
decode(response: StandardLazyResponse, options: ClientOptionsOut<T>, path: readonly string[], input: unknown): Promise<unknown>;
|
8
|
+
}
|
9
|
+
interface StandardLinkClient<T extends ClientContext> {
|
10
|
+
call(request: StandardRequest, options: ClientOptionsOut<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse>;
|
11
|
+
}
|
12
|
+
|
13
|
+
declare class InvalidEventIteratorRetryResponse extends Error {
|
14
|
+
}
|
15
|
+
interface StandardLinkOptions<T extends ClientContext> {
|
16
|
+
/**
|
17
|
+
* Maximum number of retry attempts for event iterator errors before throwing.
|
18
|
+
*
|
19
|
+
* @default 5
|
20
|
+
*/
|
21
|
+
eventIteratorMaxRetries?: Value<number, [
|
22
|
+
reconnectOptions: EventIteratorReconnectOptions,
|
23
|
+
options: ClientOptionsOut<T>,
|
24
|
+
path: readonly string[],
|
25
|
+
input: unknown
|
26
|
+
]>;
|
27
|
+
/**
|
28
|
+
* Delay (in ms) before retrying an event iterator call.
|
29
|
+
*
|
30
|
+
* @default (o) => o.lastRetry ?? (1000 * 2 ** o.retryTimes)
|
31
|
+
*/
|
32
|
+
eventIteratorRetryDelay?: Value<number, [
|
33
|
+
reconnectOptions: EventIteratorReconnectOptions,
|
34
|
+
options: ClientOptionsOut<T>,
|
35
|
+
path: readonly string[],
|
36
|
+
input: unknown
|
37
|
+
]>;
|
38
|
+
/**
|
39
|
+
* Function to determine if an error is retryable.
|
40
|
+
*
|
41
|
+
* @default true
|
42
|
+
*/
|
43
|
+
eventIteratorShouldRetry?: Value<boolean, [
|
44
|
+
reconnectOptions: EventIteratorReconnectOptions,
|
45
|
+
options: ClientOptionsOut<T>,
|
46
|
+
path: readonly string[],
|
47
|
+
input: unknown
|
48
|
+
]>;
|
49
|
+
interceptors?: Interceptor<{
|
50
|
+
path: readonly string[];
|
51
|
+
input: unknown;
|
52
|
+
options: ClientOptionsOut<T>;
|
53
|
+
}, unknown, unknown>[];
|
54
|
+
clientInterceptors?: Interceptor<{
|
55
|
+
request: StandardRequest;
|
56
|
+
}, StandardLazyResponse, unknown>[];
|
57
|
+
}
|
58
|
+
declare class StandardLink<T extends ClientContext> implements ClientLink<T> {
|
59
|
+
#private;
|
60
|
+
readonly codec: StandardLinkCodec<T>;
|
61
|
+
readonly sender: StandardLinkClient<T>;
|
62
|
+
private readonly eventIteratorMaxRetries;
|
63
|
+
private readonly eventIteratorRetryDelay;
|
64
|
+
private readonly eventIteratorShouldRetry;
|
65
|
+
private readonly interceptors;
|
66
|
+
private readonly clientInterceptors;
|
67
|
+
constructor(codec: StandardLinkCodec<T>, sender: StandardLinkClient<T>, options: StandardLinkOptions<T>);
|
68
|
+
call(path: readonly string[], input: unknown, options: ClientOptionsOut<T>): Promise<unknown>;
|
69
|
+
}
|
2
70
|
|
3
71
|
type RPCJsonSerializedMeta = [
|
4
72
|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7,
|
@@ -19,4 +87,63 @@ declare class RPCSerializer {
|
|
19
87
|
deserialize(data: unknown): unknown;
|
20
88
|
}
|
21
89
|
|
22
|
-
|
90
|
+
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
91
|
+
interface StandardRPCLinkCodecOptions<T extends ClientContext> {
|
92
|
+
/**
|
93
|
+
* Base url for all requests.
|
94
|
+
*/
|
95
|
+
url: Value<string | URL, [
|
96
|
+
options: ClientOptionsOut<T>,
|
97
|
+
path: readonly string[],
|
98
|
+
input: unknown
|
99
|
+
]>;
|
100
|
+
/**
|
101
|
+
* The maximum length of the URL.
|
102
|
+
*
|
103
|
+
* @default 2083
|
104
|
+
*/
|
105
|
+
maxUrlLength?: Value<number, [
|
106
|
+
options: ClientOptionsOut<T>,
|
107
|
+
path: readonly string[],
|
108
|
+
input: unknown
|
109
|
+
]>;
|
110
|
+
/**
|
111
|
+
* The method used to make the request.
|
112
|
+
*
|
113
|
+
* @default 'POST'
|
114
|
+
*/
|
115
|
+
method?: Value<HTTPMethod, [
|
116
|
+
options: ClientOptionsOut<T>,
|
117
|
+
path: readonly string[],
|
118
|
+
input: unknown
|
119
|
+
]>;
|
120
|
+
/**
|
121
|
+
* The method to use when the payload cannot safely pass to the server with method return from method function.
|
122
|
+
* GET is not allowed, it's very dangerous.
|
123
|
+
*
|
124
|
+
* @default 'POST'
|
125
|
+
*/
|
126
|
+
fallbackMethod?: Exclude<HTTPMethod, 'GET'>;
|
127
|
+
/**
|
128
|
+
* Inject headers to the request.
|
129
|
+
*/
|
130
|
+
headers?: Value<StandardHeaders, [
|
131
|
+
options: ClientOptionsOut<T>,
|
132
|
+
path: readonly string[],
|
133
|
+
input: unknown
|
134
|
+
]>;
|
135
|
+
rpcSerializer?: RPCSerializer;
|
136
|
+
}
|
137
|
+
declare class StandardRPCLinkCodec<T extends ClientContext> implements StandardLinkCodec<T> {
|
138
|
+
private readonly baseUrl;
|
139
|
+
private readonly maxUrlLength;
|
140
|
+
private readonly fallbackMethod;
|
141
|
+
private readonly expectedMethod;
|
142
|
+
private readonly headers;
|
143
|
+
private readonly rpcSerializer;
|
144
|
+
constructor(options: StandardRPCLinkCodecOptions<T>);
|
145
|
+
encode(path: readonly string[], input: unknown, options: ClientOptionsOut<any>): Promise<StandardRequest>;
|
146
|
+
decode(response: StandardLazyResponse): Promise<unknown>;
|
147
|
+
}
|
148
|
+
|
149
|
+
export { InvalidEventIteratorRetryResponse, type RPCJsonSerialized, type RPCJsonSerializedMeta, RPCJsonSerializer, RPCSerializer, StandardLink, type StandardLinkClient, type StandardLinkCodec, type StandardLinkOptions, StandardRPCLinkCodec, type StandardRPCLinkCodecOptions };
|
@@ -1,4 +1,4 @@
|
|
1
|
-
export { R as RPCJsonSerializer,
|
1
|
+
export { I as InvalidEventIteratorRetryResponse, R as RPCJsonSerializer, b as RPCSerializer, S as StandardLink, a as StandardRPCLinkCodec } from '../../shared/client.Ch8Gzz9n.mjs';
|
2
2
|
import '@orpc/shared';
|
3
|
+
import '../../shared/client.DcaJQZfy.mjs';
|
3
4
|
import '@orpc/standard-server';
|
4
|
-
import '../../shared/client.Ly4zGQrc.mjs';
|
package/dist/index.mjs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { i as isDefinedError } from './shared/client.
|
2
|
-
export { C as COMMON_ORPC_ERROR_DEFS, O as ORPCError, c as createAutoRetryEventIterator, a as fallbackORPCErrorMessage, f as fallbackORPCErrorStatus, m as mapEventIterator, o as onEventIteratorStatusChange, r as registerEventIteratorState, t as toORPCError, u as updateEventIteratorStatus } from './shared/client.
|
1
|
+
import { i as isDefinedError } from './shared/client.DcaJQZfy.mjs';
|
2
|
+
export { C as COMMON_ORPC_ERROR_DEFS, O as ORPCError, c as createAutoRetryEventIterator, a as fallbackORPCErrorMessage, f as fallbackORPCErrorStatus, m as mapEventIterator, o as onEventIteratorStatusChange, r as registerEventIteratorState, t as toORPCError, u as updateEventIteratorStatus } from './shared/client.DcaJQZfy.mjs';
|
3
3
|
export { ErrorEvent } from '@orpc/standard-server';
|
4
4
|
import '@orpc/shared';
|
5
5
|
|
@@ -1,6 +1,61 @@
|
|
1
|
-
import {
|
1
|
+
import { intercept, isAsyncIteratorObject, value, isObject, stringifyJSON, trim } from '@orpc/shared';
|
2
|
+
import { c as createAutoRetryEventIterator, m as mapEventIterator, t as toORPCError, O as ORPCError } from './client.DcaJQZfy.mjs';
|
2
3
|
import { ErrorEvent } from '@orpc/standard-server';
|
3
|
-
|
4
|
+
|
5
|
+
class InvalidEventIteratorRetryResponse extends Error {
|
6
|
+
}
|
7
|
+
class StandardLink {
|
8
|
+
constructor(codec, sender, options) {
|
9
|
+
this.codec = codec;
|
10
|
+
this.sender = sender;
|
11
|
+
this.eventIteratorMaxRetries = options.eventIteratorMaxRetries ?? 5;
|
12
|
+
this.eventIteratorRetryDelay = options.eventIteratorRetryDelay ?? ((o) => o.lastRetry ?? 1e3 * 2 ** o.retryTimes);
|
13
|
+
this.eventIteratorShouldRetry = options.eventIteratorShouldRetry ?? true;
|
14
|
+
this.interceptors = options.interceptors ?? [];
|
15
|
+
this.clientInterceptors = options.clientInterceptors ?? [];
|
16
|
+
}
|
17
|
+
eventIteratorMaxRetries;
|
18
|
+
eventIteratorRetryDelay;
|
19
|
+
eventIteratorShouldRetry;
|
20
|
+
interceptors;
|
21
|
+
clientInterceptors;
|
22
|
+
call(path, input, options) {
|
23
|
+
return intercept(this.interceptors, { path, input, options }, async ({ path: path2, input: input2, options: options2 }) => {
|
24
|
+
const output = await this.#call(path2, input2, options2);
|
25
|
+
if (!isAsyncIteratorObject(output)) {
|
26
|
+
return output;
|
27
|
+
}
|
28
|
+
return createAutoRetryEventIterator(output, async (reconnectOptions) => {
|
29
|
+
const maxRetries = await value(this.eventIteratorMaxRetries, reconnectOptions, options2, path2, input2);
|
30
|
+
if (options2.signal?.aborted || reconnectOptions.retryTimes > maxRetries) {
|
31
|
+
return null;
|
32
|
+
}
|
33
|
+
const shouldRetry = await value(this.eventIteratorShouldRetry, reconnectOptions, options2, path2, input2);
|
34
|
+
if (!shouldRetry) {
|
35
|
+
return null;
|
36
|
+
}
|
37
|
+
const retryDelay = await value(this.eventIteratorRetryDelay, reconnectOptions, options2, path2, input2);
|
38
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
39
|
+
const updatedOptions = { ...options2, lastEventId: reconnectOptions.lastEventId };
|
40
|
+
const maybeIterator = await this.#call(path2, input2, updatedOptions);
|
41
|
+
if (!isAsyncIteratorObject(maybeIterator)) {
|
42
|
+
throw new InvalidEventIteratorRetryResponse("Invalid Event Iterator retry response");
|
43
|
+
}
|
44
|
+
return maybeIterator;
|
45
|
+
}, options2.lastEventId);
|
46
|
+
});
|
47
|
+
}
|
48
|
+
async #call(path, input, options) {
|
49
|
+
const request = await this.codec.encode(path, input, options);
|
50
|
+
const response = await intercept(
|
51
|
+
this.clientInterceptors,
|
52
|
+
{ request },
|
53
|
+
({ request: request2 }) => this.sender.call(request2, options, path, input)
|
54
|
+
);
|
55
|
+
const output = await this.codec.decode(response, options, path, input);
|
56
|
+
return output;
|
57
|
+
}
|
58
|
+
}
|
4
59
|
|
5
60
|
class RPCJsonSerializer {
|
6
61
|
serialize(data, segments = [], meta = [], maps = [], blobs = []) {
|
@@ -189,4 +244,78 @@ class RPCSerializer {
|
|
189
244
|
}
|
190
245
|
}
|
191
246
|
|
192
|
-
|
247
|
+
class StandardRPCLinkCodec {
|
248
|
+
baseUrl;
|
249
|
+
maxUrlLength;
|
250
|
+
fallbackMethod;
|
251
|
+
expectedMethod;
|
252
|
+
headers;
|
253
|
+
rpcSerializer;
|
254
|
+
constructor(options) {
|
255
|
+
this.baseUrl = options.url;
|
256
|
+
this.maxUrlLength = options.maxUrlLength ?? 2083;
|
257
|
+
this.fallbackMethod = options.fallbackMethod ?? "POST";
|
258
|
+
this.expectedMethod = options.method ?? this.fallbackMethod;
|
259
|
+
this.headers = options.headers ?? {};
|
260
|
+
this.rpcSerializer = options.rpcSerializer ?? new RPCSerializer();
|
261
|
+
}
|
262
|
+
async encode(path, input, options) {
|
263
|
+
const expectedMethod = await value(this.expectedMethod, options, path, input);
|
264
|
+
const headers = await value(this.headers, options, path, input);
|
265
|
+
const baseUrl = await value(this.baseUrl, options, path, input);
|
266
|
+
const url = new URL(`${trim(baseUrl.toString(), "/")}/${path.map(encodeURIComponent).join("/")}`);
|
267
|
+
const serialized = this.rpcSerializer.serialize(input);
|
268
|
+
if (expectedMethod === "GET" && !(serialized instanceof FormData) && !(serialized instanceof Blob) && !isAsyncIteratorObject(serialized)) {
|
269
|
+
const maxUrlLength = await value(this.maxUrlLength, options, path, input);
|
270
|
+
const getUrl = new URL(url);
|
271
|
+
getUrl.searchParams.append("data", stringifyJSON(serialized) ?? "");
|
272
|
+
if (getUrl.toString().length <= maxUrlLength) {
|
273
|
+
return {
|
274
|
+
body: void 0,
|
275
|
+
method: expectedMethod,
|
276
|
+
headers,
|
277
|
+
url: getUrl,
|
278
|
+
signal: options.signal
|
279
|
+
};
|
280
|
+
}
|
281
|
+
}
|
282
|
+
return {
|
283
|
+
url,
|
284
|
+
method: expectedMethod === "GET" ? this.fallbackMethod : expectedMethod,
|
285
|
+
headers,
|
286
|
+
body: serialized,
|
287
|
+
signal: options.signal
|
288
|
+
};
|
289
|
+
}
|
290
|
+
async decode(response) {
|
291
|
+
const isOk = response.status >= 200 && response.status < 300;
|
292
|
+
const deserialized = await (async () => {
|
293
|
+
let isBodyOk = false;
|
294
|
+
try {
|
295
|
+
const body = await response.body();
|
296
|
+
isBodyOk = true;
|
297
|
+
return this.rpcSerializer.deserialize(body);
|
298
|
+
} catch (error) {
|
299
|
+
if (!isBodyOk) {
|
300
|
+
throw new Error("Cannot parse response body, please check the response body and content-type.", {
|
301
|
+
cause: error
|
302
|
+
});
|
303
|
+
}
|
304
|
+
throw new Error("Invalid RPC response format.", {
|
305
|
+
cause: error
|
306
|
+
});
|
307
|
+
}
|
308
|
+
})();
|
309
|
+
if (!isOk) {
|
310
|
+
if (ORPCError.isValidJSON(deserialized)) {
|
311
|
+
throw ORPCError.fromJSON(deserialized);
|
312
|
+
}
|
313
|
+
throw new Error("Invalid RPC error response format.", {
|
314
|
+
cause: deserialized
|
315
|
+
});
|
316
|
+
}
|
317
|
+
return deserialized;
|
318
|
+
}
|
319
|
+
}
|
320
|
+
|
321
|
+
export { InvalidEventIteratorRetryResponse as I, RPCJsonSerializer as R, StandardLink as S, StandardRPCLinkCodec as a, RPCSerializer as b };
|
@@ -229,7 +229,7 @@ function createAutoRetryEventIterator(initial, reconnect, initialLastEventId) {
|
|
229
229
|
retryTimes += 1;
|
230
230
|
if (retryTimes > MAX_ALLOWED_RETRY_TIMES) {
|
231
231
|
throw exit(new Error(
|
232
|
-
`Exceeded maximum retry attempts (${MAX_ALLOWED_RETRY_TIMES}) for event
|
232
|
+
`Exceeded maximum retry attempts (${MAX_ALLOWED_RETRY_TIMES}) for event iterator. Possible infinite retry loop detected. Please review the retry logic.`,
|
233
233
|
{ cause: currentError }
|
234
234
|
));
|
235
235
|
}
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@orpc/client",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.
|
4
|
+
"version": "0.46.0",
|
5
5
|
"license": "MIT",
|
6
6
|
"homepage": "https://orpc.unnoq.com",
|
7
7
|
"repository": {
|
@@ -34,9 +34,9 @@
|
|
34
34
|
"dist"
|
35
35
|
],
|
36
36
|
"dependencies": {
|
37
|
-
"@orpc/shared": "0.
|
38
|
-
"@orpc/standard-server-fetch": "0.
|
39
|
-
"@orpc/standard-server": "0.
|
37
|
+
"@orpc/shared": "0.46.0",
|
38
|
+
"@orpc/standard-server-fetch": "0.46.0",
|
39
|
+
"@orpc/standard-server": "0.46.0"
|
40
40
|
},
|
41
41
|
"devDependencies": {
|
42
42
|
"zod": "^3.24.1"
|