@nxtedition/deepstream.io-client-js 32.0.21 → 32.0.22
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/package.json +1 -1
- package/src/client.d.ts +5 -59
- package/src/client.test-d.ts +2 -96
- package/src/event/event-handler.d.ts +2 -11
- package/src/event/event-handler.js +4 -4
- package/src/record/record-handler.d.ts +21 -117
- package/src/record/record.d.ts +36 -25
- package/src/rpc/rpc-handler.d.ts +4 -7
- package/src/rpc/rpc-response.d.ts +0 -1
- package/src/utils/utils.js +8 -0
- package/src/rpc/rpc-handler.test-d.ts +0 -40
- package/src/utils/multicast-listener.js +0 -252
package/package.json
CHANGED
package/src/client.d.ts
CHANGED
|
@@ -3,25 +3,14 @@ import type { Paths, Get } from './record/record.js'
|
|
|
3
3
|
import type RecordHandler from './record/record-handler.js'
|
|
4
4
|
import type { RecordStats, ProvideOptions, SyncOptions } from './record/record-handler.js'
|
|
5
5
|
import type EventHandler from './event/event-handler.js'
|
|
6
|
-
import type { EventStats
|
|
6
|
+
import type { EventStats } from './event/event-handler.js'
|
|
7
7
|
import type RpcHandler from './rpc/rpc-handler.js'
|
|
8
8
|
import type { RpcStats, RpcMethodDef } from './rpc/rpc-handler.js'
|
|
9
9
|
|
|
10
|
-
export interface DeepstreamClientOptions {
|
|
11
|
-
reconnectIntervalIncrement?: number
|
|
12
|
-
maxReconnectInterval?: number
|
|
13
|
-
maxReconnectAttempts?: number
|
|
14
|
-
maxPacketSize?: number
|
|
15
|
-
batchSize?: number
|
|
16
|
-
schedule?: ((fn: () => void) => void) | null
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
-
logger?: any
|
|
19
|
-
}
|
|
20
|
-
|
|
21
10
|
export default function <
|
|
22
11
|
Records extends Record<string, unknown> = Record<string, unknown>,
|
|
23
12
|
Methods extends Record<string, RpcMethodDef> = Record<string, RpcMethodDef>,
|
|
24
|
-
>(url: string, options?:
|
|
13
|
+
>(url: string, options?: unknown): DeepstreamClient<Records, Methods>
|
|
25
14
|
|
|
26
15
|
export type {
|
|
27
16
|
DsRecord,
|
|
@@ -30,12 +19,9 @@ export type {
|
|
|
30
19
|
RpcHandler,
|
|
31
20
|
RpcMethodDef,
|
|
32
21
|
ProvideOptions,
|
|
33
|
-
EventProvideOptions,
|
|
34
22
|
SyncOptions,
|
|
35
23
|
Paths,
|
|
36
24
|
Get,
|
|
37
|
-
ConnectionStateName,
|
|
38
|
-
DeepstreamErrorEventName,
|
|
39
25
|
}
|
|
40
26
|
|
|
41
27
|
type RecordStateConstants = Readonly<{
|
|
@@ -91,36 +77,6 @@ type EventConstants = Readonly<{
|
|
|
91
77
|
}>
|
|
92
78
|
type EventKey = keyof EventConstants
|
|
93
79
|
type EventName = EventConstants[EventKey]
|
|
94
|
-
type DeepstreamErrorEventName = Exclude<
|
|
95
|
-
EventName,
|
|
96
|
-
'connectionStateChanged' | 'connected' | 'MAX_RECONNECTION_ATTEMPTS_REACHED'
|
|
97
|
-
>
|
|
98
|
-
|
|
99
|
-
export interface DeepstreamError extends Error {
|
|
100
|
-
topic?: string
|
|
101
|
-
event?: EventName | null
|
|
102
|
-
data?: unknown
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface DeepstreamMessage {
|
|
106
|
-
raw: string | null
|
|
107
|
-
topic: string | null
|
|
108
|
-
action: string | null
|
|
109
|
-
data: string[]
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export interface DeepstreamClientEventMap {
|
|
113
|
-
connectionStateChanged: (state: ConnectionStateName) => void
|
|
114
|
-
connected: (connected: boolean) => void
|
|
115
|
-
MAX_RECONNECTION_ATTEMPTS_REACHED: (attempt: number) => void
|
|
116
|
-
error: (error: DeepstreamError) => void
|
|
117
|
-
recv: (message: DeepstreamMessage) => void
|
|
118
|
-
send: (message: DeepstreamMessage) => void
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
type DeepstreamErrorEventMap = {
|
|
122
|
-
[K in DeepstreamErrorEventName]: (error: DeepstreamError) => void
|
|
123
|
-
}
|
|
124
80
|
|
|
125
81
|
export interface DeepstreamClient<
|
|
126
82
|
Records extends Record<string, unknown> = Record<string, unknown>,
|
|
@@ -131,21 +87,11 @@ export interface DeepstreamClient<
|
|
|
131
87
|
rpc: RpcHandler<Methods>
|
|
132
88
|
record: RecordHandler<Records>
|
|
133
89
|
user: string | null
|
|
134
|
-
on
|
|
135
|
-
|
|
136
|
-
callback: (DeepstreamClientEventMap & DeepstreamErrorEventMap)[K],
|
|
137
|
-
): this
|
|
138
|
-
off<K extends keyof (DeepstreamClientEventMap & DeepstreamErrorEventMap)>(
|
|
139
|
-
evt: K,
|
|
140
|
-
callback: (DeepstreamClientEventMap & DeepstreamErrorEventMap)[K],
|
|
141
|
-
): this
|
|
90
|
+
on: (evt: EventName, callback: (...args: unknown[]) => void) => void
|
|
91
|
+
off: (evt: EventName, callback: (...args: unknown[]) => void) => void
|
|
142
92
|
getConnectionState: () => ConnectionStateName
|
|
143
93
|
close: () => void
|
|
144
|
-
login
|
|
145
|
-
login(
|
|
146
|
-
authParams: Record<string, unknown>,
|
|
147
|
-
callback: (success: boolean, authData: unknown) => void,
|
|
148
|
-
): this
|
|
94
|
+
login: unknown
|
|
149
95
|
stats: {
|
|
150
96
|
record: RecordStats
|
|
151
97
|
rpc: RpcStats
|
package/src/client.test-d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import make, { type DeepstreamClient
|
|
2
|
+
import make, { type DeepstreamClient } from './client.js'
|
|
3
3
|
import { expectAssignable, expectError, expectType } from 'tsd'
|
|
4
4
|
import type { Observable } from 'rxjs'
|
|
5
|
-
import type { EmptyObject } from 'type-fest'
|
|
6
5
|
|
|
7
6
|
interface Records extends Record<string, unknown> {
|
|
8
7
|
o: {
|
|
@@ -23,11 +22,6 @@ interface Records extends Record<string, unknown> {
|
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
|
-
possiblyEmpty:
|
|
27
|
-
| {
|
|
28
|
-
pe1: string
|
|
29
|
-
}
|
|
30
|
-
| EmptyObject
|
|
31
25
|
c: Circular
|
|
32
26
|
m: {
|
|
33
27
|
m1: string
|
|
@@ -68,7 +62,7 @@ expectAssignable<{ n0?: { n1: { n2: { n3: string } } } } | undefined>(await ds.r
|
|
|
68
62
|
expectAssignable<{ n1: { n2: { n3: string } } } | undefined>(await ds.record.get('n', 'n0'))
|
|
69
63
|
|
|
70
64
|
// set withouth path
|
|
71
|
-
ds.record.set('
|
|
65
|
+
ds.record.set('n', {}) // empty should always work
|
|
72
66
|
ds.record.set('n', { n0: { n1: { n2: { n3: 'test' } } } })
|
|
73
67
|
expectError(ds.record.set('n', { n0: {} })) // nested props are required
|
|
74
68
|
|
|
@@ -102,14 +96,10 @@ expectError(ds.record.set('n', 'n1.x2', {}))
|
|
|
102
96
|
expectError(ds.record.set('n', 'n1.n2.n3', { n4: 22 }))
|
|
103
97
|
|
|
104
98
|
expectAssignable<string>(await ds.record.get('p', 'p1'))
|
|
105
|
-
expectAssignable<{ name: string; version: string; state: number; data: string }>(
|
|
106
|
-
await ds.record.get2('p', 'p1'),
|
|
107
|
-
)
|
|
108
99
|
expectAssignable<string>(await ds.record.get('p', 'p1', { signal: new AbortController().signal }))
|
|
109
100
|
expectAssignable<string>(await ds.record.get('p', { path: 'p1' }))
|
|
110
101
|
expectAssignable<string | undefined>(await ds.record.get('p', 'p2'))
|
|
111
102
|
expectAssignable<unknown>(await ds.record.get('p', 'x1'))
|
|
112
|
-
expectAssignable<string | undefined>(await ds.record.get('possiblyEmpty', 'pe1'))
|
|
113
103
|
|
|
114
104
|
// observe with options
|
|
115
105
|
expectAssignable<Observable<{ p1: string; p2?: string; p3: { p4: string } }>>(
|
|
@@ -189,16 +179,6 @@ expectAssignable<Promise<void>>(
|
|
|
189
179
|
)
|
|
190
180
|
expectAssignable<Promise<void>>(ds.record.update('p', 'p1', (data) => data, { timeout: 5000 }))
|
|
191
181
|
|
|
192
|
-
// update: updater receives version as second argument
|
|
193
|
-
ds.record.update('p', (data, version) => {
|
|
194
|
-
expectType<string>(version)
|
|
195
|
-
return data
|
|
196
|
-
})
|
|
197
|
-
ds.record.update('p', 'p1', (data, version) => {
|
|
198
|
-
expectType<string>(version)
|
|
199
|
-
return data
|
|
200
|
-
})
|
|
201
|
-
|
|
202
182
|
// Circular
|
|
203
183
|
expectAssignable<string | undefined>(await ds.record.get('c', 'a.b1'))
|
|
204
184
|
|
|
@@ -230,19 +210,6 @@ expectAssignable<Promise<typeof rec>>(rec.when({ state: 2, timeout: 5000 }))
|
|
|
230
210
|
expectAssignable<Promise<typeof rec>>(rec.when(2, { timeout: 5000 }))
|
|
231
211
|
expectAssignable<Promise<typeof rec>>(rec.when(2, { signal: new AbortController().signal }))
|
|
232
212
|
|
|
233
|
-
// Record.subscribe: callback receives (record, opaque)
|
|
234
|
-
rec.subscribe((record, opaque) => {
|
|
235
|
-
expectType<typeof rec>(record)
|
|
236
|
-
expectType<unknown>(opaque)
|
|
237
|
-
})
|
|
238
|
-
rec.subscribe((record, opaque) => {}, 'my-opaque-token')
|
|
239
|
-
|
|
240
|
-
// Record.unsubscribe: same callback signature
|
|
241
|
-
rec.unsubscribe((record, opaque) => {
|
|
242
|
-
expectType<typeof rec>(record)
|
|
243
|
-
expectType<unknown>(opaque)
|
|
244
|
-
})
|
|
245
|
-
|
|
246
213
|
// Record.update with options
|
|
247
214
|
expectAssignable<Promise<void>>(rec.update((x) => x, { signal: new AbortController().signal }))
|
|
248
215
|
expectAssignable<Promise<void>>(rec.update((x) => x, { timeout: 5000 }))
|
|
@@ -253,68 +220,7 @@ expectAssignable<Promise<void>>(
|
|
|
253
220
|
expectAssignable<Promise<void>>(rec.update('o0', (x) => x, { timeout: 5000 }))
|
|
254
221
|
expectAssignable<Promise<void>>(rec.update('o0', (x) => x, { state: 2 }))
|
|
255
222
|
|
|
256
|
-
// Record.update: updater receives version as second argument
|
|
257
|
-
rec.update((x, version) => {
|
|
258
|
-
expectType<string>(version)
|
|
259
|
-
return x
|
|
260
|
-
})
|
|
261
|
-
rec.update('o0', (x, version) => {
|
|
262
|
-
expectType<string>(version)
|
|
263
|
-
return x
|
|
264
|
-
})
|
|
265
|
-
|
|
266
223
|
const state = 'VOID'
|
|
267
224
|
expectType<0>(ds.record.STATE[state])
|
|
268
225
|
const unknownState: string = 'VOID'
|
|
269
226
|
expectType<number>(ds.record.STATE[unknownState])
|
|
270
|
-
|
|
271
|
-
// record.getRecord: [Symbol.dispose] is present
|
|
272
|
-
const recDispose = ds.record.getRecord('o')
|
|
273
|
-
recDispose[Symbol.dispose]()
|
|
274
|
-
|
|
275
|
-
// record.provide: returns Disposer | void
|
|
276
|
-
expectAssignable<(() => void) | void>(ds.record.provide('pattern*', () => ({})))
|
|
277
|
-
const recordDisposer = ds.record.provide('pattern*', () => ({}))
|
|
278
|
-
if (recordDisposer) {
|
|
279
|
-
recordDisposer()
|
|
280
|
-
recordDisposer[Symbol.dispose]()
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// event.provide: returns (() => void) | void
|
|
284
|
-
expectAssignable<(() => void) | void>(ds.event.provide('pattern*', () => {}, {}))
|
|
285
|
-
|
|
286
|
-
// client.on/off: 'error' is a valid event name
|
|
287
|
-
ds.on('error', (err) => {})
|
|
288
|
-
ds.off('error', (err) => {})
|
|
289
|
-
expectError(ds.on('unknownEvent', () => {}))
|
|
290
|
-
|
|
291
|
-
// client.on: callback arg types per event
|
|
292
|
-
ds.on('error', (err) => {
|
|
293
|
-
expectType<DeepstreamError>(err)
|
|
294
|
-
})
|
|
295
|
-
ds.on('connectionError', (err) => {
|
|
296
|
-
expectType<DeepstreamError>(err)
|
|
297
|
-
})
|
|
298
|
-
ds.on('connectionStateChanged', (state) => {
|
|
299
|
-
expectType<
|
|
300
|
-
| 'CLOSED'
|
|
301
|
-
| 'AWAITING_CONNECTION'
|
|
302
|
-
| 'CHALLENGING'
|
|
303
|
-
| 'AWAITING_AUTHENTICATION'
|
|
304
|
-
| 'AUTHENTICATING'
|
|
305
|
-
| 'OPEN'
|
|
306
|
-
| 'ERROR'
|
|
307
|
-
| 'RECONNECTING'
|
|
308
|
-
>(state)
|
|
309
|
-
})
|
|
310
|
-
ds.on('connected', (connected) => {
|
|
311
|
-
expectType<boolean>(connected)
|
|
312
|
-
})
|
|
313
|
-
ds.on('MAX_RECONNECTION_ATTEMPTS_REACHED', (attempt) => {
|
|
314
|
-
expectType<number>(attempt)
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
// client.on: wrong callback arg types are errors
|
|
318
|
-
expectError(ds.on('connectionStateChanged', (state: number) => {}))
|
|
319
|
-
expectError(ds.on('connected', (connected: string) => {}))
|
|
320
|
-
expectError(ds.on('MAX_RECONNECTION_ATTEMPTS_REACHED', (attempt: string) => {}))
|
|
@@ -4,22 +4,13 @@ export default class EventHandler {
|
|
|
4
4
|
connected: boolean
|
|
5
5
|
stats: EventStats
|
|
6
6
|
subscribe: (name: string, callback: (data: unknown) => void) => void
|
|
7
|
-
unsubscribe: (name: string, callback
|
|
7
|
+
unsubscribe: (name: string, callback: (data: unknown) => void) => void
|
|
8
8
|
on: (name: string, callback: (data: unknown) => void) => this
|
|
9
9
|
once: (name: string, callback: (data: unknown) => void) => this
|
|
10
10
|
off: (name: string, callback: (data: unknown) => void) => this
|
|
11
11
|
observe: <Data>(name: string) => Observable<Data>
|
|
12
12
|
emit: <Data>(name: string, data?: Data) => void
|
|
13
|
-
provide: (
|
|
14
|
-
pattern: string,
|
|
15
|
-
callback: (name: string) => void,
|
|
16
|
-
options: EventProvideOptions,
|
|
17
|
-
) => (() => void) | void
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface EventProvideOptions {
|
|
21
|
-
mode?: 'unicast' | (string & {})
|
|
22
|
-
stringify?: ((input: unknown) => string) | null
|
|
13
|
+
provide: (pattern: string, callback: (name: string) => void, options: unknown) => () => void
|
|
23
14
|
}
|
|
24
15
|
|
|
25
16
|
export interface EventStats {
|
|
@@ -71,21 +71,21 @@ EventHandler.prototype.unsubscribe = function (name, callback) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
EventHandler.
|
|
74
|
+
EventHandler.on = function (name, callback) {
|
|
75
75
|
this.subscribe(name, callback)
|
|
76
76
|
return this
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
EventHandler.
|
|
79
|
+
EventHandler.once = function (name, callback) {
|
|
80
80
|
const fn = (...args) => {
|
|
81
|
-
this.unsubscribe(
|
|
81
|
+
this.unsubscribe(fn)
|
|
82
82
|
callback(...args)
|
|
83
83
|
}
|
|
84
84
|
this.subscribe(name, fn)
|
|
85
85
|
return this
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
EventHandler.
|
|
88
|
+
EventHandler.off = function (name, callback) {
|
|
89
89
|
this.unsubscribe(name, callback)
|
|
90
90
|
return this
|
|
91
91
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { Observable } from 'rxjs'
|
|
2
2
|
import type DsRecord from './record.js'
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
EmptyObject,
|
|
5
|
+
Get,
|
|
6
|
+
UpdateOptions,
|
|
7
|
+
ObserveOptions,
|
|
8
|
+
ObserveOptionsWithPath,
|
|
9
|
+
} from './record.js'
|
|
4
10
|
|
|
5
11
|
type Lookup<Table, Name> = Name extends keyof Table ? Table[Name] : unknown
|
|
6
12
|
|
|
@@ -26,8 +32,8 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
JSON: {
|
|
29
|
-
EMPTY:
|
|
30
|
-
EMPTY_OBJ:
|
|
35
|
+
EMPTY: EmptyObject
|
|
36
|
+
EMPTY_OBJ: EmptyObject
|
|
31
37
|
EMPTY_ARR: []
|
|
32
38
|
}
|
|
33
39
|
|
|
@@ -40,44 +46,13 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
40
46
|
pattern: string,
|
|
41
47
|
callback: (key: string) => unknown,
|
|
42
48
|
optionsOrRecursive?: ProvideOptions | boolean,
|
|
43
|
-
) => Disposer
|
|
44
|
-
|
|
45
|
-
put: (
|
|
46
|
-
name: string,
|
|
47
|
-
version: string,
|
|
48
|
-
data: Record<string, unknown> | null,
|
|
49
|
-
parent?: string,
|
|
50
|
-
) => void
|
|
51
|
-
|
|
52
|
-
getAsync: {
|
|
53
|
-
<Name extends string>(
|
|
54
|
-
name: Name,
|
|
55
|
-
options: ObserveOptions,
|
|
56
|
-
):
|
|
57
|
-
| { value: Lookup<Records, Name>; async: false }
|
|
58
|
-
| { value: Promise<Lookup<Records, Name>>; async: true }
|
|
59
|
-
|
|
60
|
-
<Name extends string, Path extends string | string[]>(
|
|
61
|
-
name: Name,
|
|
62
|
-
path: Path,
|
|
63
|
-
options?: ObserveOptions,
|
|
64
|
-
):
|
|
65
|
-
| { value: Get<Lookup<Records, Name>, Path>; async: false }
|
|
66
|
-
| { value: Promise<Get<Lookup<Records, Name>, Path>>; async: true }
|
|
67
|
-
|
|
68
|
-
<Name extends string>(
|
|
69
|
-
name: Name,
|
|
70
|
-
state?: number,
|
|
71
|
-
):
|
|
72
|
-
| { value: Lookup<Records, Name>; async: false }
|
|
73
|
-
| { value: Promise<Lookup<Records, Name>>; async: true }
|
|
74
|
-
}
|
|
49
|
+
) => Disposer
|
|
75
50
|
|
|
76
51
|
sync: (options?: SyncOptions) => Promise<void>
|
|
77
52
|
|
|
78
53
|
set: {
|
|
79
54
|
// without path:
|
|
80
|
-
<Name extends string>(name: Name, data: Lookup<Records, Name>): void
|
|
55
|
+
<Name extends string>(name: Name, data: Lookup<Records, Name> | EmptyObject): void
|
|
81
56
|
|
|
82
57
|
// with path:
|
|
83
58
|
<Name extends string, Path extends string | string[]>(
|
|
@@ -92,17 +67,14 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
92
67
|
update: {
|
|
93
68
|
<Name extends string>(
|
|
94
69
|
name: Name,
|
|
95
|
-
updater: (data: Lookup<Records, Name
|
|
70
|
+
updater: (data: Lookup<Records, Name>) => Lookup<Records, Name> | EmptyObject,
|
|
96
71
|
options?: UpdateOptions,
|
|
97
72
|
): Promise<void>
|
|
98
73
|
|
|
99
74
|
<Name extends string, Path extends string | string[]>(
|
|
100
75
|
name: Name,
|
|
101
76
|
path: Path,
|
|
102
|
-
updater: (
|
|
103
|
-
data: Get<Lookup<Records, Name>, Path>,
|
|
104
|
-
version: string,
|
|
105
|
-
) => Get<Lookup<Records, Name>, Path>,
|
|
77
|
+
updater: (data: Get<Lookup<Records, Name>, Path>) => Get<Lookup<Records, Name>, Path>,
|
|
106
78
|
options?: UpdateOptions,
|
|
107
79
|
): Promise<void>
|
|
108
80
|
}
|
|
@@ -141,73 +113,6 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
141
113
|
): Observable<Get<Lookup<Records, Name>, Path>>
|
|
142
114
|
}
|
|
143
115
|
|
|
144
|
-
observe2: {
|
|
145
|
-
<Name extends string>(
|
|
146
|
-
name: Name,
|
|
147
|
-
options: ObserveOptions,
|
|
148
|
-
): Observable<{
|
|
149
|
-
name: string
|
|
150
|
-
version: string
|
|
151
|
-
state: number
|
|
152
|
-
data: Lookup<Records, Name>
|
|
153
|
-
}>
|
|
154
|
-
|
|
155
|
-
<Name extends string, Path extends string | string[]>(
|
|
156
|
-
name: Name,
|
|
157
|
-
options: ObserveOptionsWithPath<Path>,
|
|
158
|
-
): Observable<{
|
|
159
|
-
name: string
|
|
160
|
-
version: string
|
|
161
|
-
state: number
|
|
162
|
-
data: Get<Lookup<Records, Name>, Path>
|
|
163
|
-
}>
|
|
164
|
-
|
|
165
|
-
<Name extends string>(
|
|
166
|
-
name: Name,
|
|
167
|
-
state?: number,
|
|
168
|
-
options?: ObserveOptions,
|
|
169
|
-
): Observable<{
|
|
170
|
-
name: string
|
|
171
|
-
version: string
|
|
172
|
-
state: number
|
|
173
|
-
data: Lookup<Records, Name>
|
|
174
|
-
}>
|
|
175
|
-
|
|
176
|
-
<Name extends string, Path extends string | string[]>(
|
|
177
|
-
name: Name,
|
|
178
|
-
state?: number,
|
|
179
|
-
options?: ObserveOptionsWithPath<Path>,
|
|
180
|
-
): Observable<{
|
|
181
|
-
name: string
|
|
182
|
-
version: string
|
|
183
|
-
state: number
|
|
184
|
-
data: Get<Lookup<Records, Name>, Path>
|
|
185
|
-
}>
|
|
186
|
-
|
|
187
|
-
<Name extends string, Path extends string | string[]>(
|
|
188
|
-
name: Name,
|
|
189
|
-
path: Path,
|
|
190
|
-
options?: ObserveOptionsWithPath<Path>,
|
|
191
|
-
): Observable<{
|
|
192
|
-
name: string
|
|
193
|
-
version: string
|
|
194
|
-
state: number
|
|
195
|
-
data: Get<Lookup<Records, Name>, Path>
|
|
196
|
-
}>
|
|
197
|
-
|
|
198
|
-
<Name extends string, Path extends string | string[]>(
|
|
199
|
-
name: Name,
|
|
200
|
-
path: Path,
|
|
201
|
-
state?: number,
|
|
202
|
-
options?: ObserveOptionsWithPath<Path>,
|
|
203
|
-
): Observable<{
|
|
204
|
-
name: string
|
|
205
|
-
version: string
|
|
206
|
-
state: number
|
|
207
|
-
data: Get<Lookup<Records, Name>, Path>
|
|
208
|
-
}>
|
|
209
|
-
}
|
|
210
|
-
|
|
211
116
|
get: {
|
|
212
117
|
<Name extends string>(name: Name, options: ObserveOptions): Promise<Lookup<Records, Name>>
|
|
213
118
|
|
|
@@ -242,11 +147,11 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
242
147
|
): Promise<Get<Lookup<Records, Name>, Path>>
|
|
243
148
|
}
|
|
244
149
|
|
|
245
|
-
|
|
150
|
+
observe2: {
|
|
246
151
|
<Name extends string>(
|
|
247
152
|
name: Name,
|
|
248
153
|
options: ObserveOptions,
|
|
249
|
-
):
|
|
154
|
+
): Observable<{
|
|
250
155
|
name: string
|
|
251
156
|
version: string
|
|
252
157
|
state: number
|
|
@@ -256,7 +161,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
256
161
|
<Name extends string, Path extends string | string[]>(
|
|
257
162
|
name: Name,
|
|
258
163
|
options: ObserveOptionsWithPath<Path>,
|
|
259
|
-
):
|
|
164
|
+
): Observable<{
|
|
260
165
|
name: string
|
|
261
166
|
version: string
|
|
262
167
|
state: number
|
|
@@ -267,7 +172,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
267
172
|
name: Name,
|
|
268
173
|
state?: number,
|
|
269
174
|
options?: ObserveOptions,
|
|
270
|
-
):
|
|
175
|
+
): Observable<{
|
|
271
176
|
name: string
|
|
272
177
|
version: string
|
|
273
178
|
state: number
|
|
@@ -278,7 +183,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
278
183
|
name: Name,
|
|
279
184
|
state?: number,
|
|
280
185
|
options?: ObserveOptionsWithPath<Path>,
|
|
281
|
-
):
|
|
186
|
+
): Observable<{
|
|
282
187
|
name: string
|
|
283
188
|
version: string
|
|
284
189
|
state: number
|
|
@@ -289,7 +194,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
289
194
|
name: Name,
|
|
290
195
|
path: Path,
|
|
291
196
|
options?: ObserveOptionsWithPath<Path>,
|
|
292
|
-
):
|
|
197
|
+
): Observable<{
|
|
293
198
|
name: string
|
|
294
199
|
version: string
|
|
295
200
|
state: number
|
|
@@ -301,7 +206,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
|
|
|
301
206
|
path: Path,
|
|
302
207
|
state?: number,
|
|
303
208
|
options?: ObserveOptionsWithPath<Path>,
|
|
304
|
-
):
|
|
209
|
+
): Observable<{
|
|
305
210
|
name: string
|
|
306
211
|
version: string
|
|
307
212
|
state: number
|
|
@@ -318,13 +223,12 @@ export interface RecordStats {
|
|
|
318
223
|
pruning: number
|
|
319
224
|
patching: number
|
|
320
225
|
subscriptions: number
|
|
321
|
-
listeners: number
|
|
322
226
|
}
|
|
323
227
|
|
|
324
228
|
export interface ProvideOptions {
|
|
325
229
|
recursive?: boolean
|
|
326
230
|
stringify?: ((input: unknown) => string) | null
|
|
327
|
-
mode
|
|
231
|
+
mode: undefined | null | 'unicast'
|
|
328
232
|
}
|
|
329
233
|
|
|
330
234
|
export interface SyncOptions {
|
package/src/record/record.d.ts
CHANGED
|
@@ -1,15 +1,36 @@
|
|
|
1
1
|
import type RecordHandler from './record-handler.js'
|
|
2
|
-
import type { Get
|
|
3
|
-
export type { Paths } from 'type-fest'
|
|
2
|
+
import type { Get, EmptyObject, SingleKeyObject } from 'type-fest'
|
|
3
|
+
export type { Get, Paths, EmptyObject } from 'type-fest'
|
|
4
4
|
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
// When getting, for convenience, we say the data might be partial under some
|
|
6
|
+
// circumstances.
|
|
7
|
+
//
|
|
8
|
+
// When you e.g. do record.get or record.update, there is always a possibility
|
|
9
|
+
// that the data object is empty. The naive correct type for that would be
|
|
10
|
+
// `Data | EmptyObject`. However, that forces the user to always type guard
|
|
11
|
+
// against the empty object case. This type tries to allow the user to skip
|
|
12
|
+
// that check in some cases, where it should be safe to do so.
|
|
13
|
+
export type GettablePossibleEmpty<Data> = keyof Data extends never
|
|
14
|
+
? EmptyObject // If there are no keys at all
|
|
15
|
+
: Partial<Data> extends Data
|
|
16
|
+
? // All properties in Data are already optional, so we can safely return it
|
|
17
|
+
// as is. The user just need to check the properties themselves instead.
|
|
18
|
+
Data
|
|
19
|
+
: SingleKeyObject<Data> extends never
|
|
20
|
+
? // There are more than one property in Data, and some of them are
|
|
21
|
+
// required. That means that the user must always check for the empty
|
|
22
|
+
// object case.
|
|
23
|
+
Data | EmptyObject
|
|
24
|
+
: // There is exactly one property in Data, and it is required. In this
|
|
25
|
+
// particular case, we can safely use Data as the "empty" type, but
|
|
26
|
+
// with the single property turned optional.
|
|
27
|
+
{
|
|
28
|
+
[K in keyof Data]+?: Data[K]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// When setting the data must fully adhere to the Data type, or exactly an
|
|
32
|
+
// empty object.
|
|
33
|
+
export type SettablePossibleEmpty<Data> = Data | EmptyObject
|
|
13
34
|
|
|
14
35
|
export interface WhenOptions {
|
|
15
36
|
signal?: AbortSignal
|
|
@@ -24,7 +45,6 @@ export interface UpdateOptions {
|
|
|
24
45
|
}
|
|
25
46
|
|
|
26
47
|
export interface ObserveOptions {
|
|
27
|
-
key?: string
|
|
28
48
|
signal?: AbortSignal
|
|
29
49
|
timeout?: number
|
|
30
50
|
state?: number
|
|
@@ -47,21 +67,12 @@ export default class Record<Data = unknown> {
|
|
|
47
67
|
|
|
48
68
|
ref(): Record<Data>
|
|
49
69
|
unref(): Record<Data>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
callback: (record: Record<Data>, opaque: unknown) => void,
|
|
53
|
-
opaque?: unknown,
|
|
54
|
-
): Record<Data>
|
|
55
|
-
unsubscribe(
|
|
56
|
-
callback: (record: Record<Data>, opaque: unknown) => void,
|
|
57
|
-
opaque?: unknown,
|
|
58
|
-
): Record<Data>
|
|
70
|
+
subscribe(callback: (record: Record<Data>) => void, opaque?: unknown): Record<Data>
|
|
71
|
+
unsubscribe(callback: (record: Record<Data>) => void, opaque?: unknown): Record<Data>
|
|
59
72
|
|
|
60
73
|
get: {
|
|
61
74
|
// with path
|
|
62
75
|
<P extends string | string[]>(path: P): Get<Data, P>
|
|
63
|
-
// with function mapper
|
|
64
|
-
<R>(fn: (data: Data) => R): R
|
|
65
76
|
// without path
|
|
66
77
|
(): Data
|
|
67
78
|
(path: undefined | string | string[]): unknown
|
|
@@ -74,7 +85,7 @@ export default class Record<Data = unknown> {
|
|
|
74
85
|
dataAtPath: unknown extends Get<Data, P> ? never : Get<Data, P>,
|
|
75
86
|
): void
|
|
76
87
|
// without path
|
|
77
|
-
(data: Data): void
|
|
88
|
+
(data: SettablePossibleEmpty<Data>): void
|
|
78
89
|
}
|
|
79
90
|
|
|
80
91
|
when: {
|
|
@@ -86,13 +97,13 @@ export default class Record<Data = unknown> {
|
|
|
86
97
|
update: {
|
|
87
98
|
// without path
|
|
88
99
|
(
|
|
89
|
-
updater: (data: Readonly<Data
|
|
100
|
+
updater: (data: Readonly<Data>) => SettablePossibleEmpty<Data>,
|
|
90
101
|
options?: UpdateOptions,
|
|
91
102
|
): Promise<void>
|
|
92
103
|
// with path
|
|
93
104
|
<P extends string | string[]>(
|
|
94
105
|
path: P,
|
|
95
|
-
updater: (dataAtPath: Readonly<Get<Data, P
|
|
106
|
+
updater: (dataAtPath: Readonly<Get<Data, P>>) => Get<Data, P>,
|
|
96
107
|
options?: UpdateOptions,
|
|
97
108
|
): Promise<void>
|
|
98
109
|
}
|
package/src/rpc/rpc-handler.d.ts
CHANGED
|
@@ -10,11 +10,8 @@ export default class RpcHandler<
|
|
|
10
10
|
|
|
11
11
|
provide: <Name extends keyof Methods>(
|
|
12
12
|
name: Name,
|
|
13
|
-
callback: (
|
|
14
|
-
|
|
15
|
-
response: RpcResponse<Methods[Name][1]>,
|
|
16
|
-
) => Methods[Name][1] | Promise<Methods[Name][1]> | Promise<void> | void,
|
|
17
|
-
) => UnprovideFn | void
|
|
13
|
+
callback: (args: Methods[Name][0], response: RpcResponse<Methods[Name][1]>) => void,
|
|
14
|
+
) => UnprovideFn
|
|
18
15
|
|
|
19
16
|
unprovide: <Name extends keyof Methods>(name: Name) => void
|
|
20
17
|
|
|
@@ -25,7 +22,7 @@ export default class RpcHandler<
|
|
|
25
22
|
ReturnValue extends Name extends keyof Methods ? Methods[Name][1] : unknown,
|
|
26
23
|
>(
|
|
27
24
|
name: Name,
|
|
28
|
-
args
|
|
25
|
+
args: Args,
|
|
29
26
|
): Promise<ReturnValue>
|
|
30
27
|
<
|
|
31
28
|
Name extends keyof Methods | string,
|
|
@@ -33,7 +30,7 @@ export default class RpcHandler<
|
|
|
33
30
|
ReturnValue extends Name extends keyof Methods ? Methods[Name][1] : unknown,
|
|
34
31
|
>(
|
|
35
32
|
name: Name,
|
|
36
|
-
args: Args
|
|
33
|
+
args: Args,
|
|
37
34
|
callback: (error: unknown, response: ReturnValue) => void,
|
|
38
35
|
): void
|
|
39
36
|
}
|
package/src/utils/utils.js
CHANGED
|
@@ -83,6 +83,14 @@ export function setTimeout(callback, timeoutDuration) {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
export function setInterval(callback, intervalDuration) {
|
|
87
|
+
if (intervalDuration !== null) {
|
|
88
|
+
return setInterval(callback, intervalDuration)
|
|
89
|
+
} else {
|
|
90
|
+
return -1
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
86
94
|
export function compareRev(a, b) {
|
|
87
95
|
if (!a) {
|
|
88
96
|
return b ? -1 : 0
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import make from '../client.js'
|
|
2
|
-
import { expectAssignable, expectError, expectType } from 'tsd'
|
|
3
|
-
|
|
4
|
-
interface Methods extends Record<string, [unknown, unknown]> {
|
|
5
|
-
greet: [{ name: string }, { message: string }]
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const ds = make<Record<string, unknown>, Methods>('')
|
|
9
|
-
|
|
10
|
-
// provide: callback may return void, a value, or a Promise — all valid
|
|
11
|
-
ds.rpc.provide('greet', (_args, _response) => {})
|
|
12
|
-
ds.rpc.provide('greet', (_args, _response) => ({ message: 'hello' }))
|
|
13
|
-
ds.rpc.provide('greet', async (_args, _response) => ({ message: 'hello' }))
|
|
14
|
-
// async callback that uses response.send() directly — returns Promise<void>
|
|
15
|
-
ds.rpc.provide('greet', async (_args, response) => {
|
|
16
|
-
response.send({ message: 'hello' })
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
// provide: returning the wrong shape is an error
|
|
20
|
-
expectError(ds.rpc.provide('greet', (_args, _response) => ({ notMessage: 'hello' })))
|
|
21
|
-
|
|
22
|
-
// provide: response.completed is boolean
|
|
23
|
-
ds.rpc.provide('greet', (_args, response) => {
|
|
24
|
-
expectType<boolean>(response.completed)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
// provide: return type is UnprovideFn | void
|
|
28
|
-
expectAssignable<(() => void) | void>(ds.rpc.provide('greet', () => {}))
|
|
29
|
-
|
|
30
|
-
// make: args is optional (no args)
|
|
31
|
-
expectAssignable<Promise<{ message: string }>>(ds.rpc.make('greet'))
|
|
32
|
-
// make: args provided
|
|
33
|
-
expectAssignable<Promise<{ message: string }>>(ds.rpc.make('greet', { name: 'world' }))
|
|
34
|
-
// make: args explicitly undefined
|
|
35
|
-
expectAssignable<Promise<{ message: string }>>(ds.rpc.make('greet', undefined))
|
|
36
|
-
// make: callback form — args required positionally but can be undefined
|
|
37
|
-
ds.rpc.make('greet', undefined, (err, res) => {
|
|
38
|
-
expectType<unknown>(err)
|
|
39
|
-
expectAssignable<{ message: string } | undefined>(res)
|
|
40
|
-
})
|
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import * as rxjs from 'rxjs'
|
|
2
|
-
import * as C from '../constants/constants.js'
|
|
3
|
-
import { h64ToString, findBigIntPaths } from '../utils/utils.js'
|
|
4
|
-
|
|
5
|
-
export default class Listener {
|
|
6
|
-
constructor(topic, pattern, callback, handler, { recursive = false, stringify = null } = {}) {
|
|
7
|
-
this._topic = topic
|
|
8
|
-
this._pattern = pattern
|
|
9
|
-
this._callback = callback
|
|
10
|
-
this._handler = handler
|
|
11
|
-
this._client = this._handler._client
|
|
12
|
-
this._connection = this._handler._connection
|
|
13
|
-
this._subscriptions = new Map()
|
|
14
|
-
this._recursive = recursive
|
|
15
|
-
this._stringify = stringify || JSON.stringify
|
|
16
|
-
|
|
17
|
-
this._$onConnectionStateChange()
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get connected() {
|
|
21
|
-
return this._connection.connected
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get stats() {
|
|
25
|
-
return {
|
|
26
|
-
subscriptions: this._subscriptions.size,
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
_$destroy() {
|
|
31
|
-
this._reset()
|
|
32
|
-
|
|
33
|
-
if (this.connected) {
|
|
34
|
-
this._connection.sendMsg(this._topic, C.ACTIONS.UNLISTEN, [this._pattern])
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
_$onMessage(message) {
|
|
39
|
-
if (!this.connected) {
|
|
40
|
-
this._client._$onError(
|
|
41
|
-
C.TOPIC.RECORD,
|
|
42
|
-
C.EVENT.NOT_CONNECTED,
|
|
43
|
-
new Error('received message while not connected'),
|
|
44
|
-
message,
|
|
45
|
-
)
|
|
46
|
-
return
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const name = message.data[1]
|
|
50
|
-
|
|
51
|
-
if (message.action === C.ACTIONS.SUBSCRIPTION_FOR_PATTERN_FOUND) {
|
|
52
|
-
if (this._subscriptions.has(name)) {
|
|
53
|
-
this._error(name, 'invalid add: listener exists')
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// TODO (refactor): Move to class
|
|
58
|
-
const provider = {
|
|
59
|
-
name,
|
|
60
|
-
value$: null,
|
|
61
|
-
sending: false,
|
|
62
|
-
accepted: false,
|
|
63
|
-
version: null,
|
|
64
|
-
timeout: null,
|
|
65
|
-
patternSubscription: null,
|
|
66
|
-
valueSubscription: null,
|
|
67
|
-
}
|
|
68
|
-
provider.stop = () => {
|
|
69
|
-
if (this.connected && provider.accepted) {
|
|
70
|
-
this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [
|
|
71
|
-
this._pattern,
|
|
72
|
-
provider.name,
|
|
73
|
-
])
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
provider.value$ = null
|
|
77
|
-
provider.version = null
|
|
78
|
-
provider.accepted = false
|
|
79
|
-
provider.sending = false
|
|
80
|
-
|
|
81
|
-
clearTimeout(provider.timeout)
|
|
82
|
-
provider.timeout = null
|
|
83
|
-
|
|
84
|
-
provider.patternSubscription?.unsubscribe()
|
|
85
|
-
provider.patternSubscription = null
|
|
86
|
-
|
|
87
|
-
provider.valueSubscription?.unsubscribe()
|
|
88
|
-
provider.valueSubscription = null
|
|
89
|
-
}
|
|
90
|
-
provider.send = () => {
|
|
91
|
-
provider.sending = false
|
|
92
|
-
|
|
93
|
-
if (!provider.patternSubscription) {
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const accepted = Boolean(provider.value$)
|
|
98
|
-
if (provider.accepted === accepted) {
|
|
99
|
-
return
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
this._connection.sendMsg(
|
|
103
|
-
this._topic,
|
|
104
|
-
accepted ? C.ACTIONS.LISTEN_ACCEPT : C.ACTIONS.LISTEN_REJECT,
|
|
105
|
-
[this._pattern, provider.name],
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
provider.version = null
|
|
109
|
-
provider.accepted = accepted
|
|
110
|
-
}
|
|
111
|
-
provider.next = (value$) => {
|
|
112
|
-
if (!value$) {
|
|
113
|
-
value$ = null
|
|
114
|
-
} else if (typeof value$.subscribe !== 'function') {
|
|
115
|
-
value$ = rxjs.of(value$) // Compat for recursive with value
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (Boolean(provider.value$) !== Boolean(value$) && !provider.sending) {
|
|
119
|
-
provider.sending = true
|
|
120
|
-
queueMicrotask(provider.send)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
provider.value$ = value$
|
|
124
|
-
|
|
125
|
-
if (provider.valueSubscription) {
|
|
126
|
-
provider.valueSubscription.unsubscribe()
|
|
127
|
-
provider.valueSubscription = provider.value$?.subscribe(provider.observer)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
provider.error = (err) => {
|
|
131
|
-
provider.stop()
|
|
132
|
-
// TODO (feat): backoff retryCount * delay?
|
|
133
|
-
// TODO (feat): backoff option?
|
|
134
|
-
provider.timeout = setTimeout(() => {
|
|
135
|
-
provider.start()
|
|
136
|
-
}, 10e3)
|
|
137
|
-
this._error(provider.name, err)
|
|
138
|
-
}
|
|
139
|
-
provider.observer = {
|
|
140
|
-
next: (value) => {
|
|
141
|
-
if (value == null) {
|
|
142
|
-
provider.next(null) // TODO (fix): This is weird...
|
|
143
|
-
return
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (this._topic === C.TOPIC.EVENT) {
|
|
147
|
-
this._handler.emit(provider.name, value)
|
|
148
|
-
} else if (this._topic === C.TOPIC.RECORD) {
|
|
149
|
-
if (typeof value !== 'object' && typeof value !== 'string') {
|
|
150
|
-
this._error(provider.name, 'invalid value')
|
|
151
|
-
return
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (typeof value !== 'string') {
|
|
155
|
-
try {
|
|
156
|
-
value = this._stringify(value)
|
|
157
|
-
} catch (err) {
|
|
158
|
-
const bigIntPaths = /BigInt/.test(err.message) ? findBigIntPaths(value) : undefined
|
|
159
|
-
this._error(
|
|
160
|
-
Object.assign(new Error(`invalid value: ${value}`), {
|
|
161
|
-
cause: err,
|
|
162
|
-
data: { name: provider.name, bigIntPaths },
|
|
163
|
-
}),
|
|
164
|
-
)
|
|
165
|
-
return
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const body = value
|
|
170
|
-
const hash = h64ToString(body)
|
|
171
|
-
const version = `INF-${hash}`
|
|
172
|
-
|
|
173
|
-
if (provider.version !== version) {
|
|
174
|
-
provider.version = version
|
|
175
|
-
this._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UPDATE, [
|
|
176
|
-
provider.name,
|
|
177
|
-
version,
|
|
178
|
-
body,
|
|
179
|
-
])
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
error: provider.error,
|
|
184
|
-
}
|
|
185
|
-
provider.start = () => {
|
|
186
|
-
try {
|
|
187
|
-
const ret$ = this._callback(name)
|
|
188
|
-
if (this._recursive && typeof ret$?.subscribe === 'function') {
|
|
189
|
-
provider.patternSubscription = ret$.subscribe(provider)
|
|
190
|
-
} else {
|
|
191
|
-
provider.patternSubscription = rxjs.of(ret$).subscribe(provider)
|
|
192
|
-
}
|
|
193
|
-
} catch (err) {
|
|
194
|
-
this._error(provider.name, err)
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
provider.start()
|
|
199
|
-
|
|
200
|
-
this._subscriptions.set(provider.name, provider)
|
|
201
|
-
} else if (message.action === C.ACTIONS.LISTEN_ACCEPT) {
|
|
202
|
-
const provider = this._subscriptions.get(name)
|
|
203
|
-
if (!provider?.value$) {
|
|
204
|
-
return
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (provider.valueSubscription) {
|
|
208
|
-
this._error(
|
|
209
|
-
name,
|
|
210
|
-
'invalid accept: listener started (pattern:' + this._pattern + ' name:' + name + ')',
|
|
211
|
-
)
|
|
212
|
-
} else {
|
|
213
|
-
// TODO (fix): provider.version = message.data[2]
|
|
214
|
-
provider.valueSubscription = provider.value$.subscribe(provider.observer)
|
|
215
|
-
}
|
|
216
|
-
} else if (message.action === C.ACTIONS.SUBSCRIPTION_FOR_PATTERN_REMOVED) {
|
|
217
|
-
const provider = this._subscriptions.get(name)
|
|
218
|
-
|
|
219
|
-
if (!provider) {
|
|
220
|
-
this._error(
|
|
221
|
-
name,
|
|
222
|
-
'invalid remove: listener missing (pattern:' + this._pattern + ' name:' + name + ')',
|
|
223
|
-
)
|
|
224
|
-
} else {
|
|
225
|
-
provider.stop()
|
|
226
|
-
this._subscriptions.delete(provider.name)
|
|
227
|
-
}
|
|
228
|
-
} else {
|
|
229
|
-
return false
|
|
230
|
-
}
|
|
231
|
-
return true
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
_$onConnectionStateChange() {
|
|
235
|
-
if (this.connected) {
|
|
236
|
-
this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN, [this._pattern])
|
|
237
|
-
} else {
|
|
238
|
-
this._reset()
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
_error(name, err) {
|
|
243
|
-
this._client._$onError(this._topic, C.EVENT.LISTENER_ERROR, err, [this._pattern, name])
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
_reset() {
|
|
247
|
-
for (const provider of this._subscriptions.values()) {
|
|
248
|
-
provider.stop()
|
|
249
|
-
}
|
|
250
|
-
this._subscriptions.clear()
|
|
251
|
-
}
|
|
252
|
-
}
|