@orpc/experimental-durable-iterator 0.0.0-next.e7bc0b8 → 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/client/index.d.mts +5 -8
- package/dist/client/index.d.ts +5 -8
- package/dist/client/index.mjs +15 -18
- package/dist/durable-object/index.d.mts +18 -33
- package/dist/durable-object/index.d.ts +18 -33
- package/dist/durable-object/index.mjs +12 -58
- package/dist/index.d.mts +4 -11
- package/dist/index.d.ts +4 -11
- package/dist/index.mjs +5 -8
- package/dist/shared/{experimental-durable-iterator.DrenXxND.d.mts → experimental-durable-iterator.B0U3VKpv.d.ts} +2 -2
- package/dist/shared/{experimental-durable-iterator.DZOLL3sf.mjs → experimental-durable-iterator.BBUZixu_.mjs} +0 -1
- package/dist/shared/{experimental-durable-iterator.DQjHfIr1.d.mts → experimental-durable-iterator.Bh_-Jj0k.d.mts} +0 -1
- package/dist/shared/{experimental-durable-iterator.DQjHfIr1.d.ts → experimental-durable-iterator.Bh_-Jj0k.d.ts} +0 -1
- package/dist/shared/{experimental-durable-iterator.B3M42lLK.mjs → experimental-durable-iterator.CP6Ouvmj.mjs} +1 -1
- package/dist/shared/{experimental-durable-iterator.C6YPLbUA.d.ts → experimental-durable-iterator.DDJKw0d4.d.mts} +2 -2
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
<a href="https://codecov.io/gh/unnoq/orpc">
|
|
9
9
|
<img alt="codecov" src="https://codecov.io/gh/unnoq/orpc/branch/main/graph/badge.svg">
|
|
10
10
|
</a>
|
|
11
|
-
<a href="https://www.npmjs.com/package/@orpc/
|
|
12
|
-
<img alt="weekly downloads" src="https://img.shields.io/npm/dw/%40orpc%
|
|
11
|
+
<a href="https://www.npmjs.com/package/@orpc/durable-event-iterator">
|
|
12
|
+
<img alt="weekly downloads" src="https://img.shields.io/npm/dw/%40orpc%2Fdurable-event-iterator?logo=npm" />
|
|
13
13
|
</a>
|
|
14
14
|
<a href="https://github.com/unnoq/orpc/blob/main/LICENSE">
|
|
15
15
|
<img alt="MIT License" src="https://img.shields.io/github/license/unnoq/orpc?logo=open-source-initiative" />
|
|
@@ -61,7 +61,7 @@ You can find the full documentation [here](https://orpc.unnoq.com).
|
|
|
61
61
|
- [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): OpenAPI spec generation from [Valibot](https://valibot.dev/).
|
|
62
62
|
- [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): OpenAPI spec generation from [ArkType](https://arktype.io/).
|
|
63
63
|
|
|
64
|
-
## `@orpc/
|
|
64
|
+
## `@orpc/durable-event-iterator`
|
|
65
65
|
|
|
66
66
|
[Durable Objects](https://developers.cloudflare.com/durable-objects/) integration for oRPC.
|
|
67
67
|
|
package/dist/client/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { C as ClientDurableIterator, b as ClientDurableIteratorRpc, a as ClientDurableIteratorRpcContext, c as CreateClientDurableIteratorOptions, d as createClientDurableIterator, g as getClientDurableIteratorToken } from '../shared/experimental-durable-iterator.
|
|
1
|
+
export { C as ClientDurableIterator, b as ClientDurableIteratorRpc, a as ClientDurableIteratorRpcContext, c as CreateClientDurableIteratorOptions, d as createClientDurableIterator, g as getClientDurableIteratorToken } from '../shared/experimental-durable-iterator.DDJKw0d4.mjs';
|
|
2
2
|
import { ClientContext } from '@orpc/client';
|
|
3
3
|
import { StandardLinkInterceptorOptions, StandardLinkPlugin, StandardLinkOptions } from '@orpc/client/standard';
|
|
4
4
|
import { RPCLinkOptions } from '@orpc/client/websocket';
|
|
5
5
|
import { Value, Promisable } from '@orpc/shared';
|
|
6
|
-
import { b as DurableIteratorTokenPayload } from '../shared/experimental-durable-iterator.
|
|
6
|
+
import { b as DurableIteratorTokenPayload } from '../shared/experimental-durable-iterator.Bh_-Jj0k.mjs';
|
|
7
7
|
import '@orpc/client/plugins';
|
|
8
8
|
import 'valibot';
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ interface DurableIteratorLinkPluginContext {
|
|
|
12
12
|
}
|
|
13
13
|
interface DurableIteratorLinkPluginOptions<T extends ClientContext> extends Omit<RPCLinkOptions<object>, 'websocket'> {
|
|
14
14
|
/**
|
|
15
|
-
* The WebSocket URL to connect to the Durable Iterator Object.
|
|
15
|
+
* The WebSocket URL to connect to the Durable Event Iterator Object.
|
|
16
16
|
*/
|
|
17
17
|
url: Value<Promisable<string | URL>, [tokenPayload: DurableIteratorTokenPayload, options: StandardLinkInterceptorOptions<T>]>;
|
|
18
18
|
/**
|
|
@@ -24,7 +24,7 @@ interface DurableIteratorLinkPluginOptions<T extends ClientContext> extends Omit
|
|
|
24
24
|
* @remarks
|
|
25
25
|
* - Use a strong random generator to avoid collisions or predictable IDs.
|
|
26
26
|
*
|
|
27
|
-
* @default (() => crypto.randomUUID())
|
|
27
|
+
* @default (() => `${crypto.randomUUID()}-${crypto.randomUUID()}`)
|
|
28
28
|
*/
|
|
29
29
|
createId?: (tokenPayload: DurableIteratorTokenPayload, options: StandardLinkInterceptorOptions<T>) => Promisable<string>;
|
|
30
30
|
/**
|
|
@@ -41,13 +41,10 @@ interface DurableIteratorLinkPluginOptions<T extends ClientContext> extends Omit
|
|
|
41
41
|
refreshTokenBeforeExpireInSeconds?: Value<Promisable<number>, [tokenPayload: DurableIteratorTokenPayload, options: StandardLinkInterceptorOptions<T>]>;
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
* @see {@link https://orpc.unnoq.com/docs/integrations/durable-iterator Durable Iterator Integration}
|
|
44
|
+
* @see {@link https://orpc.unnoq.com/docs/integrations/durable-event-iterator Durable Event Iterator Integration}
|
|
45
45
|
*/
|
|
46
46
|
declare class DurableIteratorLinkPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
|
|
47
47
|
readonly CONTEXT_SYMBOL: symbol;
|
|
48
|
-
/**
|
|
49
|
-
* run before (modify result after) retry plugin because it can break the special iterator
|
|
50
|
-
*/
|
|
51
48
|
order: number;
|
|
52
49
|
private readonly url;
|
|
53
50
|
private readonly createId;
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { C as ClientDurableIterator, b as ClientDurableIteratorRpc, a as ClientDurableIteratorRpcContext, c as CreateClientDurableIteratorOptions, d as createClientDurableIterator, g as getClientDurableIteratorToken } from '../shared/experimental-durable-iterator.
|
|
1
|
+
export { C as ClientDurableIterator, b as ClientDurableIteratorRpc, a as ClientDurableIteratorRpcContext, c as CreateClientDurableIteratorOptions, d as createClientDurableIterator, g as getClientDurableIteratorToken } from '../shared/experimental-durable-iterator.B0U3VKpv.js';
|
|
2
2
|
import { ClientContext } from '@orpc/client';
|
|
3
3
|
import { StandardLinkInterceptorOptions, StandardLinkPlugin, StandardLinkOptions } from '@orpc/client/standard';
|
|
4
4
|
import { RPCLinkOptions } from '@orpc/client/websocket';
|
|
5
5
|
import { Value, Promisable } from '@orpc/shared';
|
|
6
|
-
import { b as DurableIteratorTokenPayload } from '../shared/experimental-durable-iterator.
|
|
6
|
+
import { b as DurableIteratorTokenPayload } from '../shared/experimental-durable-iterator.Bh_-Jj0k.js';
|
|
7
7
|
import '@orpc/client/plugins';
|
|
8
8
|
import 'valibot';
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ interface DurableIteratorLinkPluginContext {
|
|
|
12
12
|
}
|
|
13
13
|
interface DurableIteratorLinkPluginOptions<T extends ClientContext> extends Omit<RPCLinkOptions<object>, 'websocket'> {
|
|
14
14
|
/**
|
|
15
|
-
* The WebSocket URL to connect to the Durable Iterator Object.
|
|
15
|
+
* The WebSocket URL to connect to the Durable Event Iterator Object.
|
|
16
16
|
*/
|
|
17
17
|
url: Value<Promisable<string | URL>, [tokenPayload: DurableIteratorTokenPayload, options: StandardLinkInterceptorOptions<T>]>;
|
|
18
18
|
/**
|
|
@@ -24,7 +24,7 @@ interface DurableIteratorLinkPluginOptions<T extends ClientContext> extends Omit
|
|
|
24
24
|
* @remarks
|
|
25
25
|
* - Use a strong random generator to avoid collisions or predictable IDs.
|
|
26
26
|
*
|
|
27
|
-
* @default (() => crypto.randomUUID())
|
|
27
|
+
* @default (() => `${crypto.randomUUID()}-${crypto.randomUUID()}`)
|
|
28
28
|
*/
|
|
29
29
|
createId?: (tokenPayload: DurableIteratorTokenPayload, options: StandardLinkInterceptorOptions<T>) => Promisable<string>;
|
|
30
30
|
/**
|
|
@@ -41,13 +41,10 @@ interface DurableIteratorLinkPluginOptions<T extends ClientContext> extends Omit
|
|
|
41
41
|
refreshTokenBeforeExpireInSeconds?: Value<Promisable<number>, [tokenPayload: DurableIteratorTokenPayload, options: StandardLinkInterceptorOptions<T>]>;
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
* @see {@link https://orpc.unnoq.com/docs/integrations/durable-iterator Durable Iterator Integration}
|
|
44
|
+
* @see {@link https://orpc.unnoq.com/docs/integrations/durable-event-iterator Durable Event Iterator Integration}
|
|
45
45
|
*/
|
|
46
46
|
declare class DurableIteratorLinkPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
|
|
47
47
|
readonly CONTEXT_SYMBOL: symbol;
|
|
48
|
-
/**
|
|
49
|
-
* run before (modify result after) retry plugin because it can break the special iterator
|
|
50
|
-
*/
|
|
51
48
|
order: number;
|
|
52
49
|
private readonly url;
|
|
53
50
|
private readonly createId;
|
package/dist/client/index.mjs
CHANGED
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
import { c as createClientDurableIterator } from '../shared/experimental-durable-iterator.
|
|
2
|
-
export { g as getClientDurableIteratorToken } from '../shared/experimental-durable-iterator.
|
|
1
|
+
import { c as createClientDurableIterator } from '../shared/experimental-durable-iterator.CP6Ouvmj.mjs';
|
|
2
|
+
export { g as getClientDurableIteratorToken } from '../shared/experimental-durable-iterator.CP6Ouvmj.mjs';
|
|
3
3
|
import { createORPCClient } from '@orpc/client';
|
|
4
4
|
import { ClientRetryPlugin } from '@orpc/client/plugins';
|
|
5
5
|
import { RPCLink } from '@orpc/client/websocket';
|
|
6
|
-
import { fallback, value, toArray, AsyncIteratorClass, retry
|
|
6
|
+
import { fallback, value, toArray, AsyncIteratorClass, retry } from '@orpc/shared';
|
|
7
7
|
import { WebSocket } from 'partysocket';
|
|
8
|
-
import { d as DURABLE_ITERATOR_ID_PARAM, c as DURABLE_ITERATOR_TOKEN_PARAM, D as DurableIteratorError, b as DURABLE_ITERATOR_PLUGIN_HEADER_KEY, a as DURABLE_ITERATOR_PLUGIN_HEADER_VALUE, p as parseDurableIteratorToken } from '../shared/experimental-durable-iterator.
|
|
8
|
+
import { d as DURABLE_ITERATOR_ID_PARAM, c as DURABLE_ITERATOR_TOKEN_PARAM, D as DurableIteratorError, b as DURABLE_ITERATOR_PLUGIN_HEADER_KEY, a as DURABLE_ITERATOR_PLUGIN_HEADER_VALUE, p as parseDurableIteratorToken } from '../shared/experimental-durable-iterator.BBUZixu_.mjs';
|
|
9
9
|
import '@orpc/server/helpers';
|
|
10
10
|
import 'valibot';
|
|
11
11
|
|
|
12
12
|
class DurableIteratorLinkPlugin {
|
|
13
13
|
CONTEXT_SYMBOL = Symbol("ORPC_DURABLE_ITERATOR_LINK_PLUGIN_CONTEXT");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
*/
|
|
17
|
-
order = 15e5;
|
|
14
|
+
order = 21e5;
|
|
15
|
+
// make sure execute before the batch plugin and after client retry plugin
|
|
18
16
|
url;
|
|
19
17
|
createId;
|
|
20
18
|
refreshTokenBeforeExpireInSeconds;
|
|
21
19
|
linkOptions;
|
|
22
20
|
constructor({ url, refreshTokenBeforeExpireInSeconds, ...options }) {
|
|
23
21
|
this.url = url;
|
|
24
|
-
this.createId = fallback(options.createId, () => crypto.randomUUID());
|
|
22
|
+
this.createId = fallback(options.createId, () => `${crypto.randomUUID()}-${crypto.randomUUID()}`);
|
|
25
23
|
this.refreshTokenBeforeExpireInSeconds = fallback(refreshTokenBeforeExpireInSeconds, Number.NaN);
|
|
26
24
|
this.linkOptions = options;
|
|
27
25
|
}
|
|
@@ -67,10 +65,15 @@ class DurableIteratorLinkPlugin {
|
|
|
67
65
|
}
|
|
68
66
|
const nowInSeconds = Math.floor(Date.now() / 1e3);
|
|
69
67
|
refreshTokenBeforeExpireTimeoutId = setTimeout(async () => {
|
|
70
|
-
|
|
68
|
+
await retry({ times: Number.POSITIVE_INFINITY, delay: 2e3 }, async (exit) => {
|
|
71
69
|
try {
|
|
72
70
|
const output2 = await next();
|
|
73
|
-
|
|
71
|
+
const newTokenAndPayload = this.validateToken(output2, options2.path);
|
|
72
|
+
if (newTokenAndPayload.payload.chn !== tokenAndPayload.payload.chn) {
|
|
73
|
+
exit(new DurableIteratorError("Refreshed token must have the same channel with the original token"));
|
|
74
|
+
} else {
|
|
75
|
+
tokenAndPayload = newTokenAndPayload;
|
|
76
|
+
}
|
|
74
77
|
} catch (err) {
|
|
75
78
|
if (isFinished) {
|
|
76
79
|
exit(err);
|
|
@@ -78,14 +81,8 @@ class DurableIteratorLinkPlugin {
|
|
|
78
81
|
throw err;
|
|
79
82
|
}
|
|
80
83
|
});
|
|
81
|
-
const canProactivelyUpdateToken = newTokenAndPayload.payload.chn === tokenAndPayload.payload.chn && stringifyJSON(newTokenAndPayload.payload.tags) === stringifyJSON(tokenAndPayload.payload.tags);
|
|
82
|
-
tokenAndPayload = newTokenAndPayload;
|
|
83
84
|
await refreshTokenBeforeExpire();
|
|
84
|
-
|
|
85
|
-
await durableClient.updateToken({ token: tokenAndPayload.token });
|
|
86
|
-
} else {
|
|
87
|
-
websocket.reconnect();
|
|
88
|
-
}
|
|
85
|
+
await durableClient.updateToken({ token: tokenAndPayload.token });
|
|
89
86
|
}, (tokenAndPayload.payload.exp - nowInSeconds - beforeSeconds) * 1e3);
|
|
90
87
|
};
|
|
91
88
|
refreshTokenBeforeExpire();
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { RPCHandlerOptions } from '@orpc/server/websocket';
|
|
2
2
|
import { DurableObject } from 'cloudflare:workers';
|
|
3
|
-
import { b as DurableIteratorTokenPayload, a as DurableIteratorObjectDef, D as DurableIteratorObject$1 } from '../shared/experimental-durable-iterator.
|
|
3
|
+
import { b as DurableIteratorTokenPayload, a as DurableIteratorObjectDef, D as DurableIteratorObject$1 } from '../shared/experimental-durable-iterator.Bh_-Jj0k.mjs';
|
|
4
4
|
import { StandardRPCJsonSerializerOptions } from '@orpc/client/standard';
|
|
5
5
|
import { Interceptor } from '@orpc/shared';
|
|
6
|
-
export { withEventMeta } from '@orpc/server';
|
|
7
6
|
import '@orpc/client';
|
|
8
7
|
import 'valibot';
|
|
9
8
|
|
|
@@ -55,12 +54,12 @@ interface DurableIteratorWebsocketInternal {
|
|
|
55
54
|
}
|
|
56
55
|
interface DurableIteratorWebsocket extends WebSocket {
|
|
57
56
|
/**
|
|
58
|
-
* Durable Event internal apis
|
|
57
|
+
* Durable Event Iterator internal apis
|
|
59
58
|
*/
|
|
60
59
|
['~orpc']: DurableIteratorWebsocketInternal;
|
|
61
60
|
}
|
|
62
61
|
/**
|
|
63
|
-
* Create a Durable Iterator WebSocket from a regular WebSocket
|
|
62
|
+
* Create a Durable Event Iterator WebSocket from a regular WebSocket
|
|
64
63
|
*
|
|
65
64
|
* @info The websocket automatically closes if expired before sending data
|
|
66
65
|
*/
|
|
@@ -74,7 +73,7 @@ interface DurableIteratorObjectStateInternal {
|
|
|
74
73
|
*/
|
|
75
74
|
original: DurableObjectState;
|
|
76
75
|
}
|
|
77
|
-
interface DurableIteratorObjectState
|
|
76
|
+
interface DurableIteratorObjectState extends DurableObjectState {
|
|
78
77
|
/**
|
|
79
78
|
* DurableIteratorObjectState internal apis
|
|
80
79
|
*/
|
|
@@ -85,7 +84,7 @@ interface DurableIteratorObjectState<TProps> extends DurableObjectState<TProps>
|
|
|
85
84
|
*/
|
|
86
85
|
'getWebSockets'(...args: Parameters<DurableObjectState['getWebSockets']>): DurableIteratorWebsocket[];
|
|
87
86
|
}
|
|
88
|
-
declare function toDurableIteratorObjectState
|
|
87
|
+
declare function toDurableIteratorObjectState(original: DurableObjectState): DurableIteratorObjectState;
|
|
89
88
|
|
|
90
89
|
interface EventResumeStorageOptions extends StandardRPCJsonSerializerOptions {
|
|
91
90
|
/**
|
|
@@ -106,15 +105,13 @@ interface EventResumeStorageOptions extends StandardRPCJsonSerializerOptions {
|
|
|
106
105
|
*
|
|
107
106
|
* @default 'orpc:durable-iterator:resume:'
|
|
108
107
|
*/
|
|
109
|
-
|
|
108
|
+
resumeTablePrefix?: string;
|
|
110
109
|
}
|
|
111
110
|
interface ResumeEventFilter {
|
|
112
|
-
/** Only websockets with these tags will receive the event */
|
|
113
|
-
tags?: readonly string[];
|
|
114
111
|
/** Only websockets that are in this list will receive the event */
|
|
115
|
-
targets?:
|
|
112
|
+
targets?: DurableIteratorWebsocket[];
|
|
116
113
|
/** Websockets that are in this list will not receive the event */
|
|
117
|
-
exclude?:
|
|
114
|
+
exclude?: DurableIteratorWebsocket[];
|
|
118
115
|
}
|
|
119
116
|
declare class EventResumeStorage<T extends object> {
|
|
120
117
|
private readonly durableState;
|
|
@@ -142,36 +139,28 @@ declare class EventResumeStorage<T extends object> {
|
|
|
142
139
|
}
|
|
143
140
|
|
|
144
141
|
type DurableIteratorObjectRouterContext = {
|
|
145
|
-
object: DurableObject<any
|
|
142
|
+
object: DurableObject<any>;
|
|
146
143
|
resumeStorage: EventResumeStorage<any>;
|
|
147
144
|
websocket: DurableIteratorWebsocket;
|
|
148
145
|
options: DurableIteratorObjectHandlerOptions;
|
|
149
146
|
};
|
|
150
147
|
interface PublishEventOptions {
|
|
151
|
-
/**
|
|
152
|
-
* Deliver the event only to websockets that have the specified tags.
|
|
153
|
-
*/
|
|
154
|
-
tags?: readonly string[];
|
|
155
148
|
/**
|
|
156
149
|
* Restrict the event to a specific set of websockets.
|
|
157
150
|
*
|
|
158
|
-
* Accept a list of websockets or a filter function.
|
|
159
|
-
*
|
|
160
151
|
* Use this when security is important — only the listed websockets
|
|
161
152
|
* will ever receive the event. Newly connected websockets are not
|
|
162
153
|
* included unless explicitly added here.
|
|
163
154
|
*/
|
|
164
|
-
targets?:
|
|
155
|
+
targets?: WebSocket[];
|
|
165
156
|
/**
|
|
166
157
|
* Exclude certain websockets from receiving the event.
|
|
167
158
|
*
|
|
168
|
-
* Accept a list of websockets or a filter function.
|
|
169
|
-
*
|
|
170
159
|
* Use this when broadcasting widely but skipping a few clients
|
|
171
160
|
* (e.g., the sender). Newly connected websockets may still receive
|
|
172
161
|
* the event if not listed here, so this is less strict than `targets`.
|
|
173
162
|
*/
|
|
174
|
-
exclude?:
|
|
163
|
+
exclude?: WebSocket[];
|
|
175
164
|
}
|
|
176
165
|
interface DurableIteratorObjectHandlerOptions extends RPCHandlerOptions<DurableIteratorObjectRouterContext>, EventResumeStorageOptions {
|
|
177
166
|
/**
|
|
@@ -187,7 +176,7 @@ interface DurableIteratorObjectHandlerOptions extends RPCHandlerOptions<DurableI
|
|
|
187
176
|
*/
|
|
188
177
|
onSubscribed?: (websocket: DurableIteratorWebsocket, lastEventId: string | undefined) => void;
|
|
189
178
|
}
|
|
190
|
-
declare class DurableIteratorObjectHandler<T extends object
|
|
179
|
+
declare class DurableIteratorObjectHandler<T extends object> implements DurableIteratorObjectDef<T> {
|
|
191
180
|
private readonly object;
|
|
192
181
|
private readonly options;
|
|
193
182
|
'~eventPayloadType'?: {
|
|
@@ -198,8 +187,8 @@ declare class DurableIteratorObjectHandler<T extends object, TProps> implements
|
|
|
198
187
|
/**
|
|
199
188
|
* Proxied, ensure you don't accidentally change internal state, and auto close if expired websockets before .send is called
|
|
200
189
|
*/
|
|
201
|
-
ctx: DurableIteratorObjectState
|
|
202
|
-
constructor(ctx: DurableObjectState
|
|
190
|
+
ctx: DurableIteratorObjectState;
|
|
191
|
+
constructor(ctx: DurableObjectState, object: DurableObject<any>, options: DurableIteratorObjectHandlerOptions);
|
|
203
192
|
/**
|
|
204
193
|
* Publish an event to a set of clients.
|
|
205
194
|
*/
|
|
@@ -221,13 +210,13 @@ declare class DurableIteratorObjectHandler<T extends object, TProps> implements
|
|
|
221
210
|
webSocketClose(ws_: WebSocket, _code: number, _reason: string, _wasClean: boolean): void | Promise<void>;
|
|
222
211
|
}
|
|
223
212
|
|
|
224
|
-
declare class DurableIteratorObject<T extends object, TEnv =
|
|
225
|
-
'~orpc': DurableIteratorObjectHandler<T
|
|
213
|
+
declare class DurableIteratorObject<T extends object, TEnv = unknown> extends DurableObject<TEnv> implements DurableIteratorObject$1<T> {
|
|
214
|
+
'~orpc': DurableIteratorObjectHandler<T>;
|
|
226
215
|
/**
|
|
227
216
|
* Proxied, ensure you don't accidentally change internal state, and auto close if expired websockets before .send is called
|
|
228
217
|
*/
|
|
229
|
-
protected ctx: DurableIteratorObjectState
|
|
230
|
-
constructor(ctx: DurableObjectState
|
|
218
|
+
protected ctx: DurableIteratorObjectState;
|
|
219
|
+
constructor(ctx: DurableObjectState, env: TEnv, options: DurableIteratorObjectHandlerOptions);
|
|
231
220
|
/**
|
|
232
221
|
* Publish an event to clients
|
|
233
222
|
*/
|
|
@@ -264,10 +253,6 @@ interface UpgradeDurableIteratorRequestOptions {
|
|
|
264
253
|
* The durable object namespace
|
|
265
254
|
*/
|
|
266
255
|
namespace: DurableObjectNamespace<any>;
|
|
267
|
-
/**
|
|
268
|
-
* The options to use when getting the durable object stub
|
|
269
|
-
*/
|
|
270
|
-
namespaceGetOptions?: DurableObjectNamespaceGetDurableObjectOptions;
|
|
271
256
|
/**
|
|
272
257
|
* intercept upgrade process
|
|
273
258
|
*/
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { RPCHandlerOptions } from '@orpc/server/websocket';
|
|
2
2
|
import { DurableObject } from 'cloudflare:workers';
|
|
3
|
-
import { b as DurableIteratorTokenPayload, a as DurableIteratorObjectDef, D as DurableIteratorObject$1 } from '../shared/experimental-durable-iterator.
|
|
3
|
+
import { b as DurableIteratorTokenPayload, a as DurableIteratorObjectDef, D as DurableIteratorObject$1 } from '../shared/experimental-durable-iterator.Bh_-Jj0k.js';
|
|
4
4
|
import { StandardRPCJsonSerializerOptions } from '@orpc/client/standard';
|
|
5
5
|
import { Interceptor } from '@orpc/shared';
|
|
6
|
-
export { withEventMeta } from '@orpc/server';
|
|
7
6
|
import '@orpc/client';
|
|
8
7
|
import 'valibot';
|
|
9
8
|
|
|
@@ -55,12 +54,12 @@ interface DurableIteratorWebsocketInternal {
|
|
|
55
54
|
}
|
|
56
55
|
interface DurableIteratorWebsocket extends WebSocket {
|
|
57
56
|
/**
|
|
58
|
-
* Durable Event internal apis
|
|
57
|
+
* Durable Event Iterator internal apis
|
|
59
58
|
*/
|
|
60
59
|
['~orpc']: DurableIteratorWebsocketInternal;
|
|
61
60
|
}
|
|
62
61
|
/**
|
|
63
|
-
* Create a Durable Iterator WebSocket from a regular WebSocket
|
|
62
|
+
* Create a Durable Event Iterator WebSocket from a regular WebSocket
|
|
64
63
|
*
|
|
65
64
|
* @info The websocket automatically closes if expired before sending data
|
|
66
65
|
*/
|
|
@@ -74,7 +73,7 @@ interface DurableIteratorObjectStateInternal {
|
|
|
74
73
|
*/
|
|
75
74
|
original: DurableObjectState;
|
|
76
75
|
}
|
|
77
|
-
interface DurableIteratorObjectState
|
|
76
|
+
interface DurableIteratorObjectState extends DurableObjectState {
|
|
78
77
|
/**
|
|
79
78
|
* DurableIteratorObjectState internal apis
|
|
80
79
|
*/
|
|
@@ -85,7 +84,7 @@ interface DurableIteratorObjectState<TProps> extends DurableObjectState<TProps>
|
|
|
85
84
|
*/
|
|
86
85
|
'getWebSockets'(...args: Parameters<DurableObjectState['getWebSockets']>): DurableIteratorWebsocket[];
|
|
87
86
|
}
|
|
88
|
-
declare function toDurableIteratorObjectState
|
|
87
|
+
declare function toDurableIteratorObjectState(original: DurableObjectState): DurableIteratorObjectState;
|
|
89
88
|
|
|
90
89
|
interface EventResumeStorageOptions extends StandardRPCJsonSerializerOptions {
|
|
91
90
|
/**
|
|
@@ -106,15 +105,13 @@ interface EventResumeStorageOptions extends StandardRPCJsonSerializerOptions {
|
|
|
106
105
|
*
|
|
107
106
|
* @default 'orpc:durable-iterator:resume:'
|
|
108
107
|
*/
|
|
109
|
-
|
|
108
|
+
resumeTablePrefix?: string;
|
|
110
109
|
}
|
|
111
110
|
interface ResumeEventFilter {
|
|
112
|
-
/** Only websockets with these tags will receive the event */
|
|
113
|
-
tags?: readonly string[];
|
|
114
111
|
/** Only websockets that are in this list will receive the event */
|
|
115
|
-
targets?:
|
|
112
|
+
targets?: DurableIteratorWebsocket[];
|
|
116
113
|
/** Websockets that are in this list will not receive the event */
|
|
117
|
-
exclude?:
|
|
114
|
+
exclude?: DurableIteratorWebsocket[];
|
|
118
115
|
}
|
|
119
116
|
declare class EventResumeStorage<T extends object> {
|
|
120
117
|
private readonly durableState;
|
|
@@ -142,36 +139,28 @@ declare class EventResumeStorage<T extends object> {
|
|
|
142
139
|
}
|
|
143
140
|
|
|
144
141
|
type DurableIteratorObjectRouterContext = {
|
|
145
|
-
object: DurableObject<any
|
|
142
|
+
object: DurableObject<any>;
|
|
146
143
|
resumeStorage: EventResumeStorage<any>;
|
|
147
144
|
websocket: DurableIteratorWebsocket;
|
|
148
145
|
options: DurableIteratorObjectHandlerOptions;
|
|
149
146
|
};
|
|
150
147
|
interface PublishEventOptions {
|
|
151
|
-
/**
|
|
152
|
-
* Deliver the event only to websockets that have the specified tags.
|
|
153
|
-
*/
|
|
154
|
-
tags?: readonly string[];
|
|
155
148
|
/**
|
|
156
149
|
* Restrict the event to a specific set of websockets.
|
|
157
150
|
*
|
|
158
|
-
* Accept a list of websockets or a filter function.
|
|
159
|
-
*
|
|
160
151
|
* Use this when security is important — only the listed websockets
|
|
161
152
|
* will ever receive the event. Newly connected websockets are not
|
|
162
153
|
* included unless explicitly added here.
|
|
163
154
|
*/
|
|
164
|
-
targets?:
|
|
155
|
+
targets?: WebSocket[];
|
|
165
156
|
/**
|
|
166
157
|
* Exclude certain websockets from receiving the event.
|
|
167
158
|
*
|
|
168
|
-
* Accept a list of websockets or a filter function.
|
|
169
|
-
*
|
|
170
159
|
* Use this when broadcasting widely but skipping a few clients
|
|
171
160
|
* (e.g., the sender). Newly connected websockets may still receive
|
|
172
161
|
* the event if not listed here, so this is less strict than `targets`.
|
|
173
162
|
*/
|
|
174
|
-
exclude?:
|
|
163
|
+
exclude?: WebSocket[];
|
|
175
164
|
}
|
|
176
165
|
interface DurableIteratorObjectHandlerOptions extends RPCHandlerOptions<DurableIteratorObjectRouterContext>, EventResumeStorageOptions {
|
|
177
166
|
/**
|
|
@@ -187,7 +176,7 @@ interface DurableIteratorObjectHandlerOptions extends RPCHandlerOptions<DurableI
|
|
|
187
176
|
*/
|
|
188
177
|
onSubscribed?: (websocket: DurableIteratorWebsocket, lastEventId: string | undefined) => void;
|
|
189
178
|
}
|
|
190
|
-
declare class DurableIteratorObjectHandler<T extends object
|
|
179
|
+
declare class DurableIteratorObjectHandler<T extends object> implements DurableIteratorObjectDef<T> {
|
|
191
180
|
private readonly object;
|
|
192
181
|
private readonly options;
|
|
193
182
|
'~eventPayloadType'?: {
|
|
@@ -198,8 +187,8 @@ declare class DurableIteratorObjectHandler<T extends object, TProps> implements
|
|
|
198
187
|
/**
|
|
199
188
|
* Proxied, ensure you don't accidentally change internal state, and auto close if expired websockets before .send is called
|
|
200
189
|
*/
|
|
201
|
-
ctx: DurableIteratorObjectState
|
|
202
|
-
constructor(ctx: DurableObjectState
|
|
190
|
+
ctx: DurableIteratorObjectState;
|
|
191
|
+
constructor(ctx: DurableObjectState, object: DurableObject<any>, options: DurableIteratorObjectHandlerOptions);
|
|
203
192
|
/**
|
|
204
193
|
* Publish an event to a set of clients.
|
|
205
194
|
*/
|
|
@@ -221,13 +210,13 @@ declare class DurableIteratorObjectHandler<T extends object, TProps> implements
|
|
|
221
210
|
webSocketClose(ws_: WebSocket, _code: number, _reason: string, _wasClean: boolean): void | Promise<void>;
|
|
222
211
|
}
|
|
223
212
|
|
|
224
|
-
declare class DurableIteratorObject<T extends object, TEnv =
|
|
225
|
-
'~orpc': DurableIteratorObjectHandler<T
|
|
213
|
+
declare class DurableIteratorObject<T extends object, TEnv = unknown> extends DurableObject<TEnv> implements DurableIteratorObject$1<T> {
|
|
214
|
+
'~orpc': DurableIteratorObjectHandler<T>;
|
|
226
215
|
/**
|
|
227
216
|
* Proxied, ensure you don't accidentally change internal state, and auto close if expired websockets before .send is called
|
|
228
217
|
*/
|
|
229
|
-
protected ctx: DurableIteratorObjectState
|
|
230
|
-
constructor(ctx: DurableObjectState
|
|
218
|
+
protected ctx: DurableIteratorObjectState;
|
|
219
|
+
constructor(ctx: DurableObjectState, env: TEnv, options: DurableIteratorObjectHandlerOptions);
|
|
231
220
|
/**
|
|
232
221
|
* Publish an event to clients
|
|
233
222
|
*/
|
|
@@ -264,10 +253,6 @@ interface UpgradeDurableIteratorRequestOptions {
|
|
|
264
253
|
* The durable object namespace
|
|
265
254
|
*/
|
|
266
255
|
namespace: DurableObjectNamespace<any>;
|
|
267
|
-
/**
|
|
268
|
-
* The options to use when getting the durable object stub
|
|
269
|
-
*/
|
|
270
|
-
namespaceGetOptions?: DurableObjectNamespaceGetDurableObjectOptions;
|
|
271
256
|
/**
|
|
272
257
|
* intercept upgrade process
|
|
273
258
|
*/
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { getEventMeta, withEventMeta, implement, ORPCError } from '@orpc/server';
|
|
2
|
-
export { withEventMeta } from '@orpc/server';
|
|
3
2
|
import { HibernationEventIterator, encodeHibernationRPCEvent, HibernationPlugin } from '@orpc/server/hibernation';
|
|
4
3
|
import { RPCHandler } from '@orpc/server/websocket';
|
|
5
4
|
import { fallback, parseEmptyableJSON, stringifyJSON, get, toArray, intercept } from '@orpc/shared';
|
|
6
|
-
import { D as DurableIteratorError, v as verifyDurableIteratorToken, c as DURABLE_ITERATOR_TOKEN_PARAM, d as DURABLE_ITERATOR_ID_PARAM } from '../shared/experimental-durable-iterator.
|
|
5
|
+
import { D as DurableIteratorError, v as verifyDurableIteratorToken, c as DURABLE_ITERATOR_TOKEN_PARAM, d as DURABLE_ITERATOR_ID_PARAM } from '../shared/experimental-durable-iterator.BBUZixu_.mjs';
|
|
7
6
|
import { d as durableIteratorContract } from '../shared/experimental-durable-iterator.BRB0hiXN.mjs';
|
|
8
7
|
import { StandardRPCJsonSerializer } from '@orpc/client/standard';
|
|
9
8
|
import { DurableObject } from 'cloudflare:workers';
|
|
@@ -134,7 +133,7 @@ class EventResumeStorage {
|
|
|
134
133
|
constructor(durableState, options = {}) {
|
|
135
134
|
this.durableState = durableState;
|
|
136
135
|
this.retentionSeconds = fallback(options.resumeRetentionSeconds, Number.NaN);
|
|
137
|
-
this.schemaPrefix = fallback(options.
|
|
136
|
+
this.schemaPrefix = fallback(options.resumeTablePrefix, "orpc:durable-iterator:resume:");
|
|
138
137
|
this.serializer = new StandardRPCJsonSerializer(options);
|
|
139
138
|
if (this.isEnabled) {
|
|
140
139
|
this.initSchema();
|
|
@@ -166,9 +165,8 @@ class EventResumeStorage {
|
|
|
166
165
|
);
|
|
167
166
|
const insertEvent = () => {
|
|
168
167
|
const insertResult = this.durableState.storage.sql.exec(
|
|
169
|
-
`INSERT INTO "${this.schemaPrefix}events" (payload,
|
|
168
|
+
`INSERT INTO "${this.schemaPrefix}events" (payload, target_ids, exclusion_ids) VALUES (?, ?, ?) RETURNING CAST(id AS TEXT) as id`,
|
|
170
169
|
serializedEvent,
|
|
171
|
-
stringifyJSON(resumeFilter.tags),
|
|
172
170
|
stringifyJSON(targetIds),
|
|
173
171
|
stringifyJSON(excludeIds)
|
|
174
172
|
);
|
|
@@ -190,19 +188,14 @@ class EventResumeStorage {
|
|
|
190
188
|
return [];
|
|
191
189
|
}
|
|
192
190
|
this.cleanupExpiredEvents();
|
|
193
|
-
const websocketTags = websocket["~orpc"].deserializeTokenPayload().tags;
|
|
194
191
|
const websocketId = websocket["~orpc"].deserializeId();
|
|
195
192
|
const resumeQuery = this.durableState.storage.sql.exec(`
|
|
196
|
-
SELECT CAST(id AS TEXT) as id, payload,
|
|
193
|
+
SELECT CAST(id AS TEXT) as id, payload, target_ids, exclusion_ids
|
|
197
194
|
FROM "${this.schemaPrefix}events"
|
|
198
195
|
WHERE id > ?
|
|
199
196
|
ORDER BY id ASC
|
|
200
197
|
`, lastEventId);
|
|
201
198
|
return resumeQuery.toArray().filter((resumeRecord) => {
|
|
202
|
-
const tags = parseEmptyableJSON(resumeRecord.tags);
|
|
203
|
-
if (tags && !tags.some((tag) => websocketTags?.includes(tag))) {
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
199
|
const resumeTargetIds = parseEmptyableJSON(resumeRecord.target_ids);
|
|
207
200
|
const resumeExclusionIds = parseEmptyableJSON(resumeRecord.exclusion_ids);
|
|
208
201
|
if (resumeTargetIds && !resumeTargetIds.includes(websocketId)) {
|
|
@@ -222,7 +215,6 @@ class EventResumeStorage {
|
|
|
222
215
|
CREATE TABLE IF NOT EXISTS "${this.schemaPrefix}events" (
|
|
223
216
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
224
217
|
payload TEXT NOT NULL,
|
|
225
|
-
tags TEXT,
|
|
226
218
|
target_ids TEXT,
|
|
227
219
|
exclusion_ids TEXT,
|
|
228
220
|
stored_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
@@ -276,9 +268,6 @@ const router = base.router({
|
|
|
276
268
|
if (payload.chn !== old.chn) {
|
|
277
269
|
throw new ORPCError("UNAUTHORIZED", { message: "Updated token must have the same channel with the original token" });
|
|
278
270
|
}
|
|
279
|
-
if (stringifyJSON(payload.tags) !== stringifyJSON(old.tags)) {
|
|
280
|
-
throw new ORPCError("UNAUTHORIZED", { message: "Updated token must have the exact same tags with the original token" });
|
|
281
|
-
}
|
|
282
271
|
context.websocket["~orpc"].serializeTokenPayload(payload);
|
|
283
272
|
}),
|
|
284
273
|
subscribe: base.subscribe.handler(({ context, lastEventId }) => {
|
|
@@ -338,44 +327,13 @@ class DurableIteratorObjectHandler {
|
|
|
338
327
|
* Publish an event to a set of clients.
|
|
339
328
|
*/
|
|
340
329
|
publishEvent(payload, options = {}) {
|
|
341
|
-
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
const uniqueTargets = targets.filter((ws, index) => {
|
|
345
|
-
const id = ws["~orpc"].deserializeId();
|
|
346
|
-
return targets?.findIndex((ws2) => ws2["~orpc"].deserializeId() === id) === index;
|
|
347
|
-
});
|
|
348
|
-
if (!options.tags) {
|
|
349
|
-
return uniqueTargets;
|
|
350
|
-
}
|
|
351
|
-
return uniqueTargets.filter(
|
|
352
|
-
(ws) => ws["~orpc"].deserializeTokenPayload().tags?.some((tag) => options.tags?.includes(tag))
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
|
-
if (options.tags) {
|
|
356
|
-
const websockets = options.tags.map((tag) => this.ctx.getWebSockets(tag)).flat();
|
|
357
|
-
const uniqueWebsockets = websockets.filter((ws, index) => {
|
|
358
|
-
const id = ws["~orpc"].deserializeId();
|
|
359
|
-
return websockets.findIndex((ws2) => ws2["~orpc"].deserializeId() === id) === index;
|
|
360
|
-
});
|
|
361
|
-
return uniqueWebsockets;
|
|
362
|
-
} else {
|
|
363
|
-
return this.ctx.getWebSockets();
|
|
364
|
-
}
|
|
365
|
-
})();
|
|
366
|
-
if (typeof options.targets === "function") {
|
|
367
|
-
targets = websocketsFilteredByTags.filter(options.targets);
|
|
368
|
-
}
|
|
369
|
-
const exclude = Array.isArray(options.exclude) ? options.exclude.map(toDurableIteratorWebsocket) : typeof options.exclude === "function" ? websocketsFilteredByTags.filter(options.exclude) : void 0;
|
|
370
|
-
payload = this.resumeStorage.store(payload, { tags: options.tags, targets, exclude });
|
|
371
|
-
const targetIds = targets?.map((ws) => ws["~orpc"].deserializeId());
|
|
330
|
+
const targets = options.targets?.map((ws) => toDurableIteratorWebsocket(ws));
|
|
331
|
+
const exclude = options.exclude?.map((ws) => toDurableIteratorWebsocket(ws));
|
|
332
|
+
payload = this.resumeStorage.store(payload, { targets, exclude });
|
|
372
333
|
const excludeIds = exclude?.map((ws) => ws["~orpc"].deserializeId());
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
if (excludeIds?.includes(wsId)) {
|
|
334
|
+
const fallbackTargets = targets ?? this.ctx.getWebSockets().map((ws) => toDurableIteratorWebsocket(ws));
|
|
335
|
+
for (const ws of fallbackTargets) {
|
|
336
|
+
if (excludeIds?.includes(ws["~orpc"].deserializeId())) {
|
|
379
337
|
continue;
|
|
380
338
|
}
|
|
381
339
|
const hibernationId = ws["~orpc"].deserializeHibernationId();
|
|
@@ -408,11 +366,7 @@ class DurableIteratorObjectHandler {
|
|
|
408
366
|
return new Response("Invalid Token", { status: 401 });
|
|
409
367
|
}
|
|
410
368
|
const { "0": client, "1": server } = new WebSocketPair();
|
|
411
|
-
|
|
412
|
-
this.ctx.acceptWebSocket(server, [...payload.tags]);
|
|
413
|
-
} else {
|
|
414
|
-
this.ctx.acceptWebSocket(server);
|
|
415
|
-
}
|
|
369
|
+
this.ctx.acceptWebSocket(server);
|
|
416
370
|
toDurableIteratorWebsocket(server)["~orpc"].serializeId(id);
|
|
417
371
|
toDurableIteratorWebsocket(server)["~orpc"].serializeTokenPayload(payload);
|
|
418
372
|
return new Response(null, {
|
|
@@ -527,7 +481,7 @@ async function upgradeDurableIteratorRequest(request, options) {
|
|
|
527
481
|
async ({ payload: payload2 }) => {
|
|
528
482
|
const namespace = options.namespace;
|
|
529
483
|
const id2 = namespace.idFromName(payload2.chn);
|
|
530
|
-
const stub = namespace.get(id2
|
|
484
|
+
const stub = namespace.get(id2);
|
|
531
485
|
return stub.fetch(request);
|
|
532
486
|
}
|
|
533
487
|
);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as _orpc_contract from '@orpc/contract';
|
|
2
2
|
import { AsyncIteratorClass } from '@orpc/shared';
|
|
3
3
|
import * as v from 'valibot';
|
|
4
|
-
import { C as ClientDurableIterator } from './shared/experimental-durable-iterator.
|
|
5
|
-
import { D as DurableIteratorObject, I as InferDurableIteratorObjectRPC } from './shared/experimental-durable-iterator.
|
|
6
|
-
export { a as DurableIteratorObjectDef, b as DurableIteratorTokenPayload, p as parseDurableIteratorToken, s as signDurableIteratorToken, v as verifyDurableIteratorToken } from './shared/experimental-durable-iterator.
|
|
4
|
+
import { C as ClientDurableIterator } from './shared/experimental-durable-iterator.DDJKw0d4.mjs';
|
|
5
|
+
import { D as DurableIteratorObject, I as InferDurableIteratorObjectRPC } from './shared/experimental-durable-iterator.Bh_-Jj0k.mjs';
|
|
6
|
+
export { a as DurableIteratorObjectDef, b as DurableIteratorTokenPayload, p as parseDurableIteratorToken, s as signDurableIteratorToken, v as verifyDurableIteratorToken } from './shared/experimental-durable-iterator.Bh_-Jj0k.mjs';
|
|
7
7
|
import { Context, Router } from '@orpc/server';
|
|
8
8
|
import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
|
|
9
9
|
import '@orpc/client';
|
|
@@ -40,10 +40,6 @@ interface DurableIteratorOptions<T extends DurableIteratorObject<any>, RPC exten
|
|
|
40
40
|
* @default 24 hours (60 * 60 * 24)
|
|
41
41
|
*/
|
|
42
42
|
tokenTTLSeconds?: number;
|
|
43
|
-
/**
|
|
44
|
-
* Tags to attach to the token.
|
|
45
|
-
*/
|
|
46
|
-
tags?: readonly string[];
|
|
47
43
|
/**
|
|
48
44
|
* Token's attachment
|
|
49
45
|
*/
|
|
@@ -72,13 +68,10 @@ interface DurableIteratorHandlerPluginContext {
|
|
|
72
68
|
isClientDurableIteratorOutput?: boolean;
|
|
73
69
|
}
|
|
74
70
|
/**
|
|
75
|
-
* @see {@link https://orpc.unnoq.com/docs/integrations/durable-iterator Durable Iterator Integration}
|
|
71
|
+
* @see {@link https://orpc.unnoq.com/docs/integrations/durable-event-iterator Durable Event Iterator Integration}
|
|
76
72
|
*/
|
|
77
73
|
declare class DurableIteratorHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
78
74
|
readonly CONTEXT_SYMBOL: symbol;
|
|
79
|
-
/**
|
|
80
|
-
* make sure run after batch plugin
|
|
81
|
-
*/
|
|
82
75
|
order: number;
|
|
83
76
|
init(options: StandardHandlerOptions<T>, _router: Router<any, T>): void;
|
|
84
77
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as _orpc_contract from '@orpc/contract';
|
|
2
2
|
import { AsyncIteratorClass } from '@orpc/shared';
|
|
3
3
|
import * as v from 'valibot';
|
|
4
|
-
import { C as ClientDurableIterator } from './shared/experimental-durable-iterator.
|
|
5
|
-
import { D as DurableIteratorObject, I as InferDurableIteratorObjectRPC } from './shared/experimental-durable-iterator.
|
|
6
|
-
export { a as DurableIteratorObjectDef, b as DurableIteratorTokenPayload, p as parseDurableIteratorToken, s as signDurableIteratorToken, v as verifyDurableIteratorToken } from './shared/experimental-durable-iterator.
|
|
4
|
+
import { C as ClientDurableIterator } from './shared/experimental-durable-iterator.B0U3VKpv.js';
|
|
5
|
+
import { D as DurableIteratorObject, I as InferDurableIteratorObjectRPC } from './shared/experimental-durable-iterator.Bh_-Jj0k.js';
|
|
6
|
+
export { a as DurableIteratorObjectDef, b as DurableIteratorTokenPayload, p as parseDurableIteratorToken, s as signDurableIteratorToken, v as verifyDurableIteratorToken } from './shared/experimental-durable-iterator.Bh_-Jj0k.js';
|
|
7
7
|
import { Context, Router } from '@orpc/server';
|
|
8
8
|
import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
|
|
9
9
|
import '@orpc/client';
|
|
@@ -40,10 +40,6 @@ interface DurableIteratorOptions<T extends DurableIteratorObject<any>, RPC exten
|
|
|
40
40
|
* @default 24 hours (60 * 60 * 24)
|
|
41
41
|
*/
|
|
42
42
|
tokenTTLSeconds?: number;
|
|
43
|
-
/**
|
|
44
|
-
* Tags to attach to the token.
|
|
45
|
-
*/
|
|
46
|
-
tags?: readonly string[];
|
|
47
43
|
/**
|
|
48
44
|
* Token's attachment
|
|
49
45
|
*/
|
|
@@ -72,13 +68,10 @@ interface DurableIteratorHandlerPluginContext {
|
|
|
72
68
|
isClientDurableIteratorOutput?: boolean;
|
|
73
69
|
}
|
|
74
70
|
/**
|
|
75
|
-
* @see {@link https://orpc.unnoq.com/docs/integrations/durable-iterator Durable Iterator Integration}
|
|
71
|
+
* @see {@link https://orpc.unnoq.com/docs/integrations/durable-event-iterator Durable Event Iterator Integration}
|
|
76
72
|
*/
|
|
77
73
|
declare class DurableIteratorHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
78
74
|
readonly CONTEXT_SYMBOL: symbol;
|
|
79
|
-
/**
|
|
80
|
-
* make sure run after batch plugin
|
|
81
|
-
*/
|
|
82
75
|
order: number;
|
|
83
76
|
init(options: StandardHandlerOptions<T>, _router: Router<any, T>): void;
|
|
84
77
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { s as signDurableIteratorToken, D as DurableIteratorError, a as DURABLE_ITERATOR_PLUGIN_HEADER_VALUE, b as DURABLE_ITERATOR_PLUGIN_HEADER_KEY } from './shared/experimental-durable-iterator.
|
|
2
|
-
export { d as DURABLE_ITERATOR_ID_PARAM, c as DURABLE_ITERATOR_TOKEN_PARAM, p as parseDurableIteratorToken, v as verifyDurableIteratorToken } from './shared/experimental-durable-iterator.
|
|
1
|
+
import { s as signDurableIteratorToken, D as DurableIteratorError, a as DURABLE_ITERATOR_PLUGIN_HEADER_VALUE, b as DURABLE_ITERATOR_PLUGIN_HEADER_KEY } from './shared/experimental-durable-iterator.BBUZixu_.mjs';
|
|
2
|
+
export { d as DURABLE_ITERATOR_ID_PARAM, c as DURABLE_ITERATOR_TOKEN_PARAM, p as parseDurableIteratorToken, v as verifyDurableIteratorToken } from './shared/experimental-durable-iterator.BBUZixu_.mjs';
|
|
3
3
|
export { d as durableIteratorContract } from './shared/experimental-durable-iterator.BRB0hiXN.mjs';
|
|
4
4
|
import { AsyncIteratorClass } from '@orpc/shared';
|
|
5
|
-
import { c as createClientDurableIterator, g as getClientDurableIteratorToken } from './shared/experimental-durable-iterator.
|
|
5
|
+
import { c as createClientDurableIterator, g as getClientDurableIteratorToken } from './shared/experimental-durable-iterator.CP6Ouvmj.mjs';
|
|
6
6
|
import '@orpc/client';
|
|
7
7
|
import '@orpc/client/plugins';
|
|
8
8
|
import '@orpc/client/websocket';
|
|
@@ -31,7 +31,6 @@ class DurableIterator {
|
|
|
31
31
|
const nowInSeconds = Math.floor(Date.now() / 1e3);
|
|
32
32
|
const token = await signDurableIteratorToken(this.options.signingKey, {
|
|
33
33
|
chn: this.chn,
|
|
34
|
-
tags: this.options.tags,
|
|
35
34
|
att: this.options.att,
|
|
36
35
|
rpc: this.options.rpc,
|
|
37
36
|
iat: nowInSeconds,
|
|
@@ -56,10 +55,8 @@ class DurableIterator {
|
|
|
56
55
|
|
|
57
56
|
class DurableIteratorHandlerPlugin {
|
|
58
57
|
CONTEXT_SYMBOL = Symbol("ORPC_DURABLE_ITERATOR_HANDLER_PLUGIN_CONTEXT");
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*/
|
|
62
|
-
order = 15e5;
|
|
58
|
+
order = 21e5;
|
|
59
|
+
// make sure execute after the batch plugin
|
|
63
60
|
init(options, _router) {
|
|
64
61
|
options.interceptors ??= [];
|
|
65
62
|
options.clientInterceptors ??= [];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NestedClient, Client, ThrowableError, ClientLink } from '@orpc/client';
|
|
2
2
|
import { ClientRetryPluginContext } from '@orpc/client/plugins';
|
|
3
3
|
import { AsyncIteratorClass } from '@orpc/shared';
|
|
4
|
-
import { D as DurableIteratorObject, I as InferDurableIteratorObjectRPC } from './experimental-durable-iterator.
|
|
4
|
+
import { D as DurableIteratorObject, I as InferDurableIteratorObjectRPC } from './experimental-durable-iterator.Bh_-Jj0k.js';
|
|
5
5
|
|
|
6
6
|
interface ClientDurableIteratorRpcContext extends ClientRetryPluginContext {
|
|
7
7
|
}
|
|
@@ -20,7 +20,7 @@ interface CreateClientDurableIteratorOptions {
|
|
|
20
20
|
}
|
|
21
21
|
declare function createClientDurableIterator<T extends DurableIteratorObject<any>, RPC extends InferDurableIteratorObjectRPC<T>>(iterator: AsyncIteratorClass<T>, link: ClientLink<object>, options: CreateClientDurableIteratorOptions): ClientDurableIterator<T, RPC>;
|
|
22
22
|
/**
|
|
23
|
-
* If return a token if the client is a Client Durable Iterator.
|
|
23
|
+
* If return a token if the client is a Client Durable Event Iterator.
|
|
24
24
|
*/
|
|
25
25
|
declare function getClientDurableIteratorToken(client: unknown): string | undefined;
|
|
26
26
|
|
|
@@ -12,7 +12,6 @@ class DurableIteratorError extends Error {
|
|
|
12
12
|
|
|
13
13
|
const DurableIteratorTokenPayloadSchema = v.object({
|
|
14
14
|
chn: v.pipe(v.string(), v.description("Channel name")),
|
|
15
|
-
tags: v.pipe(v.optional(v.array(v.string())), v.readonly(), v.description("Tags")),
|
|
16
15
|
att: v.pipe(v.optional(v.unknown()), v.description("Attachment")),
|
|
17
16
|
rpc: v.pipe(v.optional(v.array(v.string())), v.readonly(), v.description("Allowed remote methods")),
|
|
18
17
|
iat: v.pipe(v.number(), v.description("Issued at time in seconds")),
|
|
@@ -17,7 +17,6 @@ type InferDurableIteratorObjectRPC<T extends DurableIteratorObject<any>> = Exclu
|
|
|
17
17
|
type DurableIteratorTokenPayload = v.InferOutput<typeof DurableIteratorTokenPayloadSchema>;
|
|
18
18
|
declare const DurableIteratorTokenPayloadSchema: v.ObjectSchema<{
|
|
19
19
|
readonly chn: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.DescriptionAction<string, "Channel name">]>;
|
|
20
|
-
readonly tags: v.SchemaWithPipe<readonly [v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, v.ReadonlyAction<string[] | undefined>, v.DescriptionAction<readonly string[] | undefined, "Tags">]>;
|
|
21
20
|
readonly att: v.SchemaWithPipe<readonly [v.OptionalSchema<v.UnknownSchema, undefined>, v.DescriptionAction<unknown, "Attachment">]>;
|
|
22
21
|
readonly rpc: v.SchemaWithPipe<readonly [v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, v.ReadonlyAction<string[] | undefined>, v.DescriptionAction<readonly string[] | undefined, "Allowed remote methods">]>;
|
|
23
22
|
readonly iat: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.DescriptionAction<number, "Issued at time in seconds">]>;
|
|
@@ -17,7 +17,6 @@ type InferDurableIteratorObjectRPC<T extends DurableIteratorObject<any>> = Exclu
|
|
|
17
17
|
type DurableIteratorTokenPayload = v.InferOutput<typeof DurableIteratorTokenPayloadSchema>;
|
|
18
18
|
declare const DurableIteratorTokenPayloadSchema: v.ObjectSchema<{
|
|
19
19
|
readonly chn: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.DescriptionAction<string, "Channel name">]>;
|
|
20
|
-
readonly tags: v.SchemaWithPipe<readonly [v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, v.ReadonlyAction<string[] | undefined>, v.DescriptionAction<readonly string[] | undefined, "Tags">]>;
|
|
21
20
|
readonly att: v.SchemaWithPipe<readonly [v.OptionalSchema<v.UnknownSchema, undefined>, v.DescriptionAction<unknown, "Attachment">]>;
|
|
22
21
|
readonly rpc: v.SchemaWithPipe<readonly [v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>, v.ReadonlyAction<string[] | undefined>, v.DescriptionAction<readonly string[] | undefined, "Allowed remote methods">]>;
|
|
23
22
|
readonly iat: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.DescriptionAction<number, "Issued at time in seconds">]>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createORPCClient } from '@orpc/client';
|
|
2
2
|
import { isAsyncIteratorObject } from '@orpc/shared';
|
|
3
|
-
import { p as parseDurableIteratorToken } from './experimental-durable-iterator.
|
|
3
|
+
import { p as parseDurableIteratorToken } from './experimental-durable-iterator.BBUZixu_.mjs';
|
|
4
4
|
|
|
5
5
|
const CLIENT_DURABLE_ITERATOR_TOKEN_SYMBOL = Symbol("ORPC_CLIENT_DURABLE_ITERATOR_TOKEN");
|
|
6
6
|
function createClientDurableIterator(iterator, link, options) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NestedClient, Client, ThrowableError, ClientLink } from '@orpc/client';
|
|
2
2
|
import { ClientRetryPluginContext } from '@orpc/client/plugins';
|
|
3
3
|
import { AsyncIteratorClass } from '@orpc/shared';
|
|
4
|
-
import { D as DurableIteratorObject, I as InferDurableIteratorObjectRPC } from './experimental-durable-iterator.
|
|
4
|
+
import { D as DurableIteratorObject, I as InferDurableIteratorObjectRPC } from './experimental-durable-iterator.Bh_-Jj0k.mjs';
|
|
5
5
|
|
|
6
6
|
interface ClientDurableIteratorRpcContext extends ClientRetryPluginContext {
|
|
7
7
|
}
|
|
@@ -20,7 +20,7 @@ interface CreateClientDurableIteratorOptions {
|
|
|
20
20
|
}
|
|
21
21
|
declare function createClientDurableIterator<T extends DurableIteratorObject<any>, RPC extends InferDurableIteratorObjectRPC<T>>(iterator: AsyncIteratorClass<T>, link: ClientLink<object>, options: CreateClientDurableIteratorOptions): ClientDurableIterator<T, RPC>;
|
|
22
22
|
/**
|
|
23
|
-
* If return a token if the client is a Client Durable Iterator.
|
|
23
|
+
* If return a token if the client is a Client Durable Event Iterator.
|
|
24
24
|
*/
|
|
25
25
|
declare function getClientDurableIteratorToken(client: unknown): string | undefined;
|
|
26
26
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/experimental-durable-iterator",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.0
|
|
4
|
+
"version": "0.0.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://orpc.unnoq.com",
|
|
7
7
|
"repository": {
|
|
@@ -36,15 +36,15 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"partysocket": "^1.1.5",
|
|
38
38
|
"valibot": "^1.1.0",
|
|
39
|
-
"@orpc/client": "
|
|
40
|
-
"@orpc/contract": "
|
|
41
|
-
"@orpc/server": "
|
|
42
|
-
"@orpc/shared": "
|
|
39
|
+
"@orpc/client": "1.8.7",
|
|
40
|
+
"@orpc/contract": "1.8.7",
|
|
41
|
+
"@orpc/server": "1.8.7",
|
|
42
|
+
"@orpc/shared": "1.8.7"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@cloudflare/workers-types": "^4.
|
|
45
|
+
"@cloudflare/workers-types": "^4.20250903.0",
|
|
46
46
|
"@types/node": "^22.15.30",
|
|
47
|
-
"@orpc/standard-server-peer": "
|
|
47
|
+
"@orpc/standard-server-peer": "1.8.7"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "unbuild",
|