@nymphjs/client 1.0.0-beta.12 → 1.0.0-beta.121
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/CHANGELOG.md +500 -0
- package/README.md +6 -6
- package/asyncitertest.js +53 -0
- package/dist/Entity.d.ts +156 -0
- package/{lib → dist}/Entity.js +202 -104
- package/dist/Entity.js.map +1 -0
- package/dist/Entity.types.d.ts +218 -0
- package/dist/Entity.types.js +2 -0
- package/{lib → dist}/EntityWeakCache.d.ts +1 -1
- package/{lib → dist}/EntityWeakCache.js +5 -9
- package/dist/EntityWeakCache.js.map +1 -0
- package/{lib → dist}/HttpRequester.d.ts +18 -4
- package/dist/HttpRequester.js +365 -0
- package/dist/HttpRequester.js.map +1 -0
- package/{lib → dist}/Nymph.d.ts +48 -11
- package/{lib → dist}/Nymph.js +167 -51
- package/dist/Nymph.js.map +1 -0
- package/dist/Nymph.types.d.ts +227 -0
- package/dist/Nymph.types.js +45 -0
- package/dist/Nymph.types.js.map +1 -0
- package/{lib → dist}/PubSub.d.ts +16 -10
- package/{lib → dist}/PubSub.js +208 -135
- package/dist/PubSub.js.map +1 -0
- package/{lib → dist}/PubSub.types.d.ts +19 -6
- package/dist/PubSub.types.js +2 -0
- package/{lib → dist}/entityRefresh.d.ts +1 -1
- package/{lib → dist}/entityRefresh.js +21 -13
- package/dist/entityRefresh.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/{lib → dist}/utils.d.ts +1 -1
- package/{lib → dist}/utils.js +28 -21
- package/dist/utils.js.map +1 -0
- package/jest.config.js +31 -5
- package/package.json +31 -30
- package/src/Entity.ts +174 -108
- package/src/Entity.types.ts +29 -47
- package/src/EntityWeakCache.ts +8 -6
- package/src/HttpRequester.ts +268 -31
- package/src/Nymph.ts +188 -88
- package/src/Nymph.types.ts +102 -2
- package/src/PubSub.ts +262 -179
- package/src/PubSub.types.ts +33 -19
- package/src/entityRefresh.ts +6 -6
- package/src/index.ts +10 -10
- package/src/utils.ts +12 -5
- package/tsconfig.json +7 -4
- package/typedoc.json +4 -0
- package/dist/index.js.LICENSE.txt +0 -8
- package/lib/Entity.d.ts +0 -51
- package/lib/Entity.js.map +0 -1
- package/lib/Entity.types.d.ts +0 -65
- package/lib/Entity.types.js +0 -3
- package/lib/EntityWeakCache.js.map +0 -1
- package/lib/HttpRequester.js +0 -190
- package/lib/HttpRequester.js.map +0 -1
- package/lib/Nymph.js.map +0 -1
- package/lib/Nymph.types.d.ts +0 -97
- package/lib/Nymph.types.js +0 -3
- package/lib/Nymph.types.js.map +0 -1
- package/lib/PubSub.js.map +0 -1
- package/lib/PubSub.types.js +0 -3
- package/lib/entityRefresh.js.map +0 -1
- package/lib/index.d.ts +0 -13
- package/lib/index.js +0 -34
- package/lib/index.js.map +0 -1
- package/lib/utils.js.map +0 -1
- package/webpack.config.js +0 -28
- /package/{lib → dist}/Entity.types.js.map +0 -0
- /package/{lib → dist}/PubSub.types.js.map +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export var TilmeldAccessRequest;
|
|
2
|
+
(function (TilmeldAccessRequest) {
|
|
3
|
+
/**
|
|
4
|
+
* The default level, any possible entity readable by the user.
|
|
5
|
+
*
|
|
6
|
+
* This is the same as or-ing together all of the levels listed below.
|
|
7
|
+
*/
|
|
8
|
+
TilmeldAccessRequest[TilmeldAccessRequest["ALL_LEVELS"] = 0] = "ALL_LEVELS";
|
|
9
|
+
/**
|
|
10
|
+
* Owned by and accessible to the user.
|
|
11
|
+
*
|
|
12
|
+
* This is always enabled, so not including it has no effect. It's here to
|
|
13
|
+
* allow the selection of _only_ user owned entities.
|
|
14
|
+
*/
|
|
15
|
+
TilmeldAccessRequest[TilmeldAccessRequest["USER_OWNED"] = 1] = "USER_OWNED";
|
|
16
|
+
/**
|
|
17
|
+
* Owned by and accessible to the user's primary group.
|
|
18
|
+
*/
|
|
19
|
+
TilmeldAccessRequest[TilmeldAccessRequest["PRIMARY_GROUP_OWNED"] = 2] = "PRIMARY_GROUP_OWNED";
|
|
20
|
+
/**
|
|
21
|
+
* Owned by and accessible to one of the user's secondary groups.
|
|
22
|
+
*/
|
|
23
|
+
TilmeldAccessRequest[TilmeldAccessRequest["SECONDARY_GROUP_OWNED"] = 4] = "SECONDARY_GROUP_OWNED";
|
|
24
|
+
/**
|
|
25
|
+
* The user is listed in an access control list.
|
|
26
|
+
*/
|
|
27
|
+
TilmeldAccessRequest[TilmeldAccessRequest["USER_ACCESSIBLE"] = 8] = "USER_ACCESSIBLE";
|
|
28
|
+
/**
|
|
29
|
+
* The user's primary group is listed in an access control list.
|
|
30
|
+
*/
|
|
31
|
+
TilmeldAccessRequest[TilmeldAccessRequest["PRIMARY_GROUP_ACCESSIBLE"] = 16] = "PRIMARY_GROUP_ACCESSIBLE";
|
|
32
|
+
/**
|
|
33
|
+
* One of the user's secondary groups is listed in an access control list.
|
|
34
|
+
*/
|
|
35
|
+
TilmeldAccessRequest[TilmeldAccessRequest["SECONDARY_GROUP_ACCESSIBLE"] = 32] = "SECONDARY_GROUP_ACCESSIBLE";
|
|
36
|
+
/**
|
|
37
|
+
* The entity is accessible to any user.
|
|
38
|
+
*/
|
|
39
|
+
TilmeldAccessRequest[TilmeldAccessRequest["OTHER_ACCESSIBLE"] = 64] = "OTHER_ACCESSIBLE";
|
|
40
|
+
/**
|
|
41
|
+
* The entity is not owned by anyone.
|
|
42
|
+
*/
|
|
43
|
+
TilmeldAccessRequest[TilmeldAccessRequest["UNOWNED"] = 128] = "UNOWNED";
|
|
44
|
+
})(TilmeldAccessRequest || (TilmeldAccessRequest = {}));
|
|
45
|
+
//# sourceMappingURL=Nymph.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Nymph.types.js","sourceRoot":"","sources":["../src/Nymph.types.ts"],"names":[],"mappings":"AAoOA,MAAM,CAAN,IAAY,oBA0CX;AA1CD,WAAY,oBAAoB;IAC9B;;;;OAIG;IACH,2EAAc,CAAA;IACd;;;;;OAKG;IACH,2EAAc,CAAA;IACd;;OAEG;IACH,6FAAuB,CAAA;IACvB;;OAEG;IACH,iGAAyB,CAAA;IACzB;;OAEG;IACH,qFAAmB,CAAA;IACnB;;OAEG;IACH,wGAA6B,CAAA;IAC7B;;OAEG;IACH,4GAA+B,CAAA;IAC/B;;OAEG;IACH,wFAAqB,CAAA;IACrB;;OAEG;IACH,uEAAa,CAAA;AACf,CAAC,EA1CW,oBAAoB,KAApB,oBAAoB,QA0C/B"}
|
package/{lib → dist}/PubSub.d.ts
RENAMED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import Nymph from './Nymph';
|
|
2
|
-
import { NymphOptions, Options, Selector } from './Nymph.types';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import Nymph from './Nymph.js';
|
|
2
|
+
import type { NymphOptions, Options, Selector } from './Nymph.types.js';
|
|
3
|
+
import type { EntityInstanceType } from './Entity.js';
|
|
4
|
+
import type { EntityConstructor, EntityInterface } from './Entity.types.js';
|
|
5
|
+
import type { PubSubCallbacks, PubSubConnectCallback, PubSubCountCallback, PubSubDisconnectCallback, PubSubEventType, PubSubRejectCallback, PubSubResolveCallback, PubSubErrorCallback, PubSubSubscribable, PubSubUpdate } from './PubSub.types.js';
|
|
5
6
|
export default class PubSub {
|
|
6
7
|
private nymph;
|
|
8
|
+
private authToken;
|
|
9
|
+
private switchToken;
|
|
7
10
|
private connection;
|
|
8
11
|
private waitForConnectionTimeout;
|
|
9
12
|
private pubsubUrl;
|
|
@@ -11,16 +14,17 @@ export default class PubSub {
|
|
|
11
14
|
private subscriptions;
|
|
12
15
|
private connectCallbacks;
|
|
13
16
|
private disconnectCallbacks;
|
|
17
|
+
private errorCallbacks;
|
|
14
18
|
private noConsole;
|
|
15
19
|
constructor(nymphOptions: NymphOptions, nymph: Nymph);
|
|
16
20
|
subscribeEntities<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
|
|
17
21
|
return: 'guid';
|
|
18
22
|
}, ...selectors: Selector[]): PubSubSubscribable<PubSubUpdate<string[]>>;
|
|
19
|
-
subscribeEntities<T extends EntityConstructor = EntityConstructor>(options: Options<T>, ...selectors: Selector[]): PubSubSubscribable<PubSubUpdate<
|
|
23
|
+
subscribeEntities<T extends EntityConstructor = EntityConstructor>(options: Options<T>, ...selectors: Selector[]): PubSubSubscribable<PubSubUpdate<EntityInstanceType<T>[]>>;
|
|
20
24
|
subscribeEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
|
|
21
25
|
return: 'guid';
|
|
22
26
|
}, ...selectors: Selector[]): PubSubSubscribable<PubSubUpdate<string | null>>;
|
|
23
|
-
subscribeEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T>, ...selectors: Selector[]): PubSubSubscribable<PubSubUpdate<
|
|
27
|
+
subscribeEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T>, ...selectors: Selector[]): PubSubSubscribable<PubSubUpdate<EntityInstanceType<T> | null>>;
|
|
24
28
|
subscribeUID(name: string): (resolve?: PubSubResolveCallback<number> | undefined, reject?: PubSubRejectCallback | undefined, count?: PubSubCountCallback | undefined) => {
|
|
25
29
|
unsubscribe: () => void;
|
|
26
30
|
};
|
|
@@ -34,6 +38,8 @@ export default class PubSub {
|
|
|
34
38
|
private _onclose;
|
|
35
39
|
private _send;
|
|
36
40
|
isConnectionOpen(): boolean;
|
|
41
|
+
isConnectionConnecting(): boolean;
|
|
42
|
+
isConnection(): boolean;
|
|
37
43
|
private _subscribeQuery;
|
|
38
44
|
private _subscribeUID;
|
|
39
45
|
private _sendQuery;
|
|
@@ -44,10 +50,10 @@ export default class PubSub {
|
|
|
44
50
|
private _unsubscribeUID;
|
|
45
51
|
private _sendUnQuery;
|
|
46
52
|
private _sendUnUID;
|
|
47
|
-
updateArray(
|
|
48
|
-
on<T extends PubSubEventType>(event: T, callback: T extends 'connect' ? PubSubConnectCallback : T extends 'disconnect' ? PubSubDisconnectCallback : never): () => boolean;
|
|
49
|
-
off<T extends PubSubEventType>(event: T, callback: T extends 'connect' ? PubSubConnectCallback : T extends 'disconnect' ? PubSubDisconnectCallback : never): boolean;
|
|
50
|
-
|
|
53
|
+
updateArray(current: EntityInterface[], update: PubSubUpdate<EntityInterface[]>): void;
|
|
54
|
+
on<T extends PubSubEventType>(event: T, callback: T extends 'connect' ? PubSubConnectCallback : T extends 'disconnect' ? PubSubDisconnectCallback : T extends 'error' ? PubSubErrorCallback : never): () => boolean;
|
|
55
|
+
off<T extends PubSubEventType>(event: T, callback: T extends 'connect' ? PubSubConnectCallback : T extends 'disconnect' ? PubSubDisconnectCallback : T extends 'error' ? PubSubErrorCallback : never): boolean;
|
|
56
|
+
authenticate(authToken: string | null, switchToken?: string | null): void;
|
|
51
57
|
}
|
|
52
58
|
export declare class PubSubSubscription<T> {
|
|
53
59
|
query: string;
|
package/{lib → dist}/PubSub.js
RENAMED
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { InvalidRequestError } from './Nymph.js';
|
|
2
|
+
import { entityConstructorsToClassNames } from './utils.js';
|
|
3
|
+
import { ClientError } from './HttpRequester.js';
|
|
4
|
+
export default class PubSub {
|
|
5
|
+
nymph;
|
|
6
|
+
authToken = null;
|
|
7
|
+
switchToken = null;
|
|
8
|
+
connection;
|
|
9
|
+
waitForConnectionTimeout;
|
|
10
|
+
pubsubUrl;
|
|
11
|
+
WebSocket;
|
|
12
|
+
subscriptions = {
|
|
13
|
+
queries: {},
|
|
14
|
+
uids: {},
|
|
15
|
+
};
|
|
16
|
+
connectCallbacks = [];
|
|
17
|
+
disconnectCallbacks = [];
|
|
18
|
+
errorCallbacks = [];
|
|
19
|
+
noConsole = false;
|
|
8
20
|
constructor(nymphOptions, nymph) {
|
|
9
|
-
this.subscriptions = {
|
|
10
|
-
queries: {},
|
|
11
|
-
uids: {},
|
|
12
|
-
};
|
|
13
|
-
this.connectCallbacks = [];
|
|
14
|
-
this.disconnectCallbacks = [];
|
|
15
|
-
this.noConsole = false;
|
|
16
21
|
this.nymph = nymph;
|
|
17
22
|
this.nymph.pubsub = this;
|
|
18
23
|
this.pubsubUrl = nymphOptions.pubsubUrl;
|
|
@@ -24,20 +29,23 @@ class PubSub {
|
|
|
24
29
|
if (typeof addEventListener !== 'undefined') {
|
|
25
30
|
addEventListener('online', () => this.connect());
|
|
26
31
|
}
|
|
27
|
-
if (
|
|
32
|
+
if (!nymphOptions.noAutoconnect &&
|
|
33
|
+
(typeof navigator === 'undefined' || navigator.onLine)) {
|
|
28
34
|
this.connect();
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
37
|
subscribeEntities(options, ...selectors) {
|
|
32
|
-
const promise = this.nymph.getEntities(options, ...selectors);
|
|
33
38
|
const query = [
|
|
34
|
-
|
|
35
|
-
...
|
|
39
|
+
entityConstructorsToClassNames(options),
|
|
40
|
+
...entityConstructorsToClassNames(selectors),
|
|
36
41
|
];
|
|
37
42
|
const jsonQuery = JSON.stringify(query);
|
|
38
43
|
const subscribe = (resolve, reject, count) => {
|
|
39
44
|
const callbacks = [resolve, reject, count];
|
|
40
|
-
|
|
45
|
+
if (!this.isConnection()) {
|
|
46
|
+
// Fall back to a regular query if we're not connected.
|
|
47
|
+
this.nymph.getEntities(options, ...selectors).then(resolve, reject);
|
|
48
|
+
}
|
|
41
49
|
this._subscribeQuery(jsonQuery, callbacks);
|
|
42
50
|
return new PubSubSubscription(jsonQuery, callbacks, () => {
|
|
43
51
|
this._unsubscribeQuery(jsonQuery, callbacks);
|
|
@@ -46,10 +54,9 @@ class PubSub {
|
|
|
46
54
|
return subscribe;
|
|
47
55
|
}
|
|
48
56
|
subscribeEntity(options, ...selectors) {
|
|
49
|
-
const promise = this.nymph.getEntity(options, ...selectors);
|
|
50
57
|
const query = [
|
|
51
|
-
{ ...
|
|
52
|
-
...
|
|
58
|
+
{ ...entityConstructorsToClassNames(options), limit: 1 },
|
|
59
|
+
...entityConstructorsToClassNames(selectors),
|
|
53
60
|
];
|
|
54
61
|
const jsonQuery = JSON.stringify(query);
|
|
55
62
|
const subscribe = (resolve, reject, count) => {
|
|
@@ -66,7 +73,10 @@ class PubSub {
|
|
|
66
73
|
}
|
|
67
74
|
};
|
|
68
75
|
const callbacks = [newResolve, reject, count];
|
|
69
|
-
|
|
76
|
+
if (!this.isConnection()) {
|
|
77
|
+
// Fall back to a regular query if we're not connected.
|
|
78
|
+
this.nymph.getEntity(options, ...selectors).then(resolve, reject);
|
|
79
|
+
}
|
|
70
80
|
this._subscribeQuery(jsonQuery, callbacks);
|
|
71
81
|
return new PubSubSubscription(jsonQuery, callbacks, () => {
|
|
72
82
|
this._unsubscribeQuery(jsonQuery, callbacks);
|
|
@@ -75,10 +85,12 @@ class PubSub {
|
|
|
75
85
|
return subscribe;
|
|
76
86
|
}
|
|
77
87
|
subscribeUID(name) {
|
|
78
|
-
const promise = this.nymph.getUID(name);
|
|
79
88
|
const subscribe = (resolve, reject, count) => {
|
|
80
89
|
const callbacks = [resolve, reject, count];
|
|
81
|
-
|
|
90
|
+
if (!this.isConnection()) {
|
|
91
|
+
// Fall back to a regular query if we're not connected.
|
|
92
|
+
this.nymph.getUID(name).then(resolve, reject);
|
|
93
|
+
}
|
|
82
94
|
this._subscribeUID(name, callbacks);
|
|
83
95
|
return {
|
|
84
96
|
unsubscribe: () => {
|
|
@@ -90,7 +102,7 @@ class PubSub {
|
|
|
90
102
|
}
|
|
91
103
|
subscribeWith(entity, resolve, reject, count) {
|
|
92
104
|
if (!entity.guid) {
|
|
93
|
-
throw new
|
|
105
|
+
throw new InvalidRequestError("You can't subscribe to an entity with no GUID.");
|
|
94
106
|
}
|
|
95
107
|
const query = [
|
|
96
108
|
{ class: entity.constructor.class, limit: 1 },
|
|
@@ -99,18 +111,24 @@ class PubSub {
|
|
|
99
111
|
const jsonQuery = JSON.stringify(query);
|
|
100
112
|
const newResolve = (args) => {
|
|
101
113
|
if (Array.isArray(args)) {
|
|
102
|
-
if (args
|
|
103
|
-
entity.$init(args[0]);
|
|
114
|
+
if (args.length) {
|
|
115
|
+
entity.$init(args[0].toJSON());
|
|
104
116
|
}
|
|
105
117
|
else {
|
|
106
118
|
entity.guid = null;
|
|
107
119
|
}
|
|
108
120
|
}
|
|
109
|
-
else if ('removed' in args) {
|
|
110
|
-
entity.guid = null;
|
|
111
|
-
}
|
|
112
121
|
else {
|
|
113
|
-
|
|
122
|
+
let update = args;
|
|
123
|
+
if ('multiple' in args && args.multiple) {
|
|
124
|
+
update = args.messages.pop();
|
|
125
|
+
}
|
|
126
|
+
if ('removed' in update) {
|
|
127
|
+
entity.guid = null;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
entity.$init(update.data);
|
|
131
|
+
}
|
|
114
132
|
}
|
|
115
133
|
if (resolve) {
|
|
116
134
|
resolve(entity);
|
|
@@ -123,6 +141,7 @@ class PubSub {
|
|
|
123
141
|
});
|
|
124
142
|
}
|
|
125
143
|
connect() {
|
|
144
|
+
// Are we already connected?
|
|
126
145
|
if (this.connection &&
|
|
127
146
|
(this.connection.readyState === this.WebSocket.OPEN ||
|
|
128
147
|
this.connection.readyState === this.WebSocket.CONNECTING)) {
|
|
@@ -138,28 +157,32 @@ class PubSub {
|
|
|
138
157
|
if (!this.connection) {
|
|
139
158
|
return;
|
|
140
159
|
}
|
|
141
|
-
this.connection.close(
|
|
160
|
+
this.connection.close(1000, 'Closure requested by application.');
|
|
142
161
|
}
|
|
143
|
-
_waitForConnection(attempts =
|
|
162
|
+
_waitForConnection(attempts = 1) {
|
|
163
|
+
// Wait 5 seconds, then check and attempt connection again if unsuccessful.
|
|
164
|
+
// Keep repeating, adding attempts^2*5 seconds each time to a max of ten
|
|
165
|
+
// minutes, until successful.
|
|
144
166
|
this.waitForConnectionTimeout = setTimeout(() => {
|
|
145
|
-
if (this.connection
|
|
146
|
-
this.connection.readyState !== this.WebSocket.OPEN) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
167
|
+
if (this.connection) {
|
|
168
|
+
if (this.connection.readyState !== this.WebSocket.OPEN) {
|
|
169
|
+
if (this.connection.readyState !== this.WebSocket.CONNECTING) {
|
|
170
|
+
this.connection.close();
|
|
171
|
+
this._waitForConnection(attempts + 1);
|
|
172
|
+
this._attemptConnect();
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
this._waitForConnection(attempts + 1);
|
|
176
|
+
}
|
|
155
177
|
}
|
|
156
178
|
}
|
|
157
179
|
else {
|
|
158
180
|
this._attemptConnect();
|
|
159
181
|
}
|
|
160
|
-
}, 5000);
|
|
182
|
+
}, Math.max(Math.pow(attempts, 2) * 5000, 1000 * 60 * 10));
|
|
161
183
|
}
|
|
162
184
|
_attemptConnect() {
|
|
185
|
+
// Attempt to connect.
|
|
163
186
|
if (this.pubsubUrl != null) {
|
|
164
187
|
this.connection = new this.WebSocket(this.pubsubUrl, 'nymph');
|
|
165
188
|
this.connection.onopen = this._onopen.bind(this);
|
|
@@ -170,16 +193,20 @@ class PubSub {
|
|
|
170
193
|
if (typeof console !== 'undefined' && !this.noConsole) {
|
|
171
194
|
console.log('Nymph-PubSub connection established!');
|
|
172
195
|
}
|
|
196
|
+
if (this.waitForConnectionTimeout) {
|
|
197
|
+
clearTimeout(this.waitForConnectionTimeout);
|
|
198
|
+
}
|
|
173
199
|
for (let i = 0; i < this.connectCallbacks.length; i++) {
|
|
174
200
|
const callback = this.connectCallbacks[i];
|
|
175
201
|
if (callback) {
|
|
176
202
|
callback();
|
|
177
203
|
}
|
|
178
204
|
}
|
|
179
|
-
if (authToken != null) {
|
|
205
|
+
if (this.authToken != null) {
|
|
180
206
|
this._send({
|
|
181
207
|
action: 'authenticate',
|
|
182
|
-
|
|
208
|
+
authToken: this.authToken,
|
|
209
|
+
switchToken: this.switchToken,
|
|
183
210
|
});
|
|
184
211
|
}
|
|
185
212
|
for (let query in this.subscriptions.queries) {
|
|
@@ -215,15 +242,19 @@ class PubSub {
|
|
|
215
242
|
_onmessage(e) {
|
|
216
243
|
let data = JSON.parse(e.data);
|
|
217
244
|
let subs = [];
|
|
245
|
+
let set = 'set' in data && data.set;
|
|
218
246
|
let count = 'count' in data;
|
|
247
|
+
let error = 'error' in data;
|
|
219
248
|
if (data.hasOwnProperty('query') &&
|
|
220
249
|
this.subscriptions.queries.hasOwnProperty(data.query)) {
|
|
221
250
|
subs = [...this.subscriptions.queries[data.query]];
|
|
222
|
-
if (!count) {
|
|
251
|
+
if (!count && !error) {
|
|
223
252
|
for (let i = 0; i < subs.length; i++) {
|
|
224
253
|
const callback = subs[i][0];
|
|
225
254
|
if (typeof callback === 'function') {
|
|
226
|
-
callback(
|
|
255
|
+
callback(set
|
|
256
|
+
? data.data.map((e) => this.nymph.initEntity(e))
|
|
257
|
+
: data);
|
|
227
258
|
}
|
|
228
259
|
}
|
|
229
260
|
}
|
|
@@ -231,15 +262,35 @@ class PubSub {
|
|
|
231
262
|
else if (data.hasOwnProperty('uid') &&
|
|
232
263
|
this.subscriptions.uids.hasOwnProperty(data.uid)) {
|
|
233
264
|
subs = [...this.subscriptions.uids[data.uid]];
|
|
234
|
-
if (!count) {
|
|
265
|
+
if (!count && !error) {
|
|
235
266
|
for (let i = 0; i < subs.length; i++) {
|
|
236
267
|
const callback = subs[i][0];
|
|
237
|
-
|
|
238
|
-
|
|
268
|
+
const errCallback = subs[i][1];
|
|
269
|
+
if (set && data.data == null) {
|
|
270
|
+
if (typeof errCallback === 'function') {
|
|
271
|
+
errCallback(new ClientError({ status: 404, statusText: 'Not Found' }, { textStatus: 'Not Found' }));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else if (typeof callback === 'function') {
|
|
275
|
+
if (set) {
|
|
276
|
+
callback(data.data);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
callback(data.value ?? null, data.event);
|
|
280
|
+
}
|
|
239
281
|
}
|
|
240
282
|
}
|
|
241
283
|
}
|
|
242
284
|
}
|
|
285
|
+
else if (error) {
|
|
286
|
+
for (let i = 0; i < this.errorCallbacks.length; i++) {
|
|
287
|
+
const callback = this.errorCallbacks[i];
|
|
288
|
+
if (callback) {
|
|
289
|
+
callback(data.error);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
243
294
|
if (count) {
|
|
244
295
|
for (let i = 0; i < subs.length; i++) {
|
|
245
296
|
const callback = subs[i][2];
|
|
@@ -248,6 +299,14 @@ class PubSub {
|
|
|
248
299
|
}
|
|
249
300
|
}
|
|
250
301
|
}
|
|
302
|
+
if (error) {
|
|
303
|
+
for (let i = 0; i < subs.length; i++) {
|
|
304
|
+
const callback = subs[i][1];
|
|
305
|
+
if (typeof callback === 'function') {
|
|
306
|
+
callback(data.error);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
251
310
|
}
|
|
252
311
|
_onclose(e) {
|
|
253
312
|
if (typeof console !== 'undefined' && !this.noConsole) {
|
|
@@ -259,7 +318,7 @@ class PubSub {
|
|
|
259
318
|
callback();
|
|
260
319
|
}
|
|
261
320
|
}
|
|
262
|
-
if (e.code !==
|
|
321
|
+
if (e.code !== 1000 &&
|
|
263
322
|
(typeof navigator === 'undefined' || navigator.onLine)) {
|
|
264
323
|
if (this.connection) {
|
|
265
324
|
this.connection.close();
|
|
@@ -276,6 +335,13 @@ class PubSub {
|
|
|
276
335
|
isConnectionOpen() {
|
|
277
336
|
return !!(this.connection && this.connection.readyState === this.WebSocket.OPEN);
|
|
278
337
|
}
|
|
338
|
+
isConnectionConnecting() {
|
|
339
|
+
return !!(this.connection &&
|
|
340
|
+
this.connection.readyState === this.WebSocket.CONNECTING);
|
|
341
|
+
}
|
|
342
|
+
isConnection() {
|
|
343
|
+
return this.isConnectionOpen() || this.isConnectionConnecting();
|
|
344
|
+
}
|
|
279
345
|
_subscribeQuery(query, callbacks) {
|
|
280
346
|
let isNewSubscription = false;
|
|
281
347
|
if (!this.subscriptions.queries.hasOwnProperty(query)) {
|
|
@@ -396,101 +462,103 @@ class PubSub {
|
|
|
396
462
|
uid: name,
|
|
397
463
|
});
|
|
398
464
|
}
|
|
399
|
-
updateArray(
|
|
465
|
+
updateArray(current, update) {
|
|
400
466
|
if (Array.isArray(update)) {
|
|
401
467
|
const newArr = [...update];
|
|
402
|
-
if (
|
|
403
|
-
|
|
468
|
+
if (current.length === 0) {
|
|
469
|
+
// This will happen on the first update from a subscribe.
|
|
470
|
+
current.splice(0, 0, ...newArr);
|
|
404
471
|
return;
|
|
405
472
|
}
|
|
406
473
|
const idMap = {};
|
|
407
|
-
const
|
|
474
|
+
const newEntities = [];
|
|
475
|
+
while (current.length) {
|
|
476
|
+
const first = current.shift();
|
|
477
|
+
if (!first) {
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
const guid = first.guid;
|
|
481
|
+
if (!guid) {
|
|
482
|
+
newEntities.push(first);
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
idMap[guid] = first;
|
|
486
|
+
}
|
|
408
487
|
for (let i = 0; i < newArr.length; i++) {
|
|
409
488
|
const entity = newArr[i];
|
|
410
|
-
|
|
411
|
-
|
|
489
|
+
const guid = entity.guid;
|
|
490
|
+
if (guid == null) {
|
|
491
|
+
continue;
|
|
412
492
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
else if (newArr[idMap[guid]].mdate !== oldArr[k].mdate) {
|
|
426
|
-
oldArr[k].$init(newArr[idMap[guid]].toJSON());
|
|
427
|
-
delete idMap[guid];
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
430
|
-
delete idMap[guid];
|
|
431
|
-
}
|
|
432
|
-
}
|
|
493
|
+
if (!idMap.hasOwnProperty(guid)) {
|
|
494
|
+
// It was added.
|
|
495
|
+
current.push(entity);
|
|
496
|
+
}
|
|
497
|
+
else if (idMap[guid].mdate !== entity.mdate) {
|
|
498
|
+
// It was modified.
|
|
499
|
+
idMap[guid].$init(entity.toJSON());
|
|
500
|
+
current.push(idMap[guid]);
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
// Item wasn't modified.
|
|
504
|
+
current.push(idMap[guid]);
|
|
433
505
|
}
|
|
434
506
|
}
|
|
435
|
-
|
|
436
|
-
if (a > b)
|
|
437
|
-
return -1;
|
|
438
|
-
if (a < b)
|
|
439
|
-
return 1;
|
|
440
|
-
return 0;
|
|
441
|
-
});
|
|
442
|
-
for (let n = 0; n < remove.length; n++) {
|
|
443
|
-
oldArr.splice(remove[n], 1);
|
|
444
|
-
}
|
|
445
|
-
for (let value of Object.values(idMap)) {
|
|
446
|
-
oldArr.splice(oldArr.length, 0, newArr[value]);
|
|
447
|
-
}
|
|
507
|
+
current.splice(current.length, 0, ...newEntities);
|
|
448
508
|
}
|
|
449
509
|
else if (update != null && update.hasOwnProperty('query')) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
510
|
+
const updates = 'multiple' in update && update.multiple ? update.messages : [update];
|
|
511
|
+
for (let curUpdate of updates) {
|
|
512
|
+
if ('removed' in curUpdate) {
|
|
513
|
+
for (let i = 0; i < current.length; i++) {
|
|
514
|
+
if (current[i] != null && current[i].guid === curUpdate.removed) {
|
|
515
|
+
current.splice(i, 1);
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
455
518
|
}
|
|
456
519
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
520
|
+
// Get the entity.
|
|
521
|
+
let entity = null;
|
|
522
|
+
if ('added' in curUpdate) {
|
|
523
|
+
// Check for it in the array already.
|
|
524
|
+
for (let i = 0; i < current.length; i++) {
|
|
525
|
+
if (current[i] != null && current[i].guid === curUpdate.added) {
|
|
526
|
+
entity = current.splice(i, 1)[0].$init(curUpdate.data);
|
|
527
|
+
}
|
|
463
528
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
if ('updated' in update) {
|
|
470
|
-
for (let i = 0; i < oldArr.length; i++) {
|
|
471
|
-
if (oldArr[i] != null && oldArr[i].guid === update.updated) {
|
|
472
|
-
entity = oldArr.splice(i, 1)[0].$init(update.data);
|
|
529
|
+
if (entity == null) {
|
|
530
|
+
// A new entity.
|
|
531
|
+
entity = this.nymph.initEntity(curUpdate.data);
|
|
473
532
|
}
|
|
474
533
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
let i;
|
|
483
|
-
if (reverse) {
|
|
484
|
-
for (i = 0; ((oldArr[i] ?? {})[sort] ?? 0) >= (entity[sort] ?? 0) &&
|
|
485
|
-
i < oldArr.length; i++)
|
|
486
|
-
;
|
|
534
|
+
if ('updated' in curUpdate) {
|
|
535
|
+
// Extract it from the array.
|
|
536
|
+
for (let i = 0; i < current.length; i++) {
|
|
537
|
+
if (current[i] != null && current[i].guid === curUpdate.updated) {
|
|
538
|
+
entity = current.splice(i, 1)[0].$init(curUpdate.data);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
487
541
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
542
|
+
if (entity != null) {
|
|
543
|
+
const query = JSON.parse(curUpdate.query);
|
|
544
|
+
// Insert the entity in order.
|
|
545
|
+
const sort = 'sort' in query[0] ? query[0].sort : 'cdate';
|
|
546
|
+
const reverse = query[0].hasOwnProperty('reverse')
|
|
547
|
+
? query[0].reverse
|
|
548
|
+
: false;
|
|
549
|
+
let i;
|
|
550
|
+
if (reverse) {
|
|
551
|
+
for (i = 0; ((current[i] ?? {})[sort] ?? 0) >= (entity[sort] ?? 0) &&
|
|
552
|
+
i < current.length; i++)
|
|
553
|
+
;
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
for (i = 0; ((current[i] ?? {})[sort] ?? 0) < (entity[sort] ?? 0) &&
|
|
557
|
+
i < current.length; i++)
|
|
558
|
+
;
|
|
559
|
+
}
|
|
560
|
+
current.splice(i, 0, entity);
|
|
492
561
|
}
|
|
493
|
-
oldArr.splice(i, 0, entity);
|
|
494
562
|
}
|
|
495
563
|
}
|
|
496
564
|
}
|
|
@@ -499,6 +567,7 @@ class PubSub {
|
|
|
499
567
|
if (!(prop in this)) {
|
|
500
568
|
throw new Error('Invalid event type.');
|
|
501
569
|
}
|
|
570
|
+
// @ts-ignore: The callback should always be the right type here.
|
|
502
571
|
this[prop].push(callback);
|
|
503
572
|
return () => this.off(event, callback);
|
|
504
573
|
}
|
|
@@ -507,29 +576,33 @@ class PubSub {
|
|
|
507
576
|
if (!(prop in this)) {
|
|
508
577
|
return false;
|
|
509
578
|
}
|
|
579
|
+
// @ts-ignore: The callback should always be the right type here.
|
|
510
580
|
const i = this[prop].indexOf(callback);
|
|
511
581
|
if (i > -1) {
|
|
512
582
|
this[prop].splice(i, 1);
|
|
513
583
|
}
|
|
514
584
|
return true;
|
|
515
585
|
}
|
|
516
|
-
|
|
517
|
-
authToken =
|
|
586
|
+
authenticate(authToken, switchToken = null) {
|
|
587
|
+
this.authToken = authToken;
|
|
588
|
+
this.switchToken = switchToken;
|
|
518
589
|
if (this.isConnectionOpen()) {
|
|
519
590
|
this._send({
|
|
520
591
|
action: 'authenticate',
|
|
521
|
-
|
|
592
|
+
authToken: this.authToken,
|
|
593
|
+
switchToken: this.switchToken,
|
|
522
594
|
});
|
|
523
595
|
}
|
|
524
596
|
}
|
|
525
597
|
}
|
|
526
|
-
|
|
527
|
-
|
|
598
|
+
export class PubSubSubscription {
|
|
599
|
+
query;
|
|
600
|
+
callbacks;
|
|
601
|
+
unsubscribe;
|
|
528
602
|
constructor(query, callbacks, unsubscribe) {
|
|
529
603
|
this.query = query;
|
|
530
604
|
this.callbacks = callbacks;
|
|
531
605
|
this.unsubscribe = unsubscribe;
|
|
532
606
|
}
|
|
533
607
|
}
|
|
534
|
-
exports.PubSubSubscription = PubSubSubscription;
|
|
535
608
|
//# sourceMappingURL=PubSub.js.map
|