@nxtedition/deepstream.io-client-js 30.0.1 → 31.0.0
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 +13 -10
- package/src/client.d.ts +104 -0
- package/src/constants/constants.js +1 -0
- package/src/event/event-handler.d.ts +20 -0
- package/src/message/connection.js +1 -1
- package/src/record/record-handler.d.ts +158 -0
- package/src/record/record-handler.js +316 -260
- package/src/record/record.d.ts +110 -0
- package/src/record/record.js +10 -17
- package/src/rpc/rpc-handler.d.ts +42 -0
- package/src/rpc/rpc-response.d.ts +5 -0
- package/src/utils/multicast-listener.js +164 -181
- package/src/utils/timers.js +4 -0
- package/src/utils/unicast-listener.js +35 -52
- package/src/utils/utils.js +20 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/deepstream.io-client-js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "31.0.0",
|
|
4
4
|
"description": "the javascript client for deepstream.io",
|
|
5
5
|
"homepage": "http://deepstream.io",
|
|
6
6
|
"type": "module",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"license": "Apache-2.0",
|
|
15
15
|
"author": "deepstreamHub GmbH",
|
|
16
16
|
"main": "src/client.js",
|
|
17
|
+
"types": "src/client.d.ts",
|
|
17
18
|
"browser": {
|
|
18
19
|
"ws": false
|
|
19
20
|
},
|
|
@@ -39,27 +40,29 @@
|
|
|
39
40
|
"component-emitter2": "^1.3.5",
|
|
40
41
|
"invariant": "^2.2.4",
|
|
41
42
|
"lodash.clonedeep": "^4.5.0",
|
|
42
|
-
"utf-8-validate": "^6.0.
|
|
43
|
+
"utf-8-validate": "^6.0.5",
|
|
43
44
|
"ws": "^8.18.0",
|
|
44
45
|
"xuid": "^4.1.3",
|
|
45
46
|
"xxhash-wasm": "^1.0.2"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
|
-
"
|
|
49
|
+
"@types/node": "^22.10.3",
|
|
50
|
+
"eslint": "^9.14.0",
|
|
49
51
|
"eslint-config-prettier": "^9.1.0",
|
|
50
52
|
"eslint-config-standard": "^17.1.0",
|
|
51
|
-
"eslint-plugin-import": "^2.
|
|
52
|
-
"eslint-plugin-n": "^17.
|
|
53
|
+
"eslint-plugin-import": "^2.31.0",
|
|
54
|
+
"eslint-plugin-n": "^17.12.0",
|
|
53
55
|
"eslint-plugin-node": "^11.1.0",
|
|
54
56
|
"eslint-plugin-promise": "^7.1.0",
|
|
55
|
-
"husky": "^9.1.
|
|
56
|
-
"lint-staged": "^15.2.
|
|
57
|
-
"mitata": "^0.
|
|
57
|
+
"husky": "^9.1.6",
|
|
58
|
+
"lint-staged": "^15.2.10",
|
|
59
|
+
"mitata": "^1.0.10",
|
|
58
60
|
"pinst": "^3.0.0",
|
|
59
61
|
"prettier": "^3.3.3",
|
|
60
62
|
"rxjs": "^7.8.1",
|
|
61
|
-
"
|
|
62
|
-
"typescript
|
|
63
|
+
"type-fest": "^4.33.0",
|
|
64
|
+
"typescript": "^5.6.3",
|
|
65
|
+
"typescript-eslint": "^8.12.2"
|
|
63
66
|
},
|
|
64
67
|
"peerDependencies": {
|
|
65
68
|
"rxjs": ">=6.x"
|
package/src/client.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type Record from './record/record.js'
|
|
2
|
+
import type RecordHandler, { RecordStats } from './record/record-handler.js'
|
|
3
|
+
import type EventHandler, { EventStats } from './event/event-handler.js'
|
|
4
|
+
import type RpcHandler, { RpcStats, RpcMethodDef } from './rpc/rpc-handler.js'
|
|
5
|
+
|
|
6
|
+
export default function <Records, Methods>(
|
|
7
|
+
url: string,
|
|
8
|
+
options?: unknown,
|
|
9
|
+
): DeepstreamClient<Records, Methods>
|
|
10
|
+
|
|
11
|
+
export type { Record, RecordHandler, EventHandler, RpcHandler }
|
|
12
|
+
|
|
13
|
+
type RecordStateConstants = Readonly<{
|
|
14
|
+
VOID: 0
|
|
15
|
+
CLIENT: 1
|
|
16
|
+
SERVER: 2
|
|
17
|
+
STALE: 3
|
|
18
|
+
PROVIDER: 4
|
|
19
|
+
}>
|
|
20
|
+
|
|
21
|
+
type ConnectionStateConstants = Readonly<{
|
|
22
|
+
CLOSED: 'CLOSED'
|
|
23
|
+
AWAITING_CONNECTION: 'AWAITING_CONNECTION'
|
|
24
|
+
CHALLENGING: 'CHALLENGING'
|
|
25
|
+
AWAITING_AUTHENTICATION: 'AWAITING_AUTHENTICATION'
|
|
26
|
+
AUTHENTICATING: 'AUTHENTICATING'
|
|
27
|
+
OPEN: 'OPEN'
|
|
28
|
+
ERROR: 'ERROR'
|
|
29
|
+
RECONNECTING: 'RECONNECTING'
|
|
30
|
+
}>
|
|
31
|
+
type ConnectionStateKey = keyof typeof ConnectionStateConstants
|
|
32
|
+
type ConnectionStateName = (typeof ConnectionStateConstants)[ConnectionStateKey]
|
|
33
|
+
|
|
34
|
+
type EventConstants = Readonly<{
|
|
35
|
+
CONNECTION_ERROR: 'connectionError'
|
|
36
|
+
CONNECTION_STATE_CHANGED: 'connectionStateChanged'
|
|
37
|
+
CONNECTED: 'connected'
|
|
38
|
+
MAX_RECONNECTION_ATTEMPTS_REACHED: 'MAX_RECONNECTION_ATTEMPTS_REACHED'
|
|
39
|
+
CONNECTION_AUTHENTICATION_TIMEOUT: 'CONNECTION_AUTHENTICATION_TIMEOUT'
|
|
40
|
+
NO_RPC_PROVIDER: 'NO_RPC_PROVIDER'
|
|
41
|
+
RPC_ERROR: 'RPC_ERROR'
|
|
42
|
+
TIMEOUT: 'TIMEOUT'
|
|
43
|
+
UNSOLICITED_MESSAGE: 'UNSOLICITED_MESSAGE'
|
|
44
|
+
MESSAGE_DENIED: 'MESSAGE_DENIED'
|
|
45
|
+
NOT_CONNECTED: 'NOT_CONNECTED'
|
|
46
|
+
MESSAGE_PARSE_ERROR: 'MESSAGE_PARSE_ERROR'
|
|
47
|
+
NOT_AUTHENTICATED: 'NOT_AUTHENTICATED'
|
|
48
|
+
MESSAGE_PERMISSION_ERROR: 'MESSAGE_PERMISSION_ERROR'
|
|
49
|
+
LISTENER_EXISTS: 'LISTENER_EXISTS'
|
|
50
|
+
PROVIDER_ERROR: 'PROVIDER_ERROR'
|
|
51
|
+
CACHE_ERROR: 'CACHE_ERROR'
|
|
52
|
+
UPDATE_ERROR: 'UPDATE_ERROR'
|
|
53
|
+
USER_ERROR: 'USER_ERROR'
|
|
54
|
+
REF_ERROR: 'REF_ERROR'
|
|
55
|
+
PROVIDER_EXISTS: 'PROVIDER_EXISTS'
|
|
56
|
+
NOT_LISTENING: 'NOT_LISTENING'
|
|
57
|
+
NOT_PROVIDING: 'NOT_PROVIDING'
|
|
58
|
+
LISTENER_ERROR: 'LISTENER_ERROR'
|
|
59
|
+
TOO_MANY_AUTH_ATTEMPTS: 'TOO_MANY_AUTH_ATTEMPTS'
|
|
60
|
+
IS_CLOSED: 'IS_CLOSED'
|
|
61
|
+
RECORD_NOT_FOUND: 'RECORD_NOT_FOUND'
|
|
62
|
+
NOT_SUBSCRIBED: 'NOT_SUBSCRIBED'
|
|
63
|
+
}>
|
|
64
|
+
type EventKey = keyof typeof EventConstants
|
|
65
|
+
type EventName = (typeof EventConstants)[EventKey]
|
|
66
|
+
|
|
67
|
+
export interface DeepstreamClient<
|
|
68
|
+
Records = Record<string, unknown>,
|
|
69
|
+
Methods = Record<string, RpcMethodDef>,
|
|
70
|
+
> {
|
|
71
|
+
nuid: () => string
|
|
72
|
+
event: EventHandler
|
|
73
|
+
rpc: RpcHandler<Methods>
|
|
74
|
+
record: RecordHandler<Records>
|
|
75
|
+
user: string | null
|
|
76
|
+
on: (evt: EventName, callback: (...args: unknown[]) => void) => void
|
|
77
|
+
off: (evt: EventName, callback: (...args: unknown[]) => void) => void
|
|
78
|
+
getConnectionState: () => ConnectionStateName
|
|
79
|
+
close: () => void
|
|
80
|
+
login: unknown
|
|
81
|
+
stats: {
|
|
82
|
+
record: RecordStats
|
|
83
|
+
rpc: RpcStats
|
|
84
|
+
event: EventStats
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
isSameOrNewer(a: string, b: string): boolean
|
|
88
|
+
|
|
89
|
+
CONSTANTS: {
|
|
90
|
+
CONNECTION_STATE: ConnectionStateConstants
|
|
91
|
+
RECORD_STATE: RecordStateConstants
|
|
92
|
+
EVENT: EventConstants
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface ProvideOptions {
|
|
97
|
+
recursive?: boolean
|
|
98
|
+
stringify?: ((input: unknown) => string) | null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface SyncOptions {
|
|
102
|
+
signal?: AbortSignal
|
|
103
|
+
timeout?: number
|
|
104
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Observable } from 'rxjs'
|
|
2
|
+
|
|
3
|
+
export default class EventHandler {
|
|
4
|
+
connected: boolean
|
|
5
|
+
stats: EventStats
|
|
6
|
+
subscribe: (name: string, callback: () => void) => void
|
|
7
|
+
unsubscribe: (name: string, callback: () => void) => void
|
|
8
|
+
on: (name: string, callback: () => void) => this
|
|
9
|
+
once: (name: string, callback: () => void) => this
|
|
10
|
+
off: (name: string, callback: () => void) => this
|
|
11
|
+
observe: <Data>(name: string) => Observable<Data>
|
|
12
|
+
emit: <Data>(name: string, data?: Data) => void
|
|
13
|
+
provide: (pattern: string, callback: (name: string) => void, options: unknown) => () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface EventStats {
|
|
17
|
+
emitted: number
|
|
18
|
+
listeners: number
|
|
19
|
+
events: number
|
|
20
|
+
}
|
|
@@ -199,7 +199,7 @@ Connection.prototype._onError = function (err) {
|
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
if (err.code === 'ECONNRESET' || err.code === 'ECONNREFUSED') {
|
|
202
|
-
err.message = "Can't
|
|
202
|
+
err.message = "Can't connect! Deepstream server unreachable on " + this._url
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
this._client._$onError(C.TOPIC.CONNECTION, C.EVENT.CONNECTION_ERROR, err)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import type { Observable } from 'rxjs'
|
|
2
|
+
import type Record, { EmptyObject, GettablePossibleEmpty, SettablePossibleEmpty } from './record.js'
|
|
3
|
+
|
|
4
|
+
type Paths<T> = keyof T
|
|
5
|
+
type Get<Data, Path extends string> = Path extends keyof Data ? Data[Path] : unknown
|
|
6
|
+
|
|
7
|
+
export default class RecordHandler<Records> {
|
|
8
|
+
VOID: 0
|
|
9
|
+
CLIENT: 1
|
|
10
|
+
SERVER: 2
|
|
11
|
+
STALE: 3
|
|
12
|
+
PROVIDER: 4
|
|
13
|
+
|
|
14
|
+
JSON: {
|
|
15
|
+
EMPTY: EmptyObject
|
|
16
|
+
EMPTY_OBJ: EmptyObject
|
|
17
|
+
EMPTY_ARR: Readonly<unknown[]>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
connected: boolean
|
|
21
|
+
stats: RecordStats
|
|
22
|
+
|
|
23
|
+
getRecord: <Name extends keyof Records, Data extends Records[Name] = Records[Name]>(
|
|
24
|
+
name: Name,
|
|
25
|
+
) => Record<Data>
|
|
26
|
+
|
|
27
|
+
provide: <Data>(
|
|
28
|
+
pattern: string,
|
|
29
|
+
callback: (key: string) => Data,
|
|
30
|
+
optionsOrRecursive?: ProvideOptions | boolean,
|
|
31
|
+
) => void | (() => void)
|
|
32
|
+
|
|
33
|
+
sync: (options?: SyncOptions) => Promise<void>
|
|
34
|
+
|
|
35
|
+
set: {
|
|
36
|
+
// without path:
|
|
37
|
+
<Name extends keyof Records>(name: Name, data: SettablePossibleEmpty<Records[Name]>): void
|
|
38
|
+
|
|
39
|
+
// with path:
|
|
40
|
+
<Name extends keyof Records, Data extends Records[Name], Path extends Paths<Data>>(
|
|
41
|
+
name: Name,
|
|
42
|
+
path: Path,
|
|
43
|
+
data: Get<Data, Path>,
|
|
44
|
+
): void
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
update: {
|
|
48
|
+
// without path:
|
|
49
|
+
<Name extends keyof Records, Data extends Records[Name]>(
|
|
50
|
+
name: Name,
|
|
51
|
+
updater: (data: Readonly<GettablePossibleEmpty<Data>>) => SettablePossibleEmpty<Data>,
|
|
52
|
+
): Promise<void>
|
|
53
|
+
|
|
54
|
+
// with path:
|
|
55
|
+
<Name extends keyof Records, Data extends Records[Name], Path extends Paths<Data>>(
|
|
56
|
+
name: Name,
|
|
57
|
+
path: Path,
|
|
58
|
+
updater: (data: Readonly<Get<Data, Path>> | undefined) => Get<Data, Path>,
|
|
59
|
+
): Promise<void>
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
observe: {
|
|
63
|
+
// without path:
|
|
64
|
+
<Name extends keyof Records, Data extends Records[Name]>(
|
|
65
|
+
name: Name,
|
|
66
|
+
): Observable<GettablePossibleEmpty<Data>>
|
|
67
|
+
|
|
68
|
+
// with path:
|
|
69
|
+
<Name extends keyof Records, Data extends Records[Name], Path extends Paths<Data> & string>(
|
|
70
|
+
name: Name,
|
|
71
|
+
path: Path,
|
|
72
|
+
): Observable<Get<Data, Path> | undefined>
|
|
73
|
+
|
|
74
|
+
// with state:
|
|
75
|
+
<Name extends keyof Records, Data extends Records[Name]>(
|
|
76
|
+
name: Name,
|
|
77
|
+
state: number,
|
|
78
|
+
): Observable<GettablePossibleEmpty<Data>>
|
|
79
|
+
|
|
80
|
+
// with path and state:
|
|
81
|
+
<Name extends keyof Records, Data extends Records[Name], Path extends Paths<Data> & string>(
|
|
82
|
+
name: Name,
|
|
83
|
+
path: Path,
|
|
84
|
+
state: number,
|
|
85
|
+
): Observable<Get<Data, Path> | undefined>
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get: {
|
|
89
|
+
// without path:
|
|
90
|
+
<Name extends keyof Records, Data extends Records[Name]>(
|
|
91
|
+
name: Name,
|
|
92
|
+
state?: number,
|
|
93
|
+
): Promise<GettablePossibleEmpty<Data>>
|
|
94
|
+
|
|
95
|
+
// with path:
|
|
96
|
+
<Name extends keyof Records, Data extends Records[Name], Path extends Paths<Data> & string>(
|
|
97
|
+
name: Name,
|
|
98
|
+
path?: Path,
|
|
99
|
+
state?: number,
|
|
100
|
+
): Promise<Get<Data, Path> | undefined>
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
observe2: {
|
|
104
|
+
// without path:
|
|
105
|
+
<Name extends keyof Records, Data extends Records[Name]>(
|
|
106
|
+
name: Name,
|
|
107
|
+
): Observable<{
|
|
108
|
+
name: Name
|
|
109
|
+
version: string
|
|
110
|
+
state: number
|
|
111
|
+
data: GettablePossibleEmpty<Data>
|
|
112
|
+
}>
|
|
113
|
+
|
|
114
|
+
// with path:
|
|
115
|
+
<Name extends keyof Records, Data extends Records[Name], Path extends Paths<Data> & string>(
|
|
116
|
+
name: Name,
|
|
117
|
+
path: Path,
|
|
118
|
+
): Observable<{
|
|
119
|
+
name: Name
|
|
120
|
+
version: string
|
|
121
|
+
state: number
|
|
122
|
+
data: Get<Data, Path> | undefined
|
|
123
|
+
}>
|
|
124
|
+
|
|
125
|
+
// with state:
|
|
126
|
+
<Name extends keyof Records, Data extends Records[Name]>(
|
|
127
|
+
name: Name,
|
|
128
|
+
state: number,
|
|
129
|
+
): Observable<{
|
|
130
|
+
name: Name
|
|
131
|
+
version: string
|
|
132
|
+
state: number
|
|
133
|
+
data: GettablePossibleEmpty<Data>
|
|
134
|
+
}>
|
|
135
|
+
|
|
136
|
+
// with path and state:
|
|
137
|
+
<Name extends keyof Records, Data extends Records[Name], Path extends Paths<Data> & string>(
|
|
138
|
+
name: Name,
|
|
139
|
+
path: Path,
|
|
140
|
+
state: number,
|
|
141
|
+
): Observable<{
|
|
142
|
+
name: Name
|
|
143
|
+
version: string
|
|
144
|
+
state: number
|
|
145
|
+
data: Get<Data, Path> | undefined
|
|
146
|
+
}>
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface RecordStats {
|
|
151
|
+
updating: number
|
|
152
|
+
created: number
|
|
153
|
+
destroyed: number
|
|
154
|
+
records: number
|
|
155
|
+
pruning: number
|
|
156
|
+
patching: number
|
|
157
|
+
subscriptions: number
|
|
158
|
+
}
|