@nxtedition/deepstream.io-client-js 23.4.61 → 24.0.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/deepstream.io-client-js",
3
- "version": "23.4.61",
3
+ "version": "24.0.1",
4
4
  "description": "the javascript client for deepstream.io",
5
5
  "homepage": "http://deepstream.io",
6
6
  "bugs": {
@@ -13,6 +13,44 @@ const timers = require('../utils/timers')
13
13
 
14
14
  const kEmpty = Symbol('kEmpty')
15
15
 
16
+ function onUpdate(record, subscription) {
17
+ if (subscription.state && record.state < subscription.state) {
18
+ return
19
+ }
20
+
21
+ if (subscription.timeout) {
22
+ timers.clearTimeout(subscription.timeout)
23
+ subscription.timeout = null
24
+ }
25
+
26
+ const data = subscription.path ? record.get(subscription.path) : record.data
27
+
28
+ if (subscription.dataOnly) {
29
+ if (data !== subscription.data) {
30
+ subscription.data = data
31
+ subscription.subscriber.next(data)
32
+ }
33
+ } else {
34
+ subscription.subscriber.next({
35
+ name: record.name,
36
+ version: record.version,
37
+ state: record.state,
38
+ data,
39
+ })
40
+ }
41
+ }
42
+
43
+ function onTimeout(subscription) {
44
+ const expected = C.RECORD_STATE_NAME[subscription.state]
45
+ const current = C.RECORD_STATE_NAME[subscription.record.state]
46
+
47
+ subscription.subscriber.error(
48
+ Object.assign(new Error(`timeout ${subscription.record.name} [${current}<${expected}]`), {
49
+ code: 'ETIMEDOUT',
50
+ })
51
+ )
52
+ }
53
+
16
54
  class RecordHandler {
17
55
  constructor(options, connection, client) {
18
56
  this.JSON = jsonPath
@@ -132,6 +170,10 @@ class RecordHandler {
132
170
  return this._stats
133
171
  }
134
172
 
173
+ /**
174
+ * @param {string} name
175
+ * @returns {Record}
176
+ */
135
177
  getRecord(name) {
136
178
  invariant(
137
179
  typeof name === 'string' && name.length > 0 && name !== '[object Object]',
@@ -261,7 +303,7 @@ class RecordHandler {
261
303
  let path
262
304
  let state = defaults ? defaults.state : undefined
263
305
  let signal
264
- let timeoutValue = defaults ? defaults.timeout : undefined
306
+ let timeout = defaults ? defaults.timeout : undefined
265
307
  let dataOnly = defaults ? defaults.dataOnly : undefined
266
308
 
267
309
  let idx = 0
@@ -282,7 +324,7 @@ class RecordHandler {
282
324
  }
283
325
 
284
326
  if (options.timeout != null) {
285
- timeoutValue = options.timeout
327
+ timeout = options.timeout
286
328
  }
287
329
 
288
330
  if (options.path != null) {
@@ -302,84 +344,53 @@ class RecordHandler {
302
344
  state = C.RECORD_STATE[state.toUpperCase()]
303
345
  }
304
346
 
305
- if (!name) {
306
- const data = path ? undefined : jsonPath.EMPTY
307
- return rxjs.of(
308
- dataOnly
309
- ? data
310
- : utils.deepFreeze({
311
- name,
312
- version: '0-00000000000000',
313
- data,
314
- state: Number.isFinite(state) ? state : C.RECORD_STATE.SERVER,
315
- })
316
- )
317
- }
318
-
319
- if (signal?.aborted) {
320
- return rxjs.throwError(() => new utils.AbortError())
321
- }
322
-
323
- return new rxjs.Observable((o) => {
324
- let timeoutHandle
325
- let prevData = kEmpty
326
-
327
- const onUpdate = (record) => {
328
- if (state && record.state < state) {
329
- return
330
- }
331
-
332
- if (timeoutHandle) {
333
- timers.clearTimeout(timeoutHandle)
334
- timeoutHandle = null
335
- }
347
+ return new rxjs.Observable((subscriber) => {
348
+ const subscription = {
349
+ subscriber,
350
+ path,
351
+ state,
352
+ signal,
353
+ dataOnly,
354
+ data: kEmpty,
355
+ timeout: null,
356
+ /** @type {Record?} */ record: null,
357
+ /** @type {Function?} */ abort: null,
358
+ unsubscribe() {
359
+ if (this.timeout) {
360
+ timers.clearTimeout(this.timeout)
361
+ this.timeout = null
362
+ }
336
363
 
337
- const nextData = path ? record.get(path) : record.data
364
+ if (this.signal) {
365
+ utils.removeAbortListener(this.signal, this.abort)
366
+ this.signal = null
367
+ this.abort = null
368
+ }
338
369
 
339
- if (dataOnly) {
340
- if (nextData !== prevData) {
341
- prevData = nextData
342
- o.next(nextData)
370
+ if (this.record) {
371
+ this.record.unsubscribe(onUpdate, this)
372
+ this.record.unref()
373
+ this.record = null
343
374
  }
344
- } else {
345
- o.next({
346
- name: record.name,
347
- version: record.version,
348
- data: nextData,
349
- state: record.state,
350
- })
351
- }
375
+ },
352
376
  }
353
377
 
354
- const record = this.getRecord(name).subscribe(onUpdate)
355
-
356
- if (timeoutValue && state && record.state < state) {
357
- timeoutHandle = timers.setTimeout(() => {
358
- const expected = C.RECORD_STATE_NAME[state]
359
- const current = C.RECORD_STATE_NAME[record.state]
360
- o.error(
361
- Object.assign(
362
- new Error(
363
- `timeout after ${timeoutValue / 1e3}s: ${record.name} [${current}<${expected}]`
364
- ),
365
- { code: 'ETIMEDOUT' }
366
- )
367
- )
368
- }, timeoutValue)
369
- }
378
+ subscription.record = this.getRecord(name).subscribe(onUpdate, subscription)
370
379
 
371
- if (record.version) {
372
- onUpdate(record)
380
+ if (timeout && subscription.state && subscription.record.state < subscription.state) {
381
+ subscription.timeout = timers.setTimeout(onTimeout, timeout, subscription)
373
382
  }
374
383
 
375
- const abort = signal ? () => o.error(new utils.AbortError()) : null
376
-
377
- utils.addAbortListener(signal, abort)
384
+ if (subscription.record.version) {
385
+ onUpdate(subscription.record, subscription)
386
+ }
378
387
 
379
- return () => {
380
- record.unsubscribe(onUpdate).unref()
381
- utils.removeAbortListener(signal, abort)
388
+ if (subscription.signal) {
389
+ subscription.abort = () => subscription.subscriber.error(new utils.AbortError())
390
+ utils.addAbortListener(subscription.signal, subscription.abort)
382
391
  }
392
+
393
+ return subscription
383
394
  })
384
395
  }
385
396
 
@@ -47,6 +47,10 @@ class Record {
47
47
  return this._refs
48
48
  }
49
49
 
50
+ /**
51
+ *
52
+ * @returns {Record}
53
+ */
50
54
  ref() {
51
55
  this._refs += 1
52
56
  if (this._refs === 1) {
@@ -56,6 +60,10 @@ class Record {
56
60
  return this
57
61
  }
58
62
 
63
+ /**
64
+ *
65
+ * @returns {Record}
66
+ */
59
67
  unref() {
60
68
  this._refs -= 1
61
69
  if (this._refs === 0) {
@@ -64,26 +72,48 @@ class Record {
64
72
  return this
65
73
  }
66
74
 
67
- subscribe(fn) {
75
+ /**
76
+ *
77
+ * @param {*} fn
78
+ * @param {*} opaque
79
+ * @returns {Record}
80
+ */
81
+ subscribe(fn, opaque = null) {
68
82
  if (this._emitting) {
69
83
  this._subscriptions = this._subscriptions.slice()
70
84
  this._emitting = false
71
85
  }
72
86
 
73
- this._subscriptions.push(fn)
87
+ this._subscriptions.push(fn, opaque)
74
88
 
75
89
  return this
76
90
  }
77
91
 
78
- unsubscribe(fn) {
92
+ /**
93
+ *
94
+ * @param {*} fn
95
+ * @param {*} opaque
96
+ * @returns {Record}
97
+ */
98
+ unsubscribe(fn, opaque = null) {
79
99
  if (this._emitting) {
80
100
  this._subscriptions = this._subscriptions.slice()
81
101
  this._emitting = false
82
102
  }
83
103
 
84
- const idx = this._subscriptions.indexOf(fn)
104
+ let idx = -1
105
+
106
+ const arr = this._subscriptions
107
+ const len = arr.length
108
+ for (let n = 0; n < len; n += 2) {
109
+ if (arr[n + 0] === fn && arr[n + 1] === opaque) {
110
+ idx = n
111
+ break
112
+ }
113
+ }
114
+
85
115
  if (idx !== -1) {
86
- this._subscriptions.splice(idx, 1)
116
+ this._subscriptions.splice(idx, 2)
87
117
  }
88
118
 
89
119
  return this
@@ -417,9 +447,12 @@ class Record {
417
447
  _emitUpdate() {
418
448
  this._emitting = true
419
449
  try {
420
- for (const fn of this._subscriptions) {
450
+ const arr = this._subscriptions
451
+ const len = arr.length
452
+
453
+ for (let n = 0; n < len; n += 2) {
421
454
  try {
422
- fn(this)
455
+ arr[n + 0](this, arr[n + 1])
423
456
  } catch (err) {
424
457
  this._error(
425
458
  C.EVENT.USER_ERROR,
@@ -143,13 +143,17 @@ module.exports.addAbortListener = function addAbortListener(signal, handler) {
143
143
  return
144
144
  }
145
145
 
146
- let handlers = abortSignals.get(signal)
147
- if (!handlers) {
148
- handlers = []
149
- abortSignals.set(signal, handlers)
150
- signal.addEventListener('abort', onAbort)
146
+ if (signal.aborted) {
147
+ queueMicrotask(handler)
148
+ } else {
149
+ let handlers = abortSignals.get(signal)
150
+ if (!handlers) {
151
+ handlers = []
152
+ abortSignals.set(signal, handlers)
153
+ signal.addEventListener('abort', onAbort)
154
+ }
155
+ handlers.push(handler)
151
156
  }
152
- handlers.push(handler)
153
157
  }
154
158
 
155
159
  module.exports.removeAbortListener = function removeAbortListener(signal, handler) {