@orpc/client 0.0.0-next.d16a1b6 → 0.0.0-next.d17ef5e
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 +13 -1
- package/dist/adapters/fetch/index.d.mts +12 -11
- package/dist/adapters/fetch/index.d.ts +12 -11
- package/dist/adapters/fetch/index.mjs +11 -7
- package/dist/adapters/standard/index.d.mts +44 -88
- package/dist/adapters/standard/index.d.ts +44 -88
- package/dist/adapters/standard/index.mjs +2 -2
- package/dist/index.d.mts +11 -13
- package/dist/index.d.ts +11 -13
- package/dist/index.mjs +35 -33
- package/dist/plugins/index.d.mts +61 -0
- package/dist/plugins/index.d.ts +61 -0
- package/dist/plugins/index.mjs +126 -0
- package/dist/shared/{client.MkoaGU3v.mjs → client.B1XjLWRe.mjs} +149 -136
- package/dist/shared/{client.DcaJQZfy.mjs → client.BacCdg3F.mjs} +2 -95
- package/dist/shared/client.Bt40CWA-.d.ts +39 -0
- package/dist/shared/client.CKw2tbcl.d.mts +39 -0
- package/dist/shared/client.RZs5Myak.d.mts +30 -0
- package/dist/shared/client.RZs5Myak.d.ts +30 -0
- package/package.json +10 -5
- package/dist/shared/client.D_CzLDyB.d.mts +0 -42
- package/dist/shared/client.D_CzLDyB.d.ts +0 -42
package/dist/index.mjs
CHANGED
@@ -1,17 +1,41 @@
|
|
1
|
-
import { i as isDefinedError } from './shared/client.
|
2
|
-
export { C as COMMON_ORPC_ERROR_DEFS, O as ORPCError,
|
1
|
+
import { i as isDefinedError } from './shared/client.BacCdg3F.mjs';
|
2
|
+
export { C as COMMON_ORPC_ERROR_DEFS, O as ORPCError, a as fallbackORPCErrorMessage, f as fallbackORPCErrorStatus, m as mapEventIterator, t as toORPCError } from './shared/client.BacCdg3F.mjs';
|
3
|
+
export { onError, onFinish, onStart, onSuccess } from '@orpc/shared';
|
3
4
|
export { ErrorEvent } from '@orpc/standard-server';
|
4
|
-
|
5
|
+
|
6
|
+
async function safe(promise) {
|
7
|
+
try {
|
8
|
+
const output = await promise;
|
9
|
+
return Object.assign(
|
10
|
+
[null, output, false],
|
11
|
+
{ error: null, data: output, isDefined: false }
|
12
|
+
);
|
13
|
+
} catch (e) {
|
14
|
+
const error = e;
|
15
|
+
if (isDefinedError(error)) {
|
16
|
+
return Object.assign(
|
17
|
+
[error, void 0, true],
|
18
|
+
{ error, data: void 0, isDefined: true }
|
19
|
+
);
|
20
|
+
}
|
21
|
+
return Object.assign(
|
22
|
+
[error, void 0, false],
|
23
|
+
{ error, data: void 0, isDefined: false }
|
24
|
+
);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
function resolveFriendlyClientOptions(options) {
|
28
|
+
return {
|
29
|
+
...options,
|
30
|
+
context: options?.context ?? {}
|
31
|
+
// Context only optional if all fields are optional
|
32
|
+
};
|
33
|
+
}
|
5
34
|
|
6
35
|
function createORPCClient(link, options) {
|
7
36
|
const path = options?.path ?? [];
|
8
|
-
const procedureClient = async (...[input, options2]) => {
|
9
|
-
|
10
|
-
...options2,
|
11
|
-
context: options2?.context ?? {}
|
12
|
-
// options.context can be undefined when all field is optional
|
13
|
-
};
|
14
|
-
return await link.call(path, input, optionsOut);
|
37
|
+
const procedureClient = async (...[input, options2 = {}]) => {
|
38
|
+
return await link.call(path, input, resolveFriendlyClientOptions(options2));
|
15
39
|
};
|
16
40
|
const recursive = new Proxy(procedureClient, {
|
17
41
|
get(target, key) {
|
@@ -38,26 +62,4 @@ class DynamicLink {
|
|
38
62
|
}
|
39
63
|
}
|
40
64
|
|
41
|
-
|
42
|
-
try {
|
43
|
-
const output = await promise;
|
44
|
-
return Object.assign(
|
45
|
-
[null, output, false],
|
46
|
-
{ error: null, data: output, isDefined: false }
|
47
|
-
);
|
48
|
-
} catch (e) {
|
49
|
-
const error = e;
|
50
|
-
if (isDefinedError(error)) {
|
51
|
-
return Object.assign(
|
52
|
-
[error, void 0, true],
|
53
|
-
{ error, data: void 0, isDefined: true }
|
54
|
-
);
|
55
|
-
}
|
56
|
-
return Object.assign(
|
57
|
-
[error, void 0, false],
|
58
|
-
{ error, data: void 0, isDefined: false }
|
59
|
-
);
|
60
|
-
}
|
61
|
-
}
|
62
|
-
|
63
|
-
export { DynamicLink, createORPCClient, isDefinedError, safe };
|
65
|
+
export { DynamicLink, createORPCClient, isDefinedError, resolveFriendlyClientOptions, safe };
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import { Value } from '@orpc/shared';
|
2
|
+
import { S as StandardLinkPlugin, a as StandardLinkOptions } from '../shared/client.CKw2tbcl.mjs';
|
3
|
+
import { C as ClientOptions } from '../shared/client.RZs5Myak.mjs';
|
4
|
+
import '@orpc/standard-server';
|
5
|
+
|
6
|
+
interface ClientRetryPluginAttemptOptions {
|
7
|
+
lastEventRetry: number | undefined;
|
8
|
+
lastEventId: string | undefined;
|
9
|
+
attemptIndex: number;
|
10
|
+
error: unknown;
|
11
|
+
}
|
12
|
+
interface ClientRetryPluginContext {
|
13
|
+
/**
|
14
|
+
* Maximum retry attempts before throwing
|
15
|
+
* Use `Number.POSITIVE_INFINITY` for infinite retries (e.g., when handling Server-Sent Events).
|
16
|
+
*
|
17
|
+
* @default 0
|
18
|
+
*/
|
19
|
+
retry?: number;
|
20
|
+
/**
|
21
|
+
* Delay (in ms) before retrying.
|
22
|
+
*
|
23
|
+
* @default (o) => o.lastEventRetry ?? 2000
|
24
|
+
*/
|
25
|
+
retryDelay?: Value<number, [
|
26
|
+
attemptOptions: ClientRetryPluginAttemptOptions,
|
27
|
+
clientOptions: ClientOptions<ClientRetryPluginContext>,
|
28
|
+
path: readonly string[],
|
29
|
+
input: unknown
|
30
|
+
]>;
|
31
|
+
/**
|
32
|
+
* Determine should retry or not.
|
33
|
+
*
|
34
|
+
* @default true
|
35
|
+
*/
|
36
|
+
shouldRetry?: Value<boolean, [
|
37
|
+
attemptOptions: ClientRetryPluginAttemptOptions,
|
38
|
+
clientOptions: ClientOptions<ClientRetryPluginContext>,
|
39
|
+
path: readonly string[],
|
40
|
+
input: unknown
|
41
|
+
]>;
|
42
|
+
/**
|
43
|
+
* The hook called when retrying, and return the unsubscribe function.
|
44
|
+
*/
|
45
|
+
onRetry?: (options: ClientRetryPluginAttemptOptions, clientOptions: ClientOptions<ClientRetryPluginContext>, path: readonly string[], input: unknown) => void | (() => void);
|
46
|
+
}
|
47
|
+
declare class ClientRetryPluginInvalidEventIteratorRetryResponse extends Error {
|
48
|
+
}
|
49
|
+
interface ClientRetryPluginOptions {
|
50
|
+
default?: ClientRetryPluginContext;
|
51
|
+
}
|
52
|
+
declare class ClientRetryPlugin<T extends ClientRetryPluginContext> implements StandardLinkPlugin<T> {
|
53
|
+
private readonly defaultRetry;
|
54
|
+
private readonly defaultRetryDelay;
|
55
|
+
private readonly defaultShouldRetry;
|
56
|
+
private readonly defaultOnRetry;
|
57
|
+
constructor(options?: ClientRetryPluginOptions);
|
58
|
+
init(options: StandardLinkOptions<T>): void;
|
59
|
+
}
|
60
|
+
|
61
|
+
export { ClientRetryPlugin, type ClientRetryPluginAttemptOptions, type ClientRetryPluginContext, ClientRetryPluginInvalidEventIteratorRetryResponse, type ClientRetryPluginOptions };
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import { Value } from '@orpc/shared';
|
2
|
+
import { S as StandardLinkPlugin, a as StandardLinkOptions } from '../shared/client.Bt40CWA-.js';
|
3
|
+
import { C as ClientOptions } from '../shared/client.RZs5Myak.js';
|
4
|
+
import '@orpc/standard-server';
|
5
|
+
|
6
|
+
interface ClientRetryPluginAttemptOptions {
|
7
|
+
lastEventRetry: number | undefined;
|
8
|
+
lastEventId: string | undefined;
|
9
|
+
attemptIndex: number;
|
10
|
+
error: unknown;
|
11
|
+
}
|
12
|
+
interface ClientRetryPluginContext {
|
13
|
+
/**
|
14
|
+
* Maximum retry attempts before throwing
|
15
|
+
* Use `Number.POSITIVE_INFINITY` for infinite retries (e.g., when handling Server-Sent Events).
|
16
|
+
*
|
17
|
+
* @default 0
|
18
|
+
*/
|
19
|
+
retry?: number;
|
20
|
+
/**
|
21
|
+
* Delay (in ms) before retrying.
|
22
|
+
*
|
23
|
+
* @default (o) => o.lastEventRetry ?? 2000
|
24
|
+
*/
|
25
|
+
retryDelay?: Value<number, [
|
26
|
+
attemptOptions: ClientRetryPluginAttemptOptions,
|
27
|
+
clientOptions: ClientOptions<ClientRetryPluginContext>,
|
28
|
+
path: readonly string[],
|
29
|
+
input: unknown
|
30
|
+
]>;
|
31
|
+
/**
|
32
|
+
* Determine should retry or not.
|
33
|
+
*
|
34
|
+
* @default true
|
35
|
+
*/
|
36
|
+
shouldRetry?: Value<boolean, [
|
37
|
+
attemptOptions: ClientRetryPluginAttemptOptions,
|
38
|
+
clientOptions: ClientOptions<ClientRetryPluginContext>,
|
39
|
+
path: readonly string[],
|
40
|
+
input: unknown
|
41
|
+
]>;
|
42
|
+
/**
|
43
|
+
* The hook called when retrying, and return the unsubscribe function.
|
44
|
+
*/
|
45
|
+
onRetry?: (options: ClientRetryPluginAttemptOptions, clientOptions: ClientOptions<ClientRetryPluginContext>, path: readonly string[], input: unknown) => void | (() => void);
|
46
|
+
}
|
47
|
+
declare class ClientRetryPluginInvalidEventIteratorRetryResponse extends Error {
|
48
|
+
}
|
49
|
+
interface ClientRetryPluginOptions {
|
50
|
+
default?: ClientRetryPluginContext;
|
51
|
+
}
|
52
|
+
declare class ClientRetryPlugin<T extends ClientRetryPluginContext> implements StandardLinkPlugin<T> {
|
53
|
+
private readonly defaultRetry;
|
54
|
+
private readonly defaultRetryDelay;
|
55
|
+
private readonly defaultShouldRetry;
|
56
|
+
private readonly defaultOnRetry;
|
57
|
+
constructor(options?: ClientRetryPluginOptions);
|
58
|
+
init(options: StandardLinkOptions<T>): void;
|
59
|
+
}
|
60
|
+
|
61
|
+
export { ClientRetryPlugin, type ClientRetryPluginAttemptOptions, type ClientRetryPluginContext, ClientRetryPluginInvalidEventIteratorRetryResponse, type ClientRetryPluginOptions };
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import { isAsyncIteratorObject, value } from '@orpc/shared';
|
2
|
+
import { getEventMeta } from '@orpc/standard-server';
|
3
|
+
|
4
|
+
class ClientRetryPluginInvalidEventIteratorRetryResponse extends Error {
|
5
|
+
}
|
6
|
+
class ClientRetryPlugin {
|
7
|
+
defaultRetry;
|
8
|
+
defaultRetryDelay;
|
9
|
+
defaultShouldRetry;
|
10
|
+
defaultOnRetry;
|
11
|
+
constructor(options = {}) {
|
12
|
+
this.defaultRetry = options.default?.retry ?? 0;
|
13
|
+
this.defaultRetryDelay = options.default?.retryDelay ?? ((o) => o.lastEventRetry ?? 2e3);
|
14
|
+
this.defaultShouldRetry = options.default?.shouldRetry ?? true;
|
15
|
+
this.defaultOnRetry = options.default?.onRetry;
|
16
|
+
}
|
17
|
+
init(options) {
|
18
|
+
options.interceptors ??= [];
|
19
|
+
options.interceptors.push(async (interceptorOptions) => {
|
20
|
+
const maxAttempts = interceptorOptions.options.context.retry ?? this.defaultRetry;
|
21
|
+
const retryDelay = interceptorOptions.options.context.retryDelay ?? this.defaultRetryDelay;
|
22
|
+
const shouldRetry = interceptorOptions.options.context.shouldRetry ?? this.defaultShouldRetry;
|
23
|
+
const onRetry = interceptorOptions.options.context.onRetry ?? this.defaultOnRetry;
|
24
|
+
if (maxAttempts <= 0) {
|
25
|
+
return interceptorOptions.next();
|
26
|
+
}
|
27
|
+
let lastEventId = interceptorOptions.options.lastEventId;
|
28
|
+
let lastEventRetry;
|
29
|
+
let unsubscribe;
|
30
|
+
let attemptIndex = 0;
|
31
|
+
const next = async (initial) => {
|
32
|
+
let current = initial;
|
33
|
+
while (true) {
|
34
|
+
const newClientOptions = { ...interceptorOptions.options, lastEventId };
|
35
|
+
if (current) {
|
36
|
+
if (attemptIndex >= maxAttempts) {
|
37
|
+
throw current.error;
|
38
|
+
}
|
39
|
+
const attemptOptions = {
|
40
|
+
attemptIndex,
|
41
|
+
error: current.error,
|
42
|
+
lastEventId,
|
43
|
+
lastEventRetry
|
44
|
+
};
|
45
|
+
const shouldRetryBool = await value(
|
46
|
+
shouldRetry,
|
47
|
+
attemptOptions,
|
48
|
+
newClientOptions,
|
49
|
+
interceptorOptions.path,
|
50
|
+
interceptorOptions.input
|
51
|
+
);
|
52
|
+
if (!shouldRetryBool) {
|
53
|
+
throw current.error;
|
54
|
+
}
|
55
|
+
unsubscribe = onRetry?.(
|
56
|
+
attemptOptions,
|
57
|
+
newClientOptions,
|
58
|
+
interceptorOptions.path,
|
59
|
+
interceptorOptions.input
|
60
|
+
);
|
61
|
+
const retryDelayMs = await value(
|
62
|
+
retryDelay,
|
63
|
+
attemptOptions,
|
64
|
+
newClientOptions,
|
65
|
+
interceptorOptions.path,
|
66
|
+
interceptorOptions.input
|
67
|
+
);
|
68
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
69
|
+
attemptIndex++;
|
70
|
+
}
|
71
|
+
try {
|
72
|
+
const output2 = await interceptorOptions.next({
|
73
|
+
...interceptorOptions,
|
74
|
+
options: newClientOptions
|
75
|
+
});
|
76
|
+
return output2;
|
77
|
+
} catch (error) {
|
78
|
+
if (newClientOptions.signal?.aborted === true) {
|
79
|
+
throw error;
|
80
|
+
}
|
81
|
+
current = { error };
|
82
|
+
} finally {
|
83
|
+
unsubscribe?.();
|
84
|
+
unsubscribe = void 0;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
};
|
88
|
+
const output = await next();
|
89
|
+
if (!isAsyncIteratorObject(output)) {
|
90
|
+
return output;
|
91
|
+
}
|
92
|
+
return async function* () {
|
93
|
+
let current = output;
|
94
|
+
try {
|
95
|
+
while (true) {
|
96
|
+
try {
|
97
|
+
const item = await current.next();
|
98
|
+
const meta = getEventMeta(item.value);
|
99
|
+
lastEventId = meta?.id ?? lastEventId;
|
100
|
+
lastEventRetry = meta?.retry ?? lastEventRetry;
|
101
|
+
if (item.done) {
|
102
|
+
return item.value;
|
103
|
+
}
|
104
|
+
yield item.value;
|
105
|
+
} catch (error) {
|
106
|
+
const meta = getEventMeta(error);
|
107
|
+
lastEventId = meta?.id ?? lastEventId;
|
108
|
+
lastEventRetry = meta?.retry ?? lastEventRetry;
|
109
|
+
const maybeEventIterator = await next({ error });
|
110
|
+
if (!isAsyncIteratorObject(maybeEventIterator)) {
|
111
|
+
throw new ClientRetryPluginInvalidEventIteratorRetryResponse(
|
112
|
+
"RetryPlugin: Expected an Event Iterator, got a non-Event Iterator"
|
113
|
+
);
|
114
|
+
}
|
115
|
+
current = maybeEventIterator;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
} finally {
|
119
|
+
await current.return?.();
|
120
|
+
}
|
121
|
+
}();
|
122
|
+
});
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
export { ClientRetryPlugin, ClientRetryPluginInvalidEventIteratorRetryResponse };
|