-
-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathiterator.ts
More file actions
100 lines (86 loc) · 2.99 KB
/
iterator.ts
File metadata and controls
100 lines (86 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import type { ClientLink } from '@orpc/client'
import type { ClientDurableIterator } from './client'
import type { DurableIteratorObject, InferDurableIteratorObjectRPC } from './object'
import { AsyncIteratorClass } from '@orpc/shared'
import { createClientDurableIterator } from './client'
import { DurableIteratorError } from './error'
import { signDurableIteratorToken } from './schemas'
export interface DurableIteratorOptions<
T extends DurableIteratorObject<any>,
RPC extends InferDurableIteratorObjectRPC<T>,
> {
/**
* The signing key used to sign the token
*/
signingKey: string
/**
* Time to live for the token in seconds.
* After expiration, the token will no longer be valid.
*
* @default 24 hours (60 * 60 * 24)
*/
tokenTTLSeconds?: number
/**
* Tags to attach to the token.
*/
tags?: readonly string[]
/**
* Token's attachment
*/
att?: unknown
/**
* The methods that are allowed to be called remotely.
*
* @warning Please use .rpc method to set this field in case ts complains about value you pass
*/
rpc?: readonly RPC[]
}
export class DurableIterator<
T extends DurableIteratorObject<any>,
RPC extends InferDurableIteratorObjectRPC<T> = never,
> implements PromiseLike<ClientDurableIterator<T, RPC>> {
constructor(
private readonly chn: string,
private readonly options: DurableIteratorOptions<T, RPC>,
) {
}
/**
* List of methods that are allowed to be called remotely.
*/
rpc<U extends InferDurableIteratorObjectRPC<T>>(...rpc: U[]): Omit<DurableIterator<T, U>, 'rpc'> {
return new DurableIterator<T, U>(this.chn, {
...this.options,
rpc,
})
}
then<TResult1 = ClientDurableIterator<T, RPC>, TResult2 = never>(
onfulfilled?: ((value: ClientDurableIterator<T, RPC>) => TResult1 | PromiseLike<TResult1>) | null | undefined,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined,
): PromiseLike<TResult1 | TResult2> {
return (async () => {
const tokenTTLSeconds = this.options.tokenTTLSeconds ?? 60 * 60 * 24 // 24 hours
const nowInSeconds = Math.floor(Date.now() / 1000)
const token = await signDurableIteratorToken(this.options.signingKey, {
chn: this.chn,
tags: this.options.tags,
att: this.options.att,
rpc: this.options.rpc,
iat: nowInSeconds,
exp: nowInSeconds + tokenTTLSeconds,
})
const iterator = new AsyncIteratorClass<any>(
() => Promise.reject(new DurableIteratorError('Cannot be iterated directly.')),
() => Promise.reject(new DurableIteratorError('Cannot be cleaned up directly.')),
)
const link: ClientLink<object> = {
call() {
throw new DurableIteratorError('Cannot call methods directly.')
},
}
const durableIterator = createClientDurableIterator(iterator, link, {
getToken: () => token,
})
return durableIterator as ClientDurableIterator<T, RPC>
})().then(onfulfilled, onrejected)
}
}