@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/deepstream.io-client-js",
3
- "version": "30.0.1",
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.4",
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
- "eslint": "^9.9.0",
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.29.1",
52
- "eslint-plugin-n": "^17.10.2",
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.4",
56
- "lint-staged": "^15.2.8",
57
- "mitata": "^0.1.11",
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
- "typescript": "^5.5.4",
62
- "typescript-eslint": "^8.0.1"
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"
@@ -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
+ }
@@ -81,6 +81,7 @@ ACTIONS.CHALLENGE = 'CH'
81
81
  ACTIONS.CHALLENGE_RESPONSE = 'CHR'
82
82
  ACTIONS.READ = 'R'
83
83
  ACTIONS.UPDATE = 'U'
84
+ ACTIONS.PUT = 'P'
84
85
  ACTIONS.SUBSCRIBE = 'S'
85
86
  ACTIONS.SYNC = 'SY'
86
87
  ACTIONS.UNSUBSCRIBE = 'US'
@@ -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 t! Deepstream server unreachable on " + this._url
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
+ }