@nxtedition/deepstream.io-client-js 23.4.4 → 23.4.6

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.4",
3
+ "version": "23.4.6",
4
4
  "description": "the javascript client for deepstream.io",
5
5
  "homepage": "http://deepstream.io",
6
6
  "bugs": {
@@ -19,8 +19,7 @@
19
19
  "scripts": {
20
20
  "_postinstall": "husky install",
21
21
  "prepublishOnly": "pinst --disable",
22
- "postpublish": "pinst --enable",
23
- "test": "jest --bail --watchAll"
22
+ "postpublish": "pinst --enable"
24
23
  },
25
24
  "lint-staged": {
26
25
  "*.{js,jsx,md,ts}": [
@@ -59,27 +58,27 @@
59
58
  "/__tests__"
60
59
  ],
61
60
  "dependencies": {
61
+ "@nxtedition/json-path": "^1.0.3",
62
62
  "bufferutil": "^4.0.7",
63
63
  "component-emitter2": "^1.3.5",
64
64
  "invariant": "^2.2.4",
65
- "utf-8-validate": "^5.0.10",
66
- "ws": "^8.11.0",
67
- "xuid": "^4.1.0",
65
+ "utf-8-validate": "^6.0.3",
66
+ "ws": "^8.13.0",
67
+ "xuid": "^4.1.2",
68
68
  "xxhash-wasm": "^1.0.2"
69
69
  },
70
70
  "devDependencies": {
71
- "eslint": "^8.27.0",
72
- "eslint-config-prettier": "^8.5.0",
71
+ "eslint": "^8.38.0",
72
+ "eslint-config-prettier": "^8.8.0",
73
73
  "eslint-config-standard": "^17.0.0",
74
- "eslint-plugin-import": "^2.26.0",
75
- "eslint-plugin-n": "^15.5.0",
74
+ "eslint-plugin-import": "^2.27.5",
75
+ "eslint-plugin-n": "^15.7.0",
76
76
  "eslint-plugin-node": "^11.1.0",
77
77
  "eslint-plugin-promise": "^6.1.1",
78
- "husky": "^8.0.2",
79
- "jest": "^29.3.0",
80
- "lint-staged": "^13.0.3",
78
+ "husky": "^8.0.3",
79
+ "lint-staged": "^13.2.1",
81
80
  "pinst": "^3.0.0",
82
- "prettier": "^2.7.1"
81
+ "prettier": "^2.8.7"
83
82
  },
84
83
  "peerDependencies": {
85
84
  "rxjs": ">=6.x"
@@ -5,7 +5,7 @@ const C = require('../constants/constants')
5
5
  const rxjs = require('rxjs')
6
6
  const invariant = require('invariant')
7
7
  const EventEmitter = require('component-emitter2')
8
- const jsonPath = require('./json-path')
8
+ const jsonPath = require('@nxtedition/json-path')
9
9
  const utils = require('../utils/utils')
10
10
  const rx = require('rxjs/operators')
11
11
  const xuid = require('xuid')
@@ -1,4 +1,4 @@
1
- const jsonPath = require('./json-path')
1
+ const jsonPath = require('@nxtedition/json-path')
2
2
  const utils = require('../utils/utils')
3
3
  const C = require('../constants/constants')
4
4
  const messageParser = require('../message/message-parser')
@@ -1,5 +1,4 @@
1
1
  const C = require('../constants/constants')
2
- const rx = require('rxjs/operators')
3
2
  const rxjs = require('rxjs')
4
3
 
5
4
  class Listener {
@@ -12,26 +11,7 @@ class Listener {
12
11
  this._connection = this._handler._connection
13
12
  this._subscriptions = new Map()
14
13
  this._stringify = stringify || JSON.stringify
15
- this._pipe = rxjs.pipe(
16
- rx.map((value) => {
17
- let data
18
- if (value && typeof value === 'string') {
19
- if (value.charAt(0) !== '{' && value.charAt(0) !== '[') {
20
- throw new Error(`invalid value: ${value}`)
21
- }
22
- data = value
23
- } else if (value && typeof value === 'object') {
24
- data = this._stringify(value)
25
- } else {
26
- throw new Error(`invalid value: ${value}`)
27
- }
28
-
29
- const hash = this._connection.hasher.h64ToString(data)
30
-
31
- return { data, hash }
32
- }),
33
- rx.distinctUntilKeyChanged('hash')
34
- )
14
+ this._value = null
35
15
 
36
16
  this._$onConnectionStateChange()
37
17
 
@@ -79,9 +59,30 @@ class Listener {
79
59
  }
80
60
 
81
61
  if (value$) {
82
- const subscription = value$.pipe(this._pipe).subscribe({
83
- next: ({ data, hash }) => {
84
- this._connection.sendMsg(this._topic, C.ACTIONS.UPDATE, [name, `INF-${hash}`, data])
62
+ const subscription = value$.subscribe({
63
+ next: (value) => {
64
+ let data
65
+ if (value && typeof value === 'string') {
66
+ if (value.charAt(0) !== '{' && value.charAt(0) !== '[') {
67
+ throw new Error(`invalid value: ${value}`)
68
+ }
69
+ data = value
70
+ } else if (value && typeof value === 'object') {
71
+ data = this._stringify(value)
72
+ } else {
73
+ throw new Error(`invalid value: ${value}`)
74
+ }
75
+
76
+ if (value === this._value) {
77
+ return
78
+ }
79
+
80
+ this._value = value
81
+ this._connection.sendMsg(this._topic, C.ACTIONS.UPDATE, [
82
+ name,
83
+ `INF-${this._connection.hasher.h64ToString(data)}`,
84
+ data,
85
+ ])
85
86
  },
86
87
  error: (err) => {
87
88
  this._error(name, err)
@@ -1,353 +0,0 @@
1
- const jsonPath = require('../src/record/json-path')
2
-
3
- describe('equality', () => {
4
- it('deep equal', () => {
5
- const obj = { asd: 123 }
6
- const res = jsonPath.set(
7
- {
8
- obj,
9
- foo: 'true',
10
- },
11
- null,
12
- {
13
- obj,
14
- }
15
- )
16
-
17
- expect(res.obj).toBe(obj)
18
- expect(res).toEqual({ obj })
19
- })
20
-
21
- it('returns old value', () => {
22
- const obj = {
23
- asd: true,
24
- }
25
- const res = jsonPath.set(obj, undefined, {
26
- asd: true,
27
- })
28
-
29
- expect(res).toBe(obj)
30
- })
31
- })
32
-
33
- describe('json clone', () => {
34
- it('types', () => {
35
- expect(jsonPath.jsonClone('ASD')).toEqual('ASD')
36
- expect(jsonPath.jsonClone(null)).toEqual(null)
37
- expect(jsonPath.jsonClone(undefined)).toEqual(undefined)
38
- expect(jsonPath.jsonClone(1)).toEqual(1)
39
- expect(jsonPath.jsonClone(NaN)).toEqual(null)
40
- expect(jsonPath.jsonClone(1.1)).toEqual(1.1)
41
-
42
- const date = new Date()
43
- expect(jsonPath.jsonClone(date)).toEqual(date.toISOString())
44
- })
45
- })
46
-
47
- describe('set', () => {
48
- it('set through null', () => {
49
- const res = jsonPath.set(
50
- {
51
- asd: null,
52
- },
53
- 'asd.foo.bar',
54
- true
55
- )
56
- expect(res).toEqual({
57
- asd: { foo: { bar: true } },
58
- })
59
- })
60
-
61
- it('set empty', () => {
62
- const obj = {
63
- asd: null,
64
- }
65
- const res = jsonPath.set(obj, null, {})
66
- expect(res).toEqual({})
67
- })
68
-
69
- it('set on null', () => {
70
- const res = jsonPath.set(null, null, { sad: true })
71
- expect(res).toEqual({ sad: true })
72
- })
73
-
74
- it('set string', () => {
75
- const res = jsonPath.set({ foo: 'ASD' }, null, { sad: 'ASD' })
76
- expect(res).toEqual({ sad: 'ASD' })
77
- })
78
-
79
- it('set array on object', () => {
80
- const res = jsonPath.set({}, null, [])
81
- expect(res).toEqual([])
82
- })
83
-
84
- it('set array on object plainJSON', () => {
85
- const res = jsonPath.set({}, null, [], true)
86
- expect(res).toEqual([])
87
- })
88
- })
89
-
90
- describe('order', () => {
91
- it('updates order', () => {
92
- const obj = {
93
- foo: 1,
94
- bar: 1,
95
- }
96
- const res = jsonPath.set(obj, undefined, {
97
- bar: 1,
98
- foo: 2,
99
- })
100
-
101
- expect(res).not.toBe(obj)
102
- expect(res).toEqual({ bar: 1, foo: 2 })
103
- })
104
-
105
- it('keeps order', () => {
106
- const obj = {
107
- foo: 1,
108
- bar: 1,
109
- }
110
- const res = jsonPath.set(obj, undefined, {
111
- foo: 1,
112
- bar: 1,
113
- })
114
-
115
- expect(res).toBe(obj)
116
- })
117
- })
118
-
119
- describe('paths are tokenized and retrieved correctly', () => {
120
- const testRecord = {
121
- _$data: {
122
- firstname: 'Wolfram',
123
- lastname: 'Hempel',
124
- address: {
125
- street: 'currentStreet',
126
- },
127
- pastAddresses: [
128
- { street: 'firststreet', postCode: 1001 },
129
- { street: 'secondstreet', postCode: 2002 },
130
- ],
131
- 1234: 'integer index',
132
- },
133
- }
134
-
135
- it('retrieves simple paths', () => {
136
- expect(jsonPath.get(testRecord._$data, 'firstname')).toBe('Wolfram')
137
- })
138
-
139
- it('retrieves nested paths', () => {
140
- expect(jsonPath.get(testRecord._$data, 'address.street')).toBe('currentStreet')
141
- })
142
-
143
- it('retrieves array entries', () => {
144
- expect(jsonPath.get(testRecord._$data, 'pastAddresses[1]')).toEqual({
145
- street: 'secondstreet',
146
- postCode: 2002,
147
- })
148
- })
149
-
150
- it('retrieves other array entries', () => {
151
- expect(jsonPath.get(testRecord._$data, 'pastAddresses[0]')).toEqual({
152
- street: 'firststreet',
153
- postCode: 1001,
154
- })
155
- })
156
-
157
- it('retrieves values from objects within arrays', () => {
158
- expect(jsonPath.get(testRecord._$data, 'pastAddresses[0].postCode')).toBe(1001)
159
- })
160
-
161
- it('handles whitespace', () => {
162
- expect(jsonPath.get(testRecord._$data, ' pastAddresses[ 1 ].postCode ')).toBe(2002)
163
- })
164
-
165
- it('handles integers', () => {
166
- expect(jsonPath.get(testRecord._$data, 1234)).toBe('integer index')
167
- })
168
-
169
- it('returns undefined for non existing keys', () => {
170
- expect(jsonPath.get(testRecord._$data, 'doesNotExist')).toBe(undefined)
171
- })
172
-
173
- it('returns undefined for non existing nested keys', () => {
174
- expect(jsonPath.get(testRecord._$data, 'address.number')).toBe(undefined)
175
- })
176
-
177
- it('returns undefined for existing array indices', () => {
178
- expect(jsonPath.get(testRecord._$data, 'pastAddresses[3]')).toBe(undefined)
179
- })
180
-
181
- it('returns undefined for negative array indices', () => {
182
- expect(jsonPath.get(testRecord._$data, 'pastAddresses[-1]')).toBe(undefined)
183
- })
184
-
185
- it('detects changes', () => {
186
- expect(jsonPath.get(testRecord._$data, 'firstname')).toBe('Wolfram')
187
- testRecord._$data.firstname = 'Egon'
188
- expect(jsonPath.get(testRecord._$data, 'firstname')).toBe('Egon')
189
- })
190
-
191
- it('detects changes to arrays', () => {
192
- expect(jsonPath.get(testRecord._$data, 'pastAddresses[1].street')).toBe('secondstreet')
193
- testRecord._$data.pastAddresses.pop()
194
- expect(jsonPath.get(testRecord._$data, 'pastAddresses[1].street')).toBe(undefined)
195
- })
196
- })
197
-
198
- describe('objects are created from paths and their value is set correctly', () => {
199
- it('sets simple values', () => {
200
- const record = { _$data: {} }
201
- record._$data = jsonPath.set(record._$data, 'firstname', 'Wolfram')
202
- expect(jsonPath.get(record._$data, 'firstname')).toBe('Wolfram')
203
- expect(record._$data).toEqual({ firstname: 'Wolfram' })
204
- })
205
-
206
- it('sets values for nested objects', () => {
207
- const record = { _$data: {} }
208
- record._$data = jsonPath.set(record._$data, 'adress.street', 'someStreet')
209
- expect(jsonPath.get(record._$data, 'adress.street')).toBe('someStreet')
210
- expect(record._$data).toEqual({
211
- adress: {
212
- street: 'someStreet',
213
- },
214
- })
215
- })
216
-
217
- it('sets values for arrays', () => {
218
- const record = { _$data: {} }
219
- record._$data = jsonPath.set(record._$data, 'pastAddresses[1].street', 'someStreet')
220
- expect(jsonPath.get(record._$data, 'pastAddresses[1].street')).toBe('someStreet')
221
- expect(record._$data).toEqual({
222
- pastAddresses: [
223
- undefined,
224
- {
225
- street: 'someStreet',
226
- },
227
- ],
228
- })
229
- })
230
-
231
- it('sets values for null values', () => {
232
- const record = {
233
- _$data: {
234
- job: null,
235
- joinedAt: 1480020987915,
236
- },
237
- }
238
- const jobId = { id: 88 }
239
- record._$data = jsonPath.set(record._$data, 'job', jobId, true)
240
- expect(jsonPath.get(record._$data, 'job.id')).toBe(88)
241
- expect(record._$data).toEqual({
242
- job: { id: 88 },
243
- joinedAt: 1480020987915,
244
- })
245
- })
246
-
247
- it('extends existing objects', () => {
248
- const record = { _$data: { firstname: 'Wolfram' } }
249
- record._$data = jsonPath.set(record._$data, 'lastname', 'Hempel')
250
- expect(jsonPath.get(record._$data, 'lastname')).toBe('Hempel')
251
- expect(record._$data).toEqual({
252
- firstname: 'Wolfram',
253
- lastname: 'Hempel',
254
- })
255
- })
256
-
257
- it('even when the path is not NaNish and could be interpreted as a base 16 number', () => {
258
- let record = {}
259
- const pathName = '0x02335'
260
- record = jsonPath.set(record, pathName, 'value')
261
- expect(record[0]).toBe(undefined)
262
- expect(record[pathName]).toBe('value')
263
- expect(jsonPath.get(record, pathName)).toBe('value')
264
- expect(record[pathName]).toBe('value')
265
- })
266
-
267
- it('extends existing arrays', () => {
268
- const record = {
269
- _$data: {
270
- firstname: 'Wolfram',
271
- animals: ['Bear', 'Cow', 'Ostrich'],
272
- },
273
- }
274
- record._$data = jsonPath.set(record._$data, 'animals[ 1 ]', 'Emu')
275
- expect(jsonPath.get(record._$data, 'animals[ 1 ]')).toBe('Emu')
276
- expect(record._$data).toEqual({
277
- firstname: 'Wolfram',
278
- animals: ['Bear', 'Emu', 'Ostrich'],
279
- })
280
- })
281
- })
282
-
283
- describe('plain JSON', () => {
284
- it('converts into plain JSON', () => {
285
- const time = new Date()
286
- const x = {
287
- a: time,
288
- b: undefined,
289
- c: [undefined],
290
- d: NaN,
291
- e: Infinity,
292
- g: {
293
- a: time,
294
- },
295
- }
296
- const res = jsonPath.set({ a: 1 }, null, x)
297
- expect(res).toEqual({
298
- a: time.toISOString(),
299
- c: [null],
300
- d: null,
301
- e: null,
302
- g: {
303
- a: time.toISOString(),
304
- },
305
- })
306
- expect(res.hasOwnProperty('b')).toEqual(false)
307
- })
308
-
309
- it('undefined is removed from src', () => {
310
- const y = jsonPath.EMPTY
311
- const res = jsonPath.set(y, null, {
312
- b: undefined,
313
- })
314
- expect(Object.keys(res).length).toEqual(0)
315
- expect(res).toBe(y)
316
- })
317
-
318
- it('empty is EMPTY', () => {
319
- const y = {
320
- b: 1,
321
- }
322
- const res = jsonPath.set(y, null, {
323
- b: undefined,
324
- })
325
- expect(Object.keys(res).length).toEqual(0)
326
- expect(res).toBe(jsonPath.EMPTY)
327
- expect(res).toEqual({})
328
- })
329
-
330
- it('stringify date', () => {
331
- const y = {
332
- time: {},
333
- }
334
- const date = new Date()
335
- const res = jsonPath.set(
336
- y,
337
- null,
338
- {
339
- date,
340
- },
341
- false
342
- )
343
- expect(res.date).toEqual(date.toISOString())
344
- })
345
-
346
- it('remove property on undefined', () => {
347
- const y = {
348
- time: {},
349
- }
350
- const res = jsonPath.set(y, 'time', undefined)
351
- expect(Object.keys(res)).toEqual([])
352
- })
353
- })
@@ -1,199 +0,0 @@
1
- const utils = require('../utils/utils')
2
- const PARTS_REG_EXP = /([^.[\]\s]+)/g
3
-
4
- const cache = new Map()
5
- const EMPTY = utils.deepFreeze({})
6
-
7
- const EMPTY_OBJ = EMPTY
8
- const EMPTY_ARR = utils.deepFreeze([])
9
-
10
- function get(data, path) {
11
- data = data || EMPTY
12
-
13
- if (!path) {
14
- return data
15
- }
16
-
17
- const tokens = tokenize(path)
18
-
19
- for (let i = 0; i < tokens.length; i++) {
20
- if (data == null || typeof data !== 'object') {
21
- return undefined
22
- }
23
- data = data[tokens[i]]
24
- }
25
-
26
- return data
27
- }
28
-
29
- function parse(value) {
30
- if (value === '{}') {
31
- return EMPTY_OBJ
32
- } else if (value === '[]') {
33
- return EMPTY_ARR
34
- } else {
35
- return JSON.parse(value)
36
- }
37
- }
38
-
39
- function stringify(value) {
40
- if (value === EMPTY_OBJ) {
41
- return '{}'
42
- } else if (value === EMPTY_ARR) {
43
- return '[]'
44
- } else {
45
- return JSON.stringify(value)
46
- }
47
- }
48
-
49
- function set(data, path, value, isPlainJSON = false) {
50
- data = data || EMPTY
51
-
52
- if (!path) {
53
- return patch(data, value, isPlainJSON)
54
- }
55
-
56
- const oldValue = get(data, path)
57
- const newValue = patch(oldValue, value, isPlainJSON)
58
-
59
- if (newValue === oldValue) {
60
- return data
61
- }
62
-
63
- const result = data ? utils.shallowCopy(data) : {}
64
-
65
- const tokens = tokenize(path)
66
-
67
- let node = result
68
- for (let i = 0; i < tokens.length; i++) {
69
- const token = tokens[i]
70
- if (i === tokens.length - 1) {
71
- if (newValue !== undefined) {
72
- node[token] = newValue
73
- } else {
74
- delete node[token]
75
- }
76
- } else if (node[token] != null && typeof node[token] === 'object') {
77
- node = node[token] = utils.shallowCopy(node[token])
78
- } else if (tokens[i + 1] && !isNaN(tokens[i + 1])) {
79
- node = node[token] = []
80
- } else {
81
- node = node[token] = {}
82
- }
83
- }
84
-
85
- return result
86
- }
87
-
88
- function jsonClone(o) {
89
- if (o == null || typeof o === 'string') {
90
- return o
91
- }
92
-
93
- if (Array.isArray(o) && o.length === 0) {
94
- return EMPTY_ARR
95
- } else if (utils.isPlainObject(o) && Object.keys(o).length === 0) {
96
- return EMPTY_OBJ
97
- }
98
-
99
- return JSON.parse(JSON.stringify(o))
100
- }
101
-
102
- function patch(oldValue, newValue, isPlainJSON) {
103
- if (oldValue === newValue) {
104
- return oldValue
105
- } else if (oldValue === null || newValue === null) {
106
- return isPlainJSON ? newValue : jsonClone(newValue)
107
- } else if (Array.isArray(oldValue) && Array.isArray(newValue)) {
108
- if (newValue.length === 0) {
109
- return EMPTY_ARR
110
- }
111
-
112
- let arr = newValue.length === oldValue.length ? null : []
113
- for (let i = 0; i < newValue.length; i++) {
114
- const value = patch(oldValue[i], newValue[i], isPlainJSON)
115
-
116
- if (!arr) {
117
- if (value === oldValue[i]) {
118
- continue
119
- }
120
- arr = []
121
- for (let j = 0; j < i; ++j) {
122
- arr[j] = oldValue[j]
123
- }
124
- }
125
- // JSON: compat, undefined in array is null
126
- arr[i] = value === undefined ? null : value
127
- }
128
-
129
- return arr || oldValue
130
- } else if (utils.isPlainObject(oldValue, true) && utils.isPlainObject(newValue, isPlainJSON)) {
131
- const newKeys = Object.keys(newValue).filter((key) => newValue[key] !== undefined)
132
- const oldKeys = Object.keys(oldValue)
133
-
134
- if (newKeys.length === 0) {
135
- return oldKeys.length === 0 ? oldValue : EMPTY
136
- }
137
-
138
- let obj = newKeys.length === oldKeys.length ? null : {}
139
- for (let i = 0; i < newKeys.length; ++i) {
140
- const key = newKeys[i]
141
- const val = patch(oldValue[key], newValue[key], isPlainJSON)
142
-
143
- if (!obj) {
144
- if (val === oldValue[key] && key === oldKeys[i]) {
145
- continue
146
- }
147
- obj = {}
148
- for (let j = 0; j < i; j++) {
149
- obj[newKeys[j]] = oldValue[newKeys[j]]
150
- }
151
- }
152
-
153
- if (val !== undefined) {
154
- obj[key] = val
155
- }
156
- }
157
-
158
- return obj || oldValue
159
- } else {
160
- return isPlainJSON ? newValue : jsonClone(newValue)
161
- }
162
- }
163
-
164
- function tokenize(path) {
165
- if (!path) {
166
- return []
167
- }
168
-
169
- if (Array.isArray(path)) {
170
- return path
171
- }
172
-
173
- let parts = cache.get(path)
174
-
175
- if (parts) {
176
- return parts
177
- }
178
-
179
- parts = path && String(path) !== 'undefined' ? String(path).match(PARTS_REG_EXP) : []
180
-
181
- if (!parts) {
182
- throw new Error('invalid path ' + path)
183
- }
184
-
185
- cache.set(path, parts)
186
-
187
- return parts
188
- }
189
-
190
- module.exports = {
191
- EMPTY,
192
- EMPTY_OBJ,
193
- EMPTY_ARR,
194
- parse,
195
- stringify,
196
- get,
197
- set,
198
- jsonClone,
199
- }