@nxtedition/deepstream.io-client-js 24.3.2 → 24.3.4

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": "24.3.2",
3
+ "version": "24.3.4",
4
4
  "description": "the javascript client for deepstream.io",
5
5
  "homepage": "http://deepstream.io",
6
6
  "type": "module",
@@ -65,6 +65,7 @@
65
65
  "invariant": "^2.2.4",
66
66
  "lodash.clonedeep": "^4.5.0",
67
67
  "utf-8-validate": "^6.0.3",
68
+ "varint": "^6.0.0",
68
69
  "ws": "^8.13.0",
69
70
  "xuid": "^4.1.2",
70
71
  "xxhash-wasm": "^1.0.2"
@@ -151,8 +151,8 @@ Connection.prototype.send = function (message) {
151
151
  Connection.prototype._submit = function (message) {
152
152
  const { maxPacketSize } = this._options
153
153
 
154
- if (message.length > maxPacketSize) {
155
- const err = new Error(`Packet to big: ${message.length} > ${maxPacketSize}`)
154
+ if (message.byteLength > maxPacketSize) {
155
+ const err = new Error(`Packet to big: ${message.byteLength} > ${maxPacketSize}`)
156
156
  this._client._$onError(C.TOPIC.CONNECTION, C.EVENT.CONNECTION_ERROR, err)
157
157
  return false
158
158
  } else if (this._endpoint.readyState === this._endpoint.OPEN) {
@@ -1,4 +1,5 @@
1
1
  import * as C from '../constants/constants.js'
2
+ import varint from 'varint'
2
3
 
3
4
  const poolEncoder = new TextEncoder()
4
5
 
@@ -8,7 +9,7 @@ let poolView
8
9
  let poolOffset
9
10
 
10
11
  function reallocPool(size) {
11
- poolSize = size ?? poolSize ?? 1024 * 1024
12
+ poolSize = size || poolSize || 1024 * 1024
12
13
  poolBuffer = new Uint8Array(new ArrayBuffer(poolSize))
13
14
  poolView = new DataView(poolBuffer.buffer)
14
15
  poolOffset = 0
@@ -22,14 +23,12 @@ function alignPool() {
22
23
  }
23
24
  }
24
25
 
25
- reallocPool()
26
-
27
26
  export function getMsg(topic, action, data) {
28
27
  if (data && !(data instanceof Array)) {
29
28
  throw new Error('data must be an array')
30
29
  }
31
30
 
32
- if (poolOffset + poolSize / 16 >= poolSize) {
31
+ if (!poolSize || poolOffset + poolSize / 16 >= poolSize) {
33
32
  reallocPool()
34
33
  } else {
35
34
  alignPool()
@@ -37,6 +36,11 @@ export function getMsg(topic, action, data) {
37
36
 
38
37
  const start = poolOffset
39
38
 
39
+ const headerSize = 8
40
+ poolBuffer[poolOffset++] = 128 + headerSize
41
+ let headerPos = poolOffset
42
+ poolOffset += headerSize - 1
43
+
40
44
  poolBuffer[poolOffset++] = topic.charCodeAt(0)
41
45
  poolBuffer[poolOffset++] = 31
42
46
  for (let n = 0; n < action.length; n++) {
@@ -46,33 +50,44 @@ export function getMsg(topic, action, data) {
46
50
  if (data) {
47
51
  for (let i = 0; i < data.length; i++) {
48
52
  const type = typeof data[i]
53
+ let len
49
54
  if (data[i] == null) {
50
55
  poolBuffer[poolOffset++] = 31
56
+ len = 0
51
57
  } else if (type === 'object') {
52
58
  poolBuffer[poolOffset++] = 31
53
59
  const res = poolEncoder.encodeInto(
54
60
  JSON.stringify(data[i]),
55
61
  new Uint8Array(poolBuffer.buffer, poolOffset)
56
62
  )
57
- poolOffset += res.written
63
+ len = res.written
58
64
  } else if (type === 'bigint') {
59
65
  poolBuffer[poolOffset++] = 31
60
66
  poolView.setBigUint64(poolOffset, data[i], false)
61
- poolOffset += 8
67
+ len = 8
62
68
  } else if (type === 'string') {
63
69
  poolBuffer[poolOffset++] = 31
64
70
  const res = poolEncoder.encodeInto(data[i], new Uint8Array(poolBuffer.buffer, poolOffset))
65
- poolOffset += res.written
71
+ len = res.written
66
72
  } else {
67
73
  throw new Error('invalid data')
68
74
  }
69
75
 
76
+ poolOffset += len
77
+
78
+ varint.encode(len + 1, poolBuffer, headerPos)
79
+ headerPos += varint.encode.bytes
80
+ if (headerPos - start >= headerSize) {
81
+ throw new Error(`header too large: ${headerPos - start} ${headerSize}`)
82
+ }
83
+
70
84
  if (poolOffset >= poolBuffer.length) {
71
85
  reallocPool(start === 0 ? poolSize * 2 : poolSize)
72
86
  return getMsg(topic, action, data)
73
87
  }
74
88
  }
75
89
  }
90
+
76
91
  return new Uint8Array(poolBuffer.buffer, start, poolOffset - start)
77
92
  }
78
93
 
@@ -101,6 +101,7 @@ class RecordHandler {
101
101
  this._pruning = new Set()
102
102
  this._patching = new Map()
103
103
  this._updating = new Map()
104
+ this._encoder = new TextEncoder()
104
105
 
105
106
  this._connected = 0
106
107
  this._stats = {
@@ -206,6 +207,12 @@ class RecordHandler {
206
207
  }
207
208
  }
208
209
 
210
+ getKey(name) {
211
+ return name.length <= 8 && this._encoder.encode(name).byteLength === 8
212
+ ? name
213
+ : this._connection.hasher.h64(name)
214
+ }
215
+
209
216
  /**
210
217
  * @param {string} name
211
218
  * @returns {Record}
@@ -219,7 +226,7 @@ class RecordHandler {
219
226
  let record = this._records.get(name)
220
227
 
221
228
  if (!record) {
222
- record = new Record(name, this)
229
+ record = new Record(this.getKey(name), name, this)
223
230
  this._stats.records += 1
224
231
  this._stats.created += 1
225
232
  this._records.set(name, record)
@@ -12,18 +12,10 @@ import * as timers from '../utils/timers.js'
12
12
  class Record {
13
13
  static STATE = C.RECORD_STATE
14
14
 
15
- constructor(name, handler) {
16
- const connection = handler._connection
17
-
15
+ constructor(key, name, handler) {
18
16
  this._handler = handler
19
-
20
- // TODO (fix): Implement this once we have binary header.
21
- // this._key = name.length <= 8 && encoder.encode(name).byteLength === 8
22
- // ? name
23
- // : connection.hasher?.h64(name)
24
-
25
17
  this._name = name
26
- this._key = name
18
+ this._key = key
27
19
  this._version = ''
28
20
  this._data = jsonPath.EMPTY
29
21
  this._state = C.RECORD_STATE.VOID
@@ -33,10 +25,7 @@ class Record {
33
25
 
34
26
  /** @type Map? */ this._updating = null
35
27
  /** @type Array? */ this._patching = null
36
- this._subscribed = connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [
37
- this._name,
38
- this._key,
39
- ])
28
+ this._subscribed = false
40
29
  }
41
30
 
42
31
  /** @type {string} */
@@ -56,6 +56,7 @@ class Listener {
56
56
  // TODO (refactor): Move to class
57
57
  const provider = {
58
58
  name,
59
+ key: this._handler.getKey(name),
59
60
  value$: null,
60
61
  sending: false,
61
62
  accepted: false,
@@ -68,7 +69,7 @@ class Listener {
68
69
  if (this.connected && provider.accepted) {
69
70
  this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [
70
71
  this._pattern,
71
- provider.name,
72
+ provider.key,
72
73
  ])
73
74
  }
74
75
 
@@ -101,7 +102,7 @@ class Listener {
101
102
  this._connection.sendMsg(
102
103
  this._topic,
103
104
  accepted ? C.ACTIONS.LISTEN_ACCEPT : C.ACTIONS.LISTEN_REJECT,
104
- [this._pattern, provider.name]
105
+ [this._pattern, provider.key]
105
106
  )
106
107
 
107
108
  provider.version = null
@@ -157,7 +158,7 @@ class Listener {
157
158
  if (provider.version !== version) {
158
159
  provider.version = version
159
160
  this._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UPDATE, [
160
- provider.name,
161
+ provider.key,
161
162
  version,
162
163
  body,
163
164
  ])
@@ -218,7 +219,11 @@ class Listener {
218
219
  }
219
220
 
220
221
  _error(name, err) {
221
- this._client._$onError(this._topic, C.EVENT.LISTENER_ERROR, err, [this._pattern, name])
222
+ this._client._$onError(this._topic, C.EVENT.LISTENER_ERROR, err, [
223
+ this._pattern,
224
+ name,
225
+ this._handler.getKey(name),
226
+ ])
222
227
  }
223
228
 
224
229
  _reset() {
@@ -68,27 +68,29 @@ class Listener {
68
68
  value$ = rxjs.throwError(() => err)
69
69
  }
70
70
 
71
+ const key = this._handler.getKey(name)
72
+
71
73
  if (value$) {
72
74
  const subscription = value$.pipe(PIPE).subscribe({
73
75
  next: (data) => {
74
76
  if (data == null) {
75
- this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
77
+ this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, key])
76
78
  this._subscriptions.delete(name)
77
79
  subscription.unsubscribe()
78
80
  } else {
79
81
  const version = `INF-${this._connection.hasher.h64ToString(data)}`
80
- this._connection.sendMsg(this._topic, C.ACTIONS.UPDATE, [name, version, data])
82
+ this._connection.sendMsg(this._topic, C.ACTIONS.UPDATE, [key, version, data])
81
83
  }
82
84
  },
83
85
  error: (err) => {
84
86
  this._error(name, err)
85
- this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
87
+ this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, key])
86
88
  this._subscriptions.delete(name)
87
89
  },
88
90
  })
89
91
  this._subscriptions.set(name, subscription)
90
92
  } else {
91
- this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
93
+ this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, key])
92
94
  }
93
95
  } else if (message.action === C.ACTIONS.LISTEN_REJECT) {
94
96
  const subscription = this._subscriptions.get(name)