@nxtedition/deepstream.io-client-js 24.3.1 → 24.3.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 +3 -1
- package/src/client.js +10 -10
- package/src/constants/constants.js +89 -89
- package/src/default-options.js +1 -1
- package/src/event/event-handler.js +8 -8
- package/src/message/connection.js +18 -19
- package/src/message/message-builder.js +26 -11
- package/src/message/message-parser.js +2 -2
- package/src/record/record-handler.js +21 -14
- package/src/record/record.js +12 -24
- package/src/rpc/rpc-handler.js +6 -6
- package/src/rpc/rpc-response.js +3 -3
- package/src/utils/fixed-queue.js +1 -3
- package/src/utils/multicast-listener.js +3 -3
- package/src/utils/timers.js +14 -17
- package/src/utils/unicast-listener.js +4 -4
- package/src/utils/utils.js +18 -21
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/deepstream.io-client-js",
|
|
3
|
-
"version": "24.3.
|
|
3
|
+
"version": "24.3.3",
|
|
4
4
|
"description": "the javascript client for deepstream.io",
|
|
5
5
|
"homepage": "http://deepstream.io",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"bugs": {
|
|
7
8
|
"url": "https://github.com/deepstreamIO/deepstream.io-client-js/issues"
|
|
8
9
|
},
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
"invariant": "^2.2.4",
|
|
65
66
|
"lodash.clonedeep": "^4.5.0",
|
|
66
67
|
"utf-8-validate": "^6.0.3",
|
|
68
|
+
"varint": "^6.0.0",
|
|
67
69
|
"ws": "^8.13.0",
|
|
68
70
|
"xuid": "^4.1.2",
|
|
69
71
|
"xxhash-wasm": "^1.0.2"
|
package/src/client.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import * as C from './constants/constants.js'
|
|
2
|
+
import Emitter from 'component-emitter2'
|
|
3
|
+
import Connection from './message/connection.js'
|
|
4
|
+
import EventHandler from './event/event-handler.js'
|
|
5
|
+
import RpcHandler from './rpc/rpc-handler.js'
|
|
6
|
+
import RecordHandler from './record/record-handler.js'
|
|
7
|
+
import defaultOptions from './default-options.js'
|
|
8
|
+
import xuid from 'xuid'
|
|
9
|
+
import * as utils from './utils/utils.js'
|
|
10
10
|
|
|
11
11
|
const Client = function (url, options) {
|
|
12
12
|
this._url = url
|
|
@@ -135,4 +135,4 @@ Client.prototype.isSameOrNewer = utils.isSameOrNewer
|
|
|
135
135
|
Client.prototype.CONSTANTS = C
|
|
136
136
|
createDeepstream.CONSTANTS = C
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
export default createDeepstream
|
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
|
|
1
|
+
export const CONNECTION_STATE = {}
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
CONNECTION_STATE.CLOSED = 'CLOSED'
|
|
4
|
+
CONNECTION_STATE.AWAITING_CONNECTION = 'AWAITING_CONNECTION'
|
|
5
|
+
CONNECTION_STATE.CHALLENGING = 'CHALLENGING'
|
|
6
|
+
CONNECTION_STATE.AWAITING_AUTHENTICATION = 'AWAITING_AUTHENTICATION'
|
|
7
|
+
CONNECTION_STATE.AUTHENTICATING = 'AUTHENTICATING'
|
|
8
|
+
CONNECTION_STATE.OPEN = 'OPEN'
|
|
9
|
+
CONNECTION_STATE.ERROR = 'ERROR'
|
|
10
|
+
CONNECTION_STATE.RECONNECTING = 'RECONNECTING'
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
export const RECORD_STATE = {}
|
|
13
|
+
RECORD_STATE.VOID = 0
|
|
14
|
+
RECORD_STATE.CLIENT = 1
|
|
15
|
+
RECORD_STATE.SERVER = 2
|
|
16
|
+
RECORD_STATE.STALE = 3
|
|
17
|
+
RECORD_STATE.PROVIDER = 4
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
for (const [key, val] of Object.entries(
|
|
21
|
-
|
|
19
|
+
export const RECORD_STATE_NAME = []
|
|
20
|
+
for (const [key, val] of Object.entries(RECORD_STATE)) {
|
|
21
|
+
RECORD_STATE_NAME[val] = key
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
export const MESSAGE_SEPERATOR = String.fromCharCode(30) // ASCII Record Seperator 1E
|
|
25
|
+
export const MESSAGE_PART_SEPERATOR = String.fromCharCode(31) // ASCII Unit Separator 1F
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
export const TYPES = {}
|
|
28
|
+
TYPES.STRING = 'S'
|
|
29
|
+
TYPES.OBJECT = 'O'
|
|
30
|
+
TYPES.NUMBER = 'N'
|
|
31
|
+
TYPES.NULL = 'L'
|
|
32
|
+
TYPES.TRUE = 'T'
|
|
33
|
+
TYPES.FALSE = 'F'
|
|
34
|
+
TYPES.UNDEFINED = 'U'
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
export const TOPIC = {}
|
|
37
|
+
TOPIC.CONNECTION = 'C'
|
|
38
|
+
TOPIC.AUTH = 'A'
|
|
39
|
+
TOPIC.ERROR = 'X'
|
|
40
|
+
TOPIC.EVENT = 'E'
|
|
41
|
+
TOPIC.RECORD = 'R'
|
|
42
|
+
TOPIC.RPC = 'P'
|
|
43
|
+
TOPIC.PRIVATE = 'PRIVATE/'
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
45
|
+
export const EVENT = {}
|
|
46
|
+
EVENT.CONNECTION_ERROR = 'connectionError'
|
|
47
|
+
EVENT.CONNECTION_STATE_CHANGED = 'connectionStateChanged'
|
|
48
|
+
EVENT.CONNECTED = 'connected'
|
|
49
|
+
EVENT.MAX_RECONNECTION_ATTEMPTS_REACHED = 'MAX_RECONNECTION_ATTEMPTS_REACHED'
|
|
50
|
+
EVENT.CONNECTION_AUTHENTICATION_TIMEOUT = 'CONNECTION_AUTHENTICATION_TIMEOUT'
|
|
51
|
+
EVENT.NO_RPC_PROVIDER = 'NO_RPC_PROVIDER'
|
|
52
|
+
EVENT.RPC_ERROR = 'RPC_ERROR'
|
|
53
|
+
EVENT.TIMEOUT = 'TIMEOUT'
|
|
54
|
+
EVENT.UNSOLICITED_MESSAGE = 'UNSOLICITED_MESSAGE'
|
|
55
|
+
EVENT.MESSAGE_DENIED = 'MESSAGE_DENIED'
|
|
56
|
+
EVENT.NOT_CONNECTED = 'NOT_CONNECTED'
|
|
57
|
+
EVENT.MESSAGE_PARSE_ERROR = 'MESSAGE_PARSE_ERROR'
|
|
58
|
+
EVENT.NOT_AUTHENTICATED = 'NOT_AUTHENTICATED'
|
|
59
|
+
EVENT.MESSAGE_PERMISSION_ERROR = 'MESSAGE_PERMISSION_ERROR'
|
|
60
|
+
EVENT.LISTENER_EXISTS = 'LISTENER_EXISTS'
|
|
61
|
+
EVENT.PROVIDER_ERROR = 'PROVIDER_ERROR'
|
|
62
|
+
EVENT.CACHE_ERROR = 'CACHE_ERROR'
|
|
63
|
+
EVENT.UPDATE_ERROR = 'UPDATE_ERROR'
|
|
64
|
+
EVENT.USER_ERROR = 'USER_ERROR'
|
|
65
|
+
EVENT.REF_ERROR = 'REF_ERROR'
|
|
66
|
+
EVENT.PROVIDER_EXISTS = 'PROVIDER_EXISTS'
|
|
67
|
+
EVENT.NOT_LISTENING = 'NOT_LISTENING'
|
|
68
|
+
EVENT.NOT_PROVIDING = 'NOT_PROVIDING'
|
|
69
|
+
EVENT.LISTENER_ERROR = 'LISTENER_ERROR'
|
|
70
|
+
EVENT.TOO_MANY_AUTH_ATTEMPTS = 'TOO_MANY_AUTH_ATTEMPTS'
|
|
71
|
+
EVENT.IS_CLOSED = 'IS_CLOSED'
|
|
72
|
+
EVENT.RECORD_NOT_FOUND = 'RECORD_NOT_FOUND'
|
|
73
|
+
EVENT.NOT_SUBSCRIBED = 'NOT_SUBSCRIBED'
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
75
|
+
export const ACTIONS = {}
|
|
76
|
+
ACTIONS.PING = 'PI'
|
|
77
|
+
ACTIONS.PONG = 'PO'
|
|
78
|
+
ACTIONS.ACK = 'A'
|
|
79
|
+
ACTIONS.REDIRECT = 'RED'
|
|
80
|
+
ACTIONS.CHALLENGE = 'CH'
|
|
81
|
+
ACTIONS.CHALLENGE_RESPONSE = 'CHR'
|
|
82
|
+
ACTIONS.READ = 'R'
|
|
83
|
+
ACTIONS.UPDATE = 'U'
|
|
84
|
+
ACTIONS.SUBSCRIBE = 'S'
|
|
85
|
+
ACTIONS.SYNC = 'SY'
|
|
86
|
+
ACTIONS.UNSUBSCRIBE = 'US'
|
|
87
|
+
ACTIONS.SUBSCRIPTION_FOR_PATTERN_FOUND = 'SP'
|
|
88
|
+
ACTIONS.SUBSCRIPTION_FOR_PATTERN_REMOVED = 'SR'
|
|
89
|
+
ACTIONS.SUBSCRIPTION_HAS_PROVIDER = 'SH'
|
|
90
|
+
ACTIONS.LISTEN = 'L'
|
|
91
|
+
ACTIONS.UNLISTEN = 'UL'
|
|
92
|
+
ACTIONS.LISTEN_ACCEPT = 'LA'
|
|
93
|
+
ACTIONS.LISTEN_REJECT = 'LR'
|
|
94
|
+
ACTIONS.EVENT = 'EVT'
|
|
95
|
+
ACTIONS.ERROR = 'E'
|
|
96
|
+
ACTIONS.REQUEST = 'REQ'
|
|
97
|
+
ACTIONS.RESPONSE = 'RES'
|
|
98
|
+
ACTIONS.REJECTION = 'REJ'
|
package/src/default-options.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import * as C from '../constants/constants.js'
|
|
2
|
+
import * as messageBuilder from '../message/message-builder.js'
|
|
3
|
+
import messageParser from '../message/message-parser.js'
|
|
4
|
+
import MulticastListener from '../utils/multicast-listener.js'
|
|
5
|
+
import UnicastListener from '../utils/unicast-listener.js'
|
|
6
|
+
import EventEmitter from 'component-emitter2'
|
|
7
|
+
import rxjs from 'rxjs'
|
|
8
8
|
|
|
9
9
|
const EventHandler = function (options, connection, client) {
|
|
10
10
|
this._options = options
|
|
@@ -164,4 +164,4 @@ EventHandler.prototype._onConnectionStateChange = function (connected) {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
export default EventHandler
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import * as utils from '../utils/utils.js'
|
|
2
|
+
import messageParser from './message-parser.js'
|
|
3
|
+
import * as messageBuilder from './message-builder.js'
|
|
4
|
+
import * as C from '../constants/constants.js'
|
|
5
|
+
import xxhash from 'xxhash-wasm'
|
|
6
|
+
import FixedQueue from '../utils/fixed-queue.js'
|
|
7
|
+
import Emitter from 'component-emitter2'
|
|
8
|
+
|
|
1
9
|
const BrowserWebSocket = globalThis.WebSocket || globalThis.MozWebSocket
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const messageBuilder = require('./message-builder')
|
|
6
|
-
const C = require('../constants/constants')
|
|
7
|
-
const pkg = require('../../package.json')
|
|
8
|
-
const xxhash = require('xxhash-wasm')
|
|
9
|
-
const FixedQueue = require('../utils/fixed-queue')
|
|
10
|
-
const Emitter = require('component-emitter2')
|
|
10
|
+
const NodeWebSocket = utils.isNode ? await import('ws').then((x) => x.default) : null
|
|
11
|
+
|
|
12
|
+
const HASHER = await xxhash()
|
|
11
13
|
|
|
12
14
|
const Connection = function (client, url, options) {
|
|
13
15
|
this._client = client
|
|
@@ -30,7 +32,6 @@ const Connection = function (client, url, options) {
|
|
|
30
32
|
this._recvQueue = new FixedQueue()
|
|
31
33
|
this._reconnectTimeout = null
|
|
32
34
|
this._reconnectionAttempt = 0
|
|
33
|
-
this._endpoint = null
|
|
34
35
|
|
|
35
36
|
this._processingRecv = false
|
|
36
37
|
this._recvMessages = this._recvMessages.bind(this)
|
|
@@ -39,11 +40,9 @@ const Connection = function (client, url, options) {
|
|
|
39
40
|
|
|
40
41
|
this._state = C.CONNECTION_STATE.CLOSED
|
|
41
42
|
|
|
42
|
-
this.hasher =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this._createEndpoint()
|
|
46
|
-
})
|
|
43
|
+
this.hasher = HASHER
|
|
44
|
+
|
|
45
|
+
this._createEndpoint()
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
Emitter(Connection.prototype)
|
|
@@ -152,8 +151,8 @@ Connection.prototype.send = function (message) {
|
|
|
152
151
|
Connection.prototype._submit = function (message) {
|
|
153
152
|
const { maxPacketSize } = this._options
|
|
154
153
|
|
|
155
|
-
if (message.
|
|
156
|
-
const err = new Error(`Packet to big: ${message.
|
|
154
|
+
if (message.byteLength > maxPacketSize) {
|
|
155
|
+
const err = new Error(`Packet to big: ${message.byteLength} > ${maxPacketSize}`)
|
|
157
156
|
this._client._$onError(C.TOPIC.CONNECTION, C.EVENT.CONNECTION_ERROR, err)
|
|
158
157
|
return false
|
|
159
158
|
} else if (this._endpoint.readyState === this._endpoint.OPEN) {
|
|
@@ -171,7 +170,7 @@ Connection.prototype._sendAuthParams = function () {
|
|
|
171
170
|
this._setState(C.CONNECTION_STATE.AUTHENTICATING)
|
|
172
171
|
const authMessage = messageBuilder.getMsg(C.TOPIC.AUTH, C.ACTIONS.REQUEST, [
|
|
173
172
|
this._authParams,
|
|
174
|
-
|
|
173
|
+
'24.3.1', // TODO (fix): How to read from package.json?
|
|
175
174
|
utils.isNode
|
|
176
175
|
? `Node/${process.version}`
|
|
177
176
|
: globalThis.navigator && globalThis.navigator.userAgent,
|
|
@@ -365,4 +364,4 @@ Connection.prototype._clearReconnect = function () {
|
|
|
365
364
|
this._reconnectionAttempt = 0
|
|
366
365
|
}
|
|
367
366
|
|
|
368
|
-
|
|
367
|
+
export default Connection
|
|
@@ -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
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
module.exports.getMsg = function (topic, action, data) {
|
|
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 @@ module.exports.getMsg = function (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,37 +50,48 @@ module.exports.getMsg = function (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
|
-
|
|
63
|
+
len = res.written
|
|
58
64
|
} else if (type === 'bigint') {
|
|
59
65
|
poolBuffer[poolOffset++] = 31
|
|
60
66
|
poolView.setBigUint64(poolOffset, data[i], false)
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
return
|
|
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
|
|
|
79
|
-
|
|
94
|
+
export function typed(value) {
|
|
80
95
|
const type = typeof value
|
|
81
96
|
|
|
82
97
|
if (type === 'string') {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import * as C from '../constants/constants.js'
|
|
2
2
|
|
|
3
3
|
const MessageParser = function () {
|
|
4
4
|
this._actions = this._getActions()
|
|
@@ -88,4 +88,4 @@ MessageParser.prototype.parseMessage = function (message, client, result) {
|
|
|
88
88
|
result.data = parts.splice(2)
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
export default new MessageParser()
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import Record from './record.js'
|
|
2
|
+
import MulticastListener from '../utils/multicast-listener.js'
|
|
3
|
+
import UnicastListener from '../utils/unicast-listener.js'
|
|
4
|
+
import * as C from '../constants/constants.js'
|
|
5
|
+
import rxjs from 'rxjs'
|
|
6
|
+
import invariant from 'invariant'
|
|
7
|
+
import EventEmitter from 'component-emitter2'
|
|
8
|
+
import jsonPath from '@nxtedition/json-path'
|
|
9
|
+
import * as utils from '../utils/utils.js'
|
|
10
|
+
import rx from 'rxjs/operators'
|
|
11
|
+
import xuid from 'xuid'
|
|
12
|
+
import * as timers from '../utils/timers.js'
|
|
13
13
|
|
|
14
14
|
const kEmpty = Symbol('kEmpty')
|
|
15
15
|
|
|
@@ -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)
|
|
@@ -650,4 +657,4 @@ class RecordHandler {
|
|
|
650
657
|
}
|
|
651
658
|
}
|
|
652
659
|
|
|
653
|
-
|
|
660
|
+
export default RecordHandler
|
package/src/record/record.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import jsonPath from '@nxtedition/json-path'
|
|
2
|
+
import * as utils from '../utils/utils.js'
|
|
3
|
+
import * as C from '../constants/constants.js'
|
|
4
|
+
import messageParser from '../message/message-parser.js'
|
|
5
|
+
import xuid from 'xuid'
|
|
6
|
+
import invariant from 'invariant'
|
|
7
|
+
import cloneDeep from 'lodash.clonedeep'
|
|
8
|
+
import * as timers from '../utils/timers.js'
|
|
9
9
|
|
|
10
|
-
const encoder = new TextEncoder()
|
|
10
|
+
// const encoder = new TextEncoder()
|
|
11
11
|
|
|
12
12
|
class Record {
|
|
13
13
|
static STATE = C.RECORD_STATE
|
|
14
14
|
|
|
15
|
-
constructor(name, handler) {
|
|
15
|
+
constructor(key, name, handler) {
|
|
16
16
|
const connection = handler._connection
|
|
17
17
|
|
|
18
18
|
this._handler = handler
|
|
19
19
|
|
|
20
20
|
this._name = name
|
|
21
|
-
this._key =
|
|
21
|
+
this._key = key
|
|
22
22
|
this._version = ''
|
|
23
23
|
this._data = jsonPath.EMPTY
|
|
24
24
|
this._state = C.RECORD_STATE.VOID
|
|
@@ -28,7 +28,6 @@ class Record {
|
|
|
28
28
|
|
|
29
29
|
/** @type Map? */ this._updating = null
|
|
30
30
|
/** @type Array? */ this._patching = null
|
|
31
|
-
this._hashName()
|
|
32
31
|
this._subscribed = connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [
|
|
33
32
|
this._name,
|
|
34
33
|
this._key,
|
|
@@ -316,16 +315,6 @@ class Record {
|
|
|
316
315
|
})
|
|
317
316
|
}
|
|
318
317
|
|
|
319
|
-
_hashName() {
|
|
320
|
-
// TODO (fix): It's hacky that hasher is not always available...
|
|
321
|
-
this._key =
|
|
322
|
-
typeof this._key === 'bigint'
|
|
323
|
-
? this._key
|
|
324
|
-
: this._name.length <= 8 && encoder.encode(this._name).byteLength === 8
|
|
325
|
-
? this._name
|
|
326
|
-
: this._handler.connection.hasher?.h64(this._name)
|
|
327
|
-
}
|
|
328
|
-
|
|
329
318
|
_$onMessage(message) {
|
|
330
319
|
if (message.action === C.ACTIONS.UPDATE) {
|
|
331
320
|
this._onUpdate(message.data)
|
|
@@ -342,7 +331,6 @@ class Record {
|
|
|
342
331
|
const connection = this._handler._connection
|
|
343
332
|
|
|
344
333
|
if (connected) {
|
|
345
|
-
this._hashName()
|
|
346
334
|
this._subscribed =
|
|
347
335
|
this._refs > 0 &&
|
|
348
336
|
connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [this._name, this._key])
|
|
@@ -593,4 +581,4 @@ Object.defineProperty(Record.prototype, 'hasProvider', {
|
|
|
593
581
|
},
|
|
594
582
|
})
|
|
595
583
|
|
|
596
|
-
|
|
584
|
+
export default Record
|
package/src/rpc/rpc-handler.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import * as C from '../constants/constants.js'
|
|
2
|
+
import RpcResponse from './rpc-response.js'
|
|
3
|
+
import messageParser from '../message/message-parser.js'
|
|
4
|
+
import * as messageBuilder from '../message/message-builder.js'
|
|
5
|
+
import xuid from 'xuid'
|
|
6
6
|
|
|
7
7
|
const RpcHandler = function (options, connection, client) {
|
|
8
8
|
this._options = options
|
|
@@ -175,4 +175,4 @@ RpcHandler.prototype._onConnectionStateChange = function (connected) {
|
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
export default RpcHandler
|
package/src/rpc/rpc-response.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as C from '../constants/constants.js'
|
|
2
|
+
import * as messageBuilder from '../message/message-builder.js'
|
|
3
3
|
|
|
4
4
|
const RpcResponse = function (connection, name, id) {
|
|
5
5
|
this._connection = connection
|
|
@@ -44,4 +44,4 @@ RpcResponse.prototype.send = function (data) {
|
|
|
44
44
|
])
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
export default RpcResponse
|
package/src/utils/fixed-queue.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two.
|
|
4
2
|
const kSize = 2048
|
|
5
3
|
const kMask = kSize - 1
|
|
@@ -82,7 +80,7 @@ class FixedCircularBuffer {
|
|
|
82
80
|
}
|
|
83
81
|
}
|
|
84
82
|
|
|
85
|
-
|
|
83
|
+
export default class FixedQueue {
|
|
86
84
|
constructor() {
|
|
87
85
|
this.head = this.tail = new FixedCircularBuffer()
|
|
88
86
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as C from '../constants/constants.js'
|
|
2
|
+
import rxjs from 'rxjs'
|
|
3
3
|
|
|
4
4
|
class Listener {
|
|
5
5
|
constructor(topic, pattern, callback, handler, { recursive = false, stringify = null } = {}) {
|
|
@@ -229,4 +229,4 @@ class Listener {
|
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
|
|
232
|
+
export default Listener
|
package/src/utils/timers.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
// undici timers
|
|
2
|
-
|
|
3
|
-
'use strict'
|
|
4
|
-
|
|
5
1
|
let fastNow = Date.now()
|
|
6
2
|
let fastNowTimeout
|
|
7
3
|
|
|
@@ -44,8 +40,8 @@ function refreshTimeout() {
|
|
|
44
40
|
if (fastNowTimeout && fastNowTimeout.refresh) {
|
|
45
41
|
fastNowTimeout.refresh()
|
|
46
42
|
} else {
|
|
47
|
-
clearTimeout(fastNowTimeout)
|
|
48
|
-
fastNowTimeout = setTimeout(onTimeout, 1e3)
|
|
43
|
+
globalThis.clearTimeout(fastNowTimeout)
|
|
44
|
+
fastNowTimeout = globalThis.setTimeout(onTimeout, 1e3)
|
|
49
45
|
if (fastNowTimeout.unref) {
|
|
50
46
|
fastNowTimeout.unref()
|
|
51
47
|
}
|
|
@@ -83,15 +79,16 @@ class Timeout {
|
|
|
83
79
|
}
|
|
84
80
|
}
|
|
85
81
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
82
|
+
export function setTimeout(callback, delay, opaque) {
|
|
83
|
+
return delay < 1e3
|
|
84
|
+
? globalThis.setTimeout(callback, delay, opaque)
|
|
85
|
+
: new Timeout(callback, delay, opaque)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function clearTimeout(timeout) {
|
|
89
|
+
if (timeout instanceof Timeout) {
|
|
90
|
+
timeout.clear()
|
|
91
|
+
} else {
|
|
92
|
+
globalThis.clearTimeout(timeout)
|
|
93
|
+
}
|
|
97
94
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import * as C from '../constants/constants.js'
|
|
2
|
+
import rx from 'rxjs/operators'
|
|
3
|
+
import rxjs from 'rxjs'
|
|
4
4
|
|
|
5
5
|
const PIPE = rxjs.pipe(
|
|
6
6
|
rx.map((value) => {
|
|
@@ -127,4 +127,4 @@ class Listener {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
export default Listener
|
package/src/utils/utils.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
const NODE_ENV = typeof process !== 'undefined' && process.env && process.env.NODE_ENV
|
|
2
|
-
const isNode = typeof process !== 'undefined' && process.toString() === '[object process]'
|
|
3
|
-
const isProduction = NODE_ENV === 'production'
|
|
2
|
+
export const isNode = typeof process !== 'undefined' && process.toString() === '[object process]'
|
|
3
|
+
export const isProduction = NODE_ENV === 'production'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
module.exports.isProduction = isProduction
|
|
7
|
-
|
|
8
|
-
module.exports.deepFreeze = function (o) {
|
|
5
|
+
export function deepFreeze(o) {
|
|
9
6
|
if (isProduction) {
|
|
10
7
|
return o
|
|
11
8
|
}
|
|
@@ -16,12 +13,12 @@ module.exports.deepFreeze = function (o) {
|
|
|
16
13
|
|
|
17
14
|
Object.freeze(o)
|
|
18
15
|
|
|
19
|
-
Object.getOwnPropertyNames(o).forEach((prop) =>
|
|
16
|
+
Object.getOwnPropertyNames(o).forEach((prop) => deepFreeze(o[prop]))
|
|
20
17
|
|
|
21
18
|
return o
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
export function splitRev(s) {
|
|
25
22
|
if (!s) {
|
|
26
23
|
return [-1, '00000000000000']
|
|
27
24
|
}
|
|
@@ -32,7 +29,7 @@ module.exports.splitRev = function (s) {
|
|
|
32
29
|
return [ver.charAt(0) === 'I' ? Infinity : parseInt(ver, 10), s.slice(i + 1)]
|
|
33
30
|
}
|
|
34
31
|
|
|
35
|
-
|
|
32
|
+
export function isPlainObject(value, isPlainJSON) {
|
|
36
33
|
if (isPlainJSON) {
|
|
37
34
|
return value && typeof value === 'object' && !Array.isArray(value)
|
|
38
35
|
}
|
|
@@ -53,13 +50,13 @@ module.exports.isPlainObject = function (value, isPlainJSON) {
|
|
|
53
50
|
return Object.getPrototypeOf(value) === proto
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
const [av, ar] =
|
|
58
|
-
const [bv, br] =
|
|
53
|
+
export function isSameOrNewer(a, b) {
|
|
54
|
+
const [av, ar] = splitRev(a)
|
|
55
|
+
const [bv, br] = splitRev(b)
|
|
59
56
|
return av > bv || (av === bv && ar >= br)
|
|
60
57
|
}
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
export function shallowCopy(obj) {
|
|
63
60
|
if (Array.isArray(obj)) {
|
|
64
61
|
return obj.slice(0)
|
|
65
62
|
}
|
|
@@ -72,15 +69,15 @@ module.exports.shallowCopy = function (obj) {
|
|
|
72
69
|
return copy
|
|
73
70
|
}
|
|
74
71
|
|
|
75
|
-
|
|
72
|
+
export function setTimeout(callback, timeoutDuration) {
|
|
76
73
|
if (timeoutDuration !== null) {
|
|
77
|
-
return setTimeout(callback, timeoutDuration)
|
|
74
|
+
return globalThis.setTimeout(callback, timeoutDuration)
|
|
78
75
|
} else {
|
|
79
76
|
return -1
|
|
80
77
|
}
|
|
81
78
|
}
|
|
82
79
|
|
|
83
|
-
|
|
80
|
+
export function setInterval(callback, intervalDuration) {
|
|
84
81
|
if (intervalDuration !== null) {
|
|
85
82
|
return setInterval(callback, intervalDuration)
|
|
86
83
|
} else {
|
|
@@ -88,7 +85,7 @@ module.exports.setInterval = function (callback, intervalDuration) {
|
|
|
88
85
|
}
|
|
89
86
|
}
|
|
90
87
|
|
|
91
|
-
|
|
88
|
+
export function compareRev(a, b) {
|
|
92
89
|
if (!a) {
|
|
93
90
|
return b ? -1 : 0
|
|
94
91
|
}
|
|
@@ -118,7 +115,7 @@ module.exports.compareRev = function compareRev(a, b) {
|
|
|
118
115
|
return 0
|
|
119
116
|
}
|
|
120
117
|
|
|
121
|
-
|
|
118
|
+
export class AbortError extends Error {
|
|
122
119
|
constructor() {
|
|
123
120
|
super('The operation was aborted')
|
|
124
121
|
this.code = 'ABORT_ERR'
|
|
@@ -130,7 +127,7 @@ function defaultSchedule(fn) {
|
|
|
130
127
|
setTimeout(fn, 0)
|
|
131
128
|
}
|
|
132
129
|
|
|
133
|
-
|
|
130
|
+
export const schedule = isNode ? defaultSchedule : window.requestIdleCallback
|
|
134
131
|
|
|
135
132
|
const abortSignals = new WeakMap()
|
|
136
133
|
const onAbort = function () {
|
|
@@ -142,7 +139,7 @@ const onAbort = function () {
|
|
|
142
139
|
}
|
|
143
140
|
}
|
|
144
141
|
|
|
145
|
-
|
|
142
|
+
export function addAbortListener(signal, handler) {
|
|
146
143
|
if (!signal) {
|
|
147
144
|
return
|
|
148
145
|
}
|
|
@@ -160,7 +157,7 @@ module.exports.addAbortListener = function addAbortListener(signal, handler) {
|
|
|
160
157
|
}
|
|
161
158
|
}
|
|
162
159
|
|
|
163
|
-
|
|
160
|
+
export function removeAbortListener(signal, handler) {
|
|
164
161
|
if (!signal) {
|
|
165
162
|
return
|
|
166
163
|
}
|