@nxtedition/deepstream.io-client-js 26.0.13 → 27.0.0-beta.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": "26.0.13",
3
+ "version": "27.0.0-beta.1",
4
4
  "description": "the javascript client for deepstream.io",
5
5
  "homepage": "http://deepstream.io",
6
6
  "type": "module",
@@ -170,7 +170,7 @@ Connection.prototype._sendAuthParams = function () {
170
170
  this._setState(C.CONNECTION_STATE.AUTHENTICATING)
171
171
  const authMessage = messageBuilder.getMsg(C.TOPIC.AUTH, C.ACTIONS.REQUEST, [
172
172
  this._authParams,
173
- '26.0.0',
173
+ '27.0.0',
174
174
  utils.isNode
175
175
  ? `Node/${process.version}`
176
176
  : globalThis.navigator && globalThis.navigator.userAgent,
@@ -11,11 +11,16 @@ export default class Record {
11
11
  static STATE = C.RECORD_STATE
12
12
 
13
13
  constructor(name, handler) {
14
+ if (!name?.length || typeof name !== 'string') {
15
+ throw new Error('invalid argument: name')
16
+ }
17
+
14
18
  const connection = handler._connection
15
19
 
16
20
  this._handler = handler
17
21
 
18
22
  this._name = name
23
+ this._key = utils.hashNameBigInt(name)
19
24
  this._version = ''
20
25
  this._data = jsonPath.EMPTY
21
26
  this._state = C.RECORD_STATE.VOID
@@ -24,7 +29,10 @@ export default class Record {
24
29
  this._emitting = false
25
30
  /** @type Map? */ this._updating = null
26
31
  /** @type Array? */ this._patching = null
27
- this._subscribed = connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [this._name])
32
+ this._subscribed = connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [
33
+ this._name,
34
+ this._key,
35
+ ])
28
36
  }
29
37
 
30
38
  /** @type {string} */
@@ -32,6 +40,11 @@ export default class Record {
32
40
  return this._name
33
41
  }
34
42
 
43
+ /** @type {bigint} */
44
+ get key() {
45
+ return this._key
46
+ }
47
+
35
48
  /** @type {string} */
36
49
  get version() {
37
50
  return this._version
@@ -62,7 +75,8 @@ export default class Record {
62
75
  if (this._refs === 1) {
63
76
  this._handler._onPruning(this, false)
64
77
  this._subscribed =
65
- this._subscribed || connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [this._name])
78
+ this._subscribed ||
79
+ connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [this._name, this._key])
66
80
  }
67
81
  return this
68
82
  }
@@ -324,7 +338,8 @@ export default class Record {
324
338
 
325
339
  if (connected) {
326
340
  this._subscribed =
327
- this._refs > 0 && connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [this._name])
341
+ this._refs > 0 &&
342
+ connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [this._key, this._name])
328
343
 
329
344
  if (this._updating) {
330
345
  for (const update of this._updating.values()) {
@@ -349,7 +364,7 @@ export default class Record {
349
364
  invariant(!this._updating, 'must not have updates')
350
365
 
351
366
  if (this._subscribed) {
352
- connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UNSUBSCRIBE, [this._name])
367
+ connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UNSUBSCRIBE, [this._key])
353
368
  this._subscribed = false
354
369
  }
355
370
 
@@ -371,7 +386,7 @@ export default class Record {
371
386
  const prevVersion = this._version
372
387
  const nextVersion = this._makeVersion(parseInt(prevVersion) + 1)
373
388
 
374
- const update = [this._name, nextVersion, jsonPath.stringify(nextData), prevVersion]
389
+ const update = [this._key, nextVersion, jsonPath.stringify(nextData), prevVersion]
375
390
 
376
391
  if (!this._updating) {
377
392
  this._onUpdating(true)
@@ -1,5 +1,6 @@
1
1
  import * as C from '../constants/constants.js'
2
2
  import * as rxjs from 'rxjs'
3
+ import * as utils from '../utils/utils.js'
3
4
 
4
5
  class Listener {
5
6
  constructor(topic, pattern, callback, handler, { recursive = false, stringify = null } = {}) {
@@ -47,8 +48,15 @@ class Listener {
47
48
 
48
49
  const name = message.data[1]
49
50
 
51
+ if (!name?.length) {
52
+ this._error(name, 'invalid message')
53
+ return
54
+ }
55
+
56
+ const key = utils.hashNameBigInt(name)
57
+
50
58
  if (message.action === C.ACTIONS.SUBSCRIPTION_FOR_PATTERN_FOUND) {
51
- if (this._subscriptions.has(name)) {
59
+ if (this._subscriptions.has(key)) {
52
60
  this._error(name, 'invalid add: listener exists')
53
61
  return
54
62
  }
@@ -56,6 +64,7 @@ class Listener {
56
64
  // TODO (refactor): Move to class
57
65
  const provider = {
58
66
  name,
67
+ key,
59
68
  value$: null,
60
69
  sending: false,
61
70
  accepted: false,
@@ -68,7 +77,7 @@ class Listener {
68
77
  if (this.connected && provider.accepted) {
69
78
  this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [
70
79
  this._pattern,
71
- provider.name,
80
+ provider.key,
72
81
  ])
73
82
  }
74
83
 
@@ -101,7 +110,7 @@ class Listener {
101
110
  this._connection.sendMsg(
102
111
  this._topic,
103
112
  accepted ? C.ACTIONS.LISTEN_ACCEPT : C.ACTIONS.LISTEN_REJECT,
104
- [this._pattern, provider.name],
113
+ [this._pattern, provider.key],
105
114
  )
106
115
 
107
116
  provider.version = null
@@ -151,13 +160,13 @@ class Listener {
151
160
  }
152
161
 
153
162
  const body = typeof value !== 'string' ? this._stringify(value) : value
154
- const hash = this._connection.hasher.h64ToString(body)
163
+ const hash = utils.h64ToString(body)
155
164
  const version = `INF-${hash}`
156
165
 
157
166
  if (provider.version !== version) {
158
167
  provider.version = version
159
168
  this._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UPDATE, [
160
- provider.name,
169
+ provider.key,
161
170
  version,
162
171
  body,
163
172
  ])
@@ -181,9 +190,9 @@ class Listener {
181
190
 
182
191
  provider.start()
183
192
 
184
- this._subscriptions.set(provider.name, provider)
193
+ this._subscriptions.set(provider.key, provider)
185
194
  } else if (message.action === C.ACTIONS.LISTEN_ACCEPT) {
186
- const provider = this._subscriptions.get(name)
195
+ const provider = this._subscriptions.get(key)
187
196
  if (!provider?.value$) {
188
197
  return
189
198
  }
@@ -195,13 +204,13 @@ class Listener {
195
204
  provider.valueSubscription = provider.value$.subscribe(provider.observer)
196
205
  }
197
206
  } else if (message.action === C.ACTIONS.SUBSCRIPTION_FOR_PATTERN_REMOVED) {
198
- const provider = this._subscriptions.get(name)
207
+ const provider = this._subscriptions.get(key)
199
208
 
200
209
  if (!provider) {
201
210
  this._error(name, 'invalid remove: listener missing')
202
211
  } else {
203
212
  provider.stop()
204
- this._subscriptions.delete(provider.name)
213
+ this._subscriptions.delete(provider.key)
205
214
  }
206
215
  } else {
207
216
  return false
@@ -1,5 +1,6 @@
1
1
  import * as C from '../constants/constants.js'
2
2
  import * as rxjs from 'rxjs'
3
+ import * as utils from '../utils/utils.js'
3
4
 
4
5
  const PIPE = rxjs.pipe(
5
6
  rxjs.map((value) => {
@@ -54,8 +55,15 @@ class Listener {
54
55
  _$onMessage(message) {
55
56
  const name = message.data[1]
56
57
 
58
+ if (!name?.length) {
59
+ this._error(name, 'invalid message')
60
+ return
61
+ }
62
+
63
+ const key = utils.hashNameBigInt(name)
64
+
57
65
  if (message.action === C.ACTIONS.LISTEN_ACCEPT) {
58
- if (this._subscriptions.has(name)) {
66
+ if (this._subscriptions.has(key)) {
59
67
  this._error(name, 'invalid accept: listener exists')
60
68
  return
61
69
  }
@@ -71,29 +79,29 @@ class Listener {
71
79
  const subscription = value$.pipe(PIPE).subscribe({
72
80
  next: (data) => {
73
81
  if (data == null) {
74
- this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
75
- this._subscriptions.delete(name)
82
+ this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, key])
83
+ this._subscriptions.delete(key)
76
84
  subscription.unsubscribe()
77
85
  } else {
78
- const version = `INF-${this._connection.hasher.h64ToString(data)}`
79
- this._connection.sendMsg(this._topic, C.ACTIONS.UPDATE, [name, version, data])
86
+ const version = `INF-${utils.h64ToString(data)}`
87
+ this._connection.sendMsg(this._topic, C.ACTIONS.UPDATE, [key, version, data])
80
88
  }
81
89
  },
82
90
  error: (err) => {
83
91
  this._error(name, err)
84
- this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
85
- this._subscriptions.delete(name)
92
+ this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, key])
93
+ this._subscriptions.delete(key)
86
94
  },
87
95
  })
88
- this._subscriptions.set(name, subscription)
96
+ this._subscriptions.set(key, subscription)
89
97
  } else {
90
- this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
98
+ this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, key])
91
99
  }
92
100
  } else if (message.action === C.ACTIONS.LISTEN_REJECT) {
93
- const subscription = this._subscriptions.get(name)
101
+ const subscription = this._subscriptions.get(key)
94
102
 
95
103
  if (subscription) {
96
- this._subscriptions.delete(name)
104
+ this._subscriptions.delete(key)
97
105
  subscription.unsubscribe()
98
106
  } else {
99
107
  this._error(name, 'invalid remove: listener missing')
@@ -1,3 +1,7 @@
1
+ import xxhash from 'xxhash-wasm'
2
+
3
+ const HASHER = await xxhash()
4
+
1
5
  const NODE_ENV = typeof process !== 'undefined' && process.env && process.env.NODE_ENV
2
6
  export const isNode = typeof process !== 'undefined' && process.toString() === '[object process]'
3
7
  export const isProduction = NODE_ENV === 'production'
@@ -174,3 +178,24 @@ export function removeAbortListener(signal, handler) {
174
178
  }
175
179
  }
176
180
  }
181
+
182
+ export function h64(name) {
183
+ return HASHER.h64(name)
184
+ }
185
+
186
+ export function h64ToString(name) {
187
+ return HASHER.h64ToString(name)
188
+ }
189
+
190
+ const encoder = new globalThis.TextEncoder()
191
+ const buffer = new Uint8Array(8 * 3)
192
+ const view = new DataView(buffer.buffer)
193
+
194
+ export function hashNameBigInt(name) {
195
+ if (name.length >= 8) {
196
+ return HASHER.h64(name)
197
+ }
198
+
199
+ const { written } = encoder.encodeInto(name, buffer)
200
+ return written === 8 ? view.getBigUint64(0, false) : HASHER.h64Raw(buffer.subarray(0, written))
201
+ }