@nxtedition/deepstream.io-client-js 32.0.0 → 32.0.3

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": "32.0.0",
3
+ "version": "32.0.3",
4
4
  "description": "the javascript client for deepstream.io",
5
5
  "homepage": "http://deepstream.io",
6
6
  "type": "module",
@@ -36,7 +36,7 @@
36
36
  "singleQuote": true
37
37
  },
38
38
  "dependencies": {
39
- "@nxtedition/json-path": "^2.0.0",
39
+ "@nxtedition/json-path": "^2.0.2",
40
40
  "bufferutil": "^4.1.0",
41
41
  "component-emitter2": "^1.3.5",
42
42
  "invariant": "^2.2.4",
@@ -48,7 +48,7 @@
48
48
  "xxhash-wasm": "^1.0.2"
49
49
  },
50
50
  "devDependencies": {
51
- "@types/node": "^25.0.8",
51
+ "@types/node": "^25.0.10",
52
52
  "eslint": "^9.39.2",
53
53
  "eslint-config-prettier": "^10.1.8",
54
54
  "eslint-config-standard": "^17.1.0",
@@ -60,12 +60,12 @@
60
60
  "lint-staged": "^16.2.7",
61
61
  "mitata": "^1.0.10",
62
62
  "pinst": "^3.0.0",
63
- "prettier": "^3.8.0",
63
+ "prettier": "^3.8.1",
64
64
  "rxjs": "^7.8.1",
65
65
  "tsd": "^0.33.0",
66
66
  "type-fest": "^5.4.1",
67
67
  "typescript": "^5.6.3",
68
- "typescript-eslint": "^8.53.0"
68
+ "typescript-eslint": "^8.53.1"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "rxjs": ">=6.x"
@@ -96,6 +96,9 @@ expectError(ds.record.set('n', 'n1.x2', {}))
96
96
  expectError(ds.record.set('n', 'n1.n2.n3', { n4: 22 }))
97
97
 
98
98
  expectAssignable<string>(await ds.record.get('p', 'p1'))
99
+ expectAssignable<{ name: string; version: string; state: number; data: string }>(
100
+ await ds.record.get2('p', 'p1'),
101
+ )
99
102
  expectAssignable<string>(await ds.record.get('p', 'p1', { signal: new AbortController().signal }))
100
103
  expectAssignable<string>(await ds.record.get('p', { path: 'p1' }))
101
104
  expectAssignable<string | undefined>(await ds.record.get('p', 'p2'))
@@ -113,6 +113,73 @@ export default class RecordHandler<Records = Record<string, unknown>> {
113
113
  ): Observable<Get<Lookup<Records, Name>, Path>>
114
114
  }
115
115
 
116
+ observe2: {
117
+ <Name extends string>(
118
+ name: Name,
119
+ options: ObserveOptions,
120
+ ): Observable<{
121
+ name: string
122
+ version: string
123
+ state: number
124
+ data: Lookup<Records, Name>
125
+ }>
126
+
127
+ <Name extends string, Path extends string | string[]>(
128
+ name: Name,
129
+ options: ObserveOptionsWithPath<Path>,
130
+ ): Observable<{
131
+ name: string
132
+ version: string
133
+ state: number
134
+ data: Get<Lookup<Records, Name>, Path>
135
+ }>
136
+
137
+ <Name extends string>(
138
+ name: Name,
139
+ state?: number,
140
+ options?: ObserveOptions,
141
+ ): Observable<{
142
+ name: string
143
+ version: string
144
+ state: number
145
+ data: Lookup<Records, Name>
146
+ }>
147
+
148
+ <Name extends string, Path extends string | string[]>(
149
+ name: Name,
150
+ state?: number,
151
+ options?: ObserveOptionsWithPath<Path>,
152
+ ): Observable<{
153
+ name: string
154
+ version: string
155
+ state: number
156
+ data: Get<Lookup<Records, Name>, Path>
157
+ }>
158
+
159
+ <Name extends string, Path extends string | string[]>(
160
+ name: Name,
161
+ path: Path,
162
+ options?: ObserveOptionsWithPath<Path>,
163
+ ): Observable<{
164
+ name: string
165
+ version: string
166
+ state: number
167
+ data: Get<Lookup<Records, Name>, Path>
168
+ }>
169
+
170
+ <Name extends string, Path extends string | string[]>(
171
+ name: Name,
172
+ path: Path,
173
+ state?: number,
174
+ options?: ObserveOptionsWithPath<Path>,
175
+ ): Observable<{
176
+ name: string
177
+ version: string
178
+ state: number
179
+ data: Get<Lookup<Records, Name>, Path>
180
+ }>
181
+ }
182
+
116
183
  get: {
117
184
  <Name extends string>(name: Name, options: ObserveOptions): Promise<Lookup<Records, Name>>
118
185
 
@@ -147,11 +214,11 @@ export default class RecordHandler<Records = Record<string, unknown>> {
147
214
  ): Promise<Get<Lookup<Records, Name>, Path>>
148
215
  }
149
216
 
150
- observe2: {
217
+ get2: {
151
218
  <Name extends string>(
152
219
  name: Name,
153
220
  options: ObserveOptions,
154
- ): Observable<{
221
+ ): Promise<{
155
222
  name: string
156
223
  version: string
157
224
  state: number
@@ -161,7 +228,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
161
228
  <Name extends string, Path extends string | string[]>(
162
229
  name: Name,
163
230
  options: ObserveOptionsWithPath<Path>,
164
- ): Observable<{
231
+ ): Promise<{
165
232
  name: string
166
233
  version: string
167
234
  state: number
@@ -172,7 +239,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
172
239
  name: Name,
173
240
  state?: number,
174
241
  options?: ObserveOptions,
175
- ): Observable<{
242
+ ): Promise<{
176
243
  name: string
177
244
  version: string
178
245
  state: number
@@ -183,7 +250,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
183
250
  name: Name,
184
251
  state?: number,
185
252
  options?: ObserveOptionsWithPath<Path>,
186
- ): Observable<{
253
+ ): Promise<{
187
254
  name: string
188
255
  version: string
189
256
  state: number
@@ -194,7 +261,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
194
261
  name: Name,
195
262
  path: Path,
196
263
  options?: ObserveOptionsWithPath<Path>,
197
- ): Observable<{
264
+ ): Promise<{
198
265
  name: string
199
266
  version: string
200
267
  state: number
@@ -206,7 +273,7 @@ export default class RecordHandler<Records = Record<string, unknown>> {
206
273
  path: Path,
207
274
  state?: number,
208
275
  options?: ObserveOptionsWithPath<Path>,
209
- ): Observable<{
276
+ ): Promise<{
210
277
  name: string
211
278
  version: string
212
279
  state: number
@@ -44,17 +44,10 @@ function onUpdate(record, subscription) {
44
44
  }
45
45
 
46
46
  if (!subscription.synced || subscription.record.state < subscription.state) {
47
- if (subscription.timeoutValue > 0) {
48
- if (!subscription.timeout) {
49
- subscription.timeout = timers.setTimeout(onTimeout, subscription.timeoutValue, subscription)
50
- } else {
51
- subscription.timeout.refresh()
52
- }
53
- }
54
47
  return
55
48
  }
56
49
 
57
- if (subscription.timeout) {
50
+ if (subscription.timeout != null) {
58
51
  timers.clearTimeout(subscription.timeout)
59
52
  subscription.timeout = null
60
53
  }
@@ -101,6 +94,34 @@ function onTimeout(subscription) {
101
94
  )
102
95
  }
103
96
 
97
+ class Subscription {
98
+ /** @type {unknown} */
99
+ subscriber = null
100
+ /** @type {unknown} */
101
+ path = null
102
+ /** @type {number} */
103
+ state = 0
104
+ /** @type {AbortSignal|null} */
105
+ signal = null
106
+ /** @type {boolean} */
107
+ dataOnly = false
108
+
109
+ /** @type {Record|null} */
110
+ record = null
111
+ /** @type {Timeout|null} */
112
+ timeout = null
113
+ /** @type {Function?} */
114
+ abort = null
115
+ /** @type {object|Array} */
116
+ data = kEmpty
117
+ /** @type {boolean} */
118
+ synced = false
119
+
120
+ index = -1
121
+
122
+ onUpdate = onUpdate
123
+ }
124
+
104
125
  class RecordHandler {
105
126
  constructor(options, connection, client) {
106
127
  this.JSON = jsonPath
@@ -146,13 +167,23 @@ class RecordHandler {
146
167
  this._pruning = new Set()
147
168
 
148
169
  for (const rec of pruning) {
149
- rec._$dispose()
150
- this._records.delete(rec.name)
170
+ try {
171
+ rec._$dispose()
172
+ if (!this._records.delete(rec.name)) {
173
+ this._client._$onError(
174
+ C.TOPIC.RECORD,
175
+ C.EVENT.INTERNAL_ERROR,
176
+ `failed to delete pruned record: ${rec.name}`,
177
+ )
178
+ }
179
+ } catch (err) {
180
+ this._client._$onError(C.TOPIC.RECORD, C.EVENT.INTERNAL_ERROR, err)
181
+ }
151
182
  }
152
183
 
153
- this._stats.pruning -= pruning.size
154
- this._stats.records -= pruning.size
155
184
  this._stats.destroyed += pruning.size
185
+ this._stats.pruning = this._pruning.size
186
+ this._stats.records = this._records.size
156
187
 
157
188
  this._pruningTimeout.refresh()
158
189
  }
@@ -161,17 +192,12 @@ class RecordHandler {
161
192
  }
162
193
 
163
194
  _onPruning(rec, value) {
164
- if (value) {
165
- this._stats.pruning += 1
166
- } else {
167
- this._stats.pruning -= 1
168
- }
169
-
170
195
  if (value) {
171
196
  this._pruning.add(rec)
172
197
  } else {
173
198
  this._pruning.delete(rec)
174
199
  }
200
+ this._stats.pruning = this._pruning.size
175
201
  }
176
202
 
177
203
  _onUpdating(rec, value) {
@@ -194,17 +220,15 @@ class RecordHandler {
194
220
 
195
221
  _onPatching(rec, value) {
196
222
  if (value) {
197
- this._stats.patching += 1
198
223
  this._patching.set(rec, [])
199
224
  } else {
200
- this._stats.patching -= 1
201
-
202
225
  const callbacks = this._patching.get(rec)
203
226
  this._patching.delete(rec)
204
227
  for (const callback of callbacks) {
205
228
  callback()
206
229
  }
207
230
  }
231
+ this._stats.patching = this._patching.size
208
232
  }
209
233
 
210
234
  get connected() {
@@ -242,15 +266,16 @@ class RecordHandler {
242
266
  }
243
267
 
244
268
  let record = this._records.get(name)
245
-
246
269
  if (!record) {
247
270
  record = new Record(name, this)
248
- this._stats.records += 1
249
- this._stats.created += 1
250
271
  this._records.set(name, record)
272
+ this._stats.created += 1
273
+ this._stats.records = this._records.size
274
+ } else {
275
+ record.ref()
251
276
  }
252
277
 
253
- return record.ref()
278
+ return record
254
279
  }
255
280
 
256
281
  provide(pattern, callback, options) {
@@ -638,36 +663,19 @@ class RecordHandler {
638
663
  }
639
664
 
640
665
  return new rxjs.Observable((subscriber) => {
641
- // TODO (perf): Make a class
642
- const subscription = {
643
- /** @readonly @type {unknown} */
644
- subscriber,
645
- /** @readonly @type {unknown} */
646
- path,
647
- /** @readonly @type {number} */
648
- state,
649
- /** @type {AbortSignal|null} */
650
- signal,
651
- /** @readonly @type {boolean} */
652
- dataOnly,
653
- /** @readonly @type {number} */
654
- timeoutValue: timeout,
655
-
656
- /** @type {Record|null} */
657
- record: null,
658
- /** @type {Timeout|null} */
659
- timeout: null,
660
- /** @type {Function?} */
661
- abort: null,
662
- /** @type {object|Array} */
663
- data: kEmpty,
664
- /** @type {boolean} */
665
- synced: false,
666
-
667
- index: -1,
668
- onUpdate,
666
+ if (signal?.aborted) {
667
+ subscriber.error(new utils.AbortError())
668
+ return
669
669
  }
670
670
 
671
+ const subscription = new Subscription()
672
+
673
+ subscription.subscriber = subscriber
674
+ subscription.path = path
675
+ subscription.state = state
676
+ subscription.signal = signal
677
+ subscription.dataOnly = dataOnly
678
+
671
679
  subscriber.add(() => {
672
680
  if (subscription.timeout) {
673
681
  timers.clearTimeout(subscription.timeout)
@@ -700,6 +708,10 @@ class RecordHandler {
700
708
  } else {
701
709
  onSync(subscription)
702
710
  }
711
+
712
+ if (timeout > 0 && (!subscription.synced || subscription.record.state < subscription.state)) {
713
+ subscription.timeout = timers.setTimeout(onTimeout, timeout, subscription)
714
+ }
703
715
  })
704
716
  }
705
717
 
@@ -18,7 +18,7 @@ class Record {
18
18
  this._version = ''
19
19
  this._data = jsonPath.EMPTY_OBJ
20
20
  this._state = C.RECORD_STATE.VOID
21
- this._refs = 0
21
+ this._refs = 1
22
22
  this._subscriptions = []
23
23
 
24
24
  /** @type {Array|null} */
@@ -141,6 +141,11 @@ class Record {
141
141
  throw new Error('already observing')
142
142
  }
143
143
 
144
+ if (this._emittingArr === this._observers) {
145
+ // TODO (perf): Shift from start if emitting?
146
+ this._observers = this._observers.slice()
147
+ }
148
+
144
149
  subscription.index = this._observers.push(subscription) - 1
145
150
  }
146
151