gingersnap 0.22.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/_virtual/_tslib.cjs +102 -0
- package/_virtual/_tslib.mjs +93 -0
- package/data/AtomicValue.d.ts +15 -0
- package/data/bus.cjs +179 -0
- package/data/bus.d.ts +72 -0
- package/data/bus.mjs +177 -0
- package/data/decoders/index.d.ts +4 -0
- package/data/decoders/json.cjs +12 -0
- package/data/decoders/json.d.ts +7 -0
- package/data/decoders/json.mjs +10 -0
- package/data/decoders/msgpack.cjs +14 -0
- package/data/decoders/msgpack.d.ts +7 -0
- package/data/decoders/msgpack.mjs +12 -0
- package/data/decoders/protobuf.d.ts +13 -0
- package/data/decoders/string.cjs +12 -0
- package/data/decoders/string.d.ts +7 -0
- package/data/decoders/string.mjs +10 -0
- package/data/decoders/type.d.ts +7 -0
- package/data/decoders.cjs +11 -0
- package/data/decoders.mjs +3 -0
- package/data/model/credentials.cjs +114 -0
- package/data/model/credentials.d.ts +61 -0
- package/data/model/credentials.mjs +109 -0
- package/data/model/extra.cjs +88 -0
- package/data/model/extra.d.ts +5 -0
- package/data/model/extra.mjs +66 -0
- package/data/model/index.d.ts +6 -0
- package/data/model/model.cjs +541 -0
- package/data/model/model.d.ts +207 -0
- package/data/model/model.mjs +518 -0
- package/data/model/plugin.cjs +96 -0
- package/data/model/plugin.d.ts +38 -0
- package/data/model/plugin.mjs +72 -0
- package/data/model/property.cjs +310 -0
- package/data/model/property.d.ts +83 -0
- package/data/model/property.mjs +278 -0
- package/data/model/types.cjs +32 -0
- package/data/model/types.d.ts +28 -0
- package/data/model/types.mjs +32 -0
- package/data/model.cjs +43 -0
- package/data/model.mjs +6 -0
- package/data/signal.cjs +47 -0
- package/data/signal.d.ts +17 -0
- package/data/signal.mjs +45 -0
- package/data/store/index.d.ts +4 -0
- package/data/store/json.cjs +58 -0
- package/data/store/json.d.ts +18 -0
- package/data/store/json.mjs +56 -0
- package/data/store/manager.cjs +206 -0
- package/data/store/manager.d.ts +44 -0
- package/data/store/manager.mjs +203 -0
- package/data/store/web.cjs +92 -0
- package/data/store/web.d.ts +25 -0
- package/data/store/web.mjs +89 -0
- package/data/value.cjs +66 -0
- package/data/value.mjs +64 -0
- package/data-structures/array/CyclicalList.cjs +57 -0
- package/data-structures/array/CyclicalList.d.ts +12 -0
- package/data-structures/array/CyclicalList.mjs +55 -0
- package/data-structures/array/Pair.cjs +30 -0
- package/data-structures/array/Pair.d.ts +17 -0
- package/data-structures/array/Pair.mjs +27 -0
- package/data-structures/array/Stack.cjs +96 -0
- package/data-structures/array/Stack.d.ts +41 -0
- package/data-structures/array/Stack.mjs +94 -0
- package/data-structures/array/Triple.cjs +34 -0
- package/data-structures/array/Triple.d.ts +19 -0
- package/data-structures/array/Triple.mjs +31 -0
- package/data-structures/array/Tuple.d.ts +8 -0
- package/data-structures/array/index.d.ts +5 -0
- package/data-structures/array.cjs +15 -0
- package/data-structures/array.mjs +4 -0
- package/data-structures/object/BufferQueue.cjs +98 -0
- package/data-structures/object/BufferQueue.d.ts +21 -0
- package/data-structures/object/BufferQueue.mjs +77 -0
- package/data-structures/object/CyclicalObject.cjs +155 -0
- package/data-structures/object/CyclicalObject.d.ts +74 -0
- package/data-structures/object/CyclicalObject.mjs +134 -0
- package/data-structures/object/Queue.cjs +178 -0
- package/data-structures/object/Queue.d.ts +31 -0
- package/data-structures/object/Queue.mjs +176 -0
- package/data-structures/object/SimpleQueue.cjs +53 -0
- package/data-structures/object/SimpleQueue.d.ts +13 -0
- package/data-structures/object/SimpleQueue.mjs +51 -0
- package/data-structures/object/TimeableObject.cjs +73 -0
- package/data-structures/object/TimeableObject.d.ts +30 -0
- package/data-structures/object/TimeableObject.mjs +71 -0
- package/data-structures/object/WaitableObject.cjs +61 -0
- package/data-structures/object/WaitableObject.d.ts +29 -0
- package/data-structures/object/WaitableObject.mjs +59 -0
- package/data-structures/object/WatchableObject.cjs +251 -0
- package/data-structures/object/WatchableObject.d.ts +88 -0
- package/data-structures/object/WatchableObject.mjs +230 -0
- package/data-structures/object/index.d.ts +7 -0
- package/data-structures/object.cjs +23 -0
- package/data-structures/object.mjs +7 -0
- package/errors/AbortError.cjs +9 -0
- package/errors/AbortError.d.ts +5 -0
- package/errors/AbortError.mjs +7 -0
- package/errors/CallExecutionError.cjs +13 -0
- package/errors/CallExecutionError.d.ts +7 -0
- package/errors/CallExecutionError.mjs +11 -0
- package/errors/FutureCancelled.cjs +11 -0
- package/errors/FutureCancelled.d.ts +6 -0
- package/errors/FutureCancelled.mjs +9 -0
- package/errors/FutureError.cjs +11 -0
- package/errors/FutureError.d.ts +6 -0
- package/errors/FutureError.mjs +9 -0
- package/errors/IllegalArgumentsError.cjs +13 -0
- package/errors/IllegalArgumentsError.d.ts +7 -0
- package/errors/IllegalArgumentsError.mjs +11 -0
- package/errors/IllegalOperationError.cjs +6 -0
- package/errors/IllegalOperationError.d.ts +2 -0
- package/errors/IllegalOperationError.mjs +4 -0
- package/errors/InvalidType.cjs +6 -0
- package/errors/InvalidType.d.ts +2 -0
- package/errors/InvalidType.mjs +4 -0
- package/errors/InvalidValue.cjs +11 -0
- package/errors/InvalidValue.d.ts +4 -0
- package/errors/InvalidValue.mjs +9 -0
- package/errors/MissingArgumentsError.cjs +13 -0
- package/errors/MissingArgumentsError.d.ts +7 -0
- package/errors/MissingArgumentsError.mjs +11 -0
- package/errors/NetworkError.cjs +13 -0
- package/errors/NetworkError.d.ts +8 -0
- package/errors/NetworkError.mjs +11 -0
- package/errors/NoSuchElement.cjs +6 -0
- package/errors/NoSuchElement.d.ts +2 -0
- package/errors/NoSuchElement.mjs +4 -0
- package/errors/NotImplemented.cjs +9 -0
- package/errors/NotImplemented.d.ts +5 -0
- package/errors/NotImplemented.mjs +7 -0
- package/errors/ParsingError.cjs +10 -0
- package/errors/ParsingError.d.ts +5 -0
- package/errors/ParsingError.mjs +8 -0
- package/errors/QueueEmptyError.cjs +6 -0
- package/errors/QueueEmptyError.d.ts +2 -0
- package/errors/QueueEmptyError.mjs +4 -0
- package/errors/QueueFullError.cjs +6 -0
- package/errors/QueueFullError.d.ts +2 -0
- package/errors/QueueFullError.mjs +4 -0
- package/errors/StackEmptyError.cjs +6 -0
- package/errors/StackEmptyError.d.ts +2 -0
- package/errors/StackEmptyError.mjs +4 -0
- package/errors/StackFullError.cjs +6 -0
- package/errors/StackFullError.d.ts +2 -0
- package/errors/StackFullError.mjs +4 -0
- package/errors/StreamEnded.cjs +6 -0
- package/errors/StreamEnded.d.ts +2 -0
- package/errors/StreamEnded.mjs +4 -0
- package/errors/TimeoutError.cjs +11 -0
- package/errors/TimeoutError.d.ts +6 -0
- package/errors/TimeoutError.mjs +9 -0
- package/errors/ValueDestroyedError.cjs +6 -0
- package/errors/ValueDestroyedError.d.ts +2 -0
- package/errors/ValueDestroyedError.mjs +4 -0
- package/errors/VerificationError.cjs +9 -0
- package/errors/VerificationError.d.ts +5 -0
- package/errors/VerificationError.mjs +7 -0
- package/errors/index.d.ts +18 -0
- package/errors.cjs +41 -0
- package/errors.mjs +18 -0
- package/files.cjs +201 -0
- package/files.d.ts +31 -0
- package/files.mjs +180 -0
- package/functools/index.d.ts +31 -0
- package/functools.cjs +371 -0
- package/functools.mjs +334 -0
- package/future/future.cjs +570 -0
- package/future/future.d.ts +208 -0
- package/future/future.mjs +548 -0
- package/future/group.cjs +180 -0
- package/future/group.d.ts +82 -0
- package/future/group.mjs +159 -0
- package/future/index.d.ts +3 -0
- package/future/result.cjs +19 -0
- package/future/result.d.ts +18 -0
- package/future/result.mjs +17 -0
- package/future.cjs +11 -0
- package/future.mjs +3 -0
- package/managers/context.d.ts +8 -0
- package/managers/index.d.ts +1 -0
- package/managers.cjs +2 -0
- package/managers.mjs +1 -0
- package/mocks.cjs +301 -0
- package/mocks.d.ts +125 -0
- package/mocks.mjs +293 -0
- package/networking/EventSourceService.cjs +104 -0
- package/networking/EventSourceService.d.ts +11 -0
- package/networking/EventSourceService.mjs +83 -0
- package/networking/NetworkService.cjs +394 -0
- package/networking/NetworkService.d.ts +97 -0
- package/networking/NetworkService.mjs +373 -0
- package/networking/SocketService.cjs +218 -0
- package/networking/SocketService.d.ts +23 -0
- package/networking/SocketService.mjs +197 -0
- package/networking/decorators/index.d.ts +4 -0
- package/networking/decorators/options.cjs +289 -0
- package/networking/decorators/options.d.ts +148 -0
- package/networking/decorators/options.mjs +242 -0
- package/networking/decorators/requests.cjs +80 -0
- package/networking/decorators/requests.d.ts +34 -0
- package/networking/decorators/requests.mjs +52 -0
- package/networking/decorators/socket.cjs +81 -0
- package/networking/decorators/socket.d.ts +13 -0
- package/networking/decorators/socket.mjs +51 -0
- package/networking/http.cjs +69 -0
- package/networking/http.d.ts +66 -0
- package/networking/http.mjs +69 -0
- package/networking/index.d.ts +39 -0
- package/networking/request.cjs +18 -0
- package/networking/request.d.ts +9 -0
- package/networking/request.mjs +16 -0
- package/networking/types.cjs +37 -0
- package/networking/types.d.ts +132 -0
- package/networking/types.mjs +35 -0
- package/networking.cjs +91 -0
- package/networking.mjs +33 -0
- package/package.json +1 -0
- package/reflection/injector.cjs +43 -0
- package/reflection/injector.d.ts +3 -0
- package/reflection/injector.mjs +40 -0
- package/socket.cjs +239 -0
- package/socket.d.ts +65 -0
- package/socket.mjs +237 -0
- package/store.cjs +12 -0
- package/store.mjs +3 -0
- package/stream/call.cjs +157 -0
- package/stream/call.d.ts +66 -0
- package/stream/call.mjs +154 -0
- package/stream/collector.cjs +217 -0
- package/stream/collector.d.ts +14 -0
- package/stream/collector.mjs +215 -0
- package/stream/index.d.ts +257 -0
- package/stream/observable.cjs +110 -0
- package/stream/observable.d.ts +65 -0
- package/stream/observable.mjs +106 -0
- package/stream/state.cjs +10 -0
- package/stream/state.d.ts +5 -0
- package/stream/state.mjs +8 -0
- package/stream.cjs +1153 -0
- package/stream.mjs +1132 -0
- package/synchronize.cjs +106 -0
- package/synchronize.d.ts +54 -0
- package/synchronize.mjs +103 -0
- package/typing/types.d.ts +24 -0
- package/typing.cjs +2 -0
- package/typing.mjs +1 -0
- package/utils/parser.cjs +37 -0
- package/utils/parser.d.ts +7 -0
- package/utils/parser.mjs +16 -0
package/socket.cjs
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _tslib = require('./_virtual/_tslib.cjs');
|
|
4
|
+
var AbortError = require('./errors/AbortError.cjs');
|
|
5
|
+
var FutureCancelled = require('./errors/FutureCancelled.cjs');
|
|
6
|
+
var NetworkError = require('./errors/NetworkError.cjs');
|
|
7
|
+
require('./networking/decorators/options.cjs');
|
|
8
|
+
require('./networking/decorators/requests.cjs');
|
|
9
|
+
var http = require('./networking/http.cjs');
|
|
10
|
+
require('ramda');
|
|
11
|
+
require('uuid');
|
|
12
|
+
var stream = require('./stream.cjs');
|
|
13
|
+
var future = require('./future/future.cjs');
|
|
14
|
+
var synchronize = require('./synchronize.cjs');
|
|
15
|
+
var stream_state = require('./stream/state.cjs');
|
|
16
|
+
var WebSocket = require('modern-isomorphic-ws');
|
|
17
|
+
require('./data-structures/object/WatchableObject.cjs');
|
|
18
|
+
require('object-hash');
|
|
19
|
+
var Queue = require('./data-structures/object/Queue.cjs');
|
|
20
|
+
var Pair = require('./data-structures/array/Pair.cjs');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Future-based web sockets
|
|
24
|
+
*/
|
|
25
|
+
class StreamableWebSocket {
|
|
26
|
+
constructor(url, decoder, { retryOnDisconnect, cacheSize, cacheExpiryPeriod, exponentialFactor, backoffPeriodMs, } = {}, maxReconnectAttempt = 3) {
|
|
27
|
+
this.maxReconnectAttempt = maxReconnectAttempt;
|
|
28
|
+
this.connectionAttemptCount = 0;
|
|
29
|
+
this.signal = new AbortController().signal;
|
|
30
|
+
this.decoder = decoder;
|
|
31
|
+
this.socketListeners = [];
|
|
32
|
+
this.url = url;
|
|
33
|
+
this.cacheSize = cacheSize !== null && cacheSize !== void 0 ? cacheSize : 10000;
|
|
34
|
+
this.manuallyClosed = false;
|
|
35
|
+
this.retryOnDisconnect = retryOnDisconnect !== null && retryOnDisconnect !== void 0 ? retryOnDisconnect : true;
|
|
36
|
+
this.exponentialFactor = exponentialFactor !== null && exponentialFactor !== void 0 ? exponentialFactor : 2;
|
|
37
|
+
this.backoffPeriodMs = backoffPeriodMs !== null && backoffPeriodMs !== void 0 ? backoffPeriodMs : 10;
|
|
38
|
+
this.backoffPeriods = -1;
|
|
39
|
+
this.messageQueues = [];
|
|
40
|
+
this.evt = new EventTarget();
|
|
41
|
+
this.dataReadyEvent = new synchronize.FutureEvent();
|
|
42
|
+
this.dataProcessingLock = new synchronize.Lock();
|
|
43
|
+
}
|
|
44
|
+
get opened() {
|
|
45
|
+
return this.socket && this.socket.readyState === WebSocket.OPEN;
|
|
46
|
+
}
|
|
47
|
+
get closed() {
|
|
48
|
+
return this.socket && this.socket.readyState === WebSocket.CLOSED;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* opens the current web socket connection
|
|
52
|
+
*/
|
|
53
|
+
open() {
|
|
54
|
+
var _a;
|
|
55
|
+
if (!this.openFuture || ((_a = this.openFuture) === null || _a === void 0 ? void 0 : _a.failed)) {
|
|
56
|
+
this.closeFuture = new future.Future((resolve, reject, signal) => {
|
|
57
|
+
this.signal.addEventListener("abort", () => {
|
|
58
|
+
resolve();
|
|
59
|
+
});
|
|
60
|
+
signal.onabort = () => {
|
|
61
|
+
this.signal.removeEventListener("abort", resolve);
|
|
62
|
+
reject(new AbortError.AbortError());
|
|
63
|
+
};
|
|
64
|
+
}).schedule();
|
|
65
|
+
this.openFuture = new future.Future((resolve, reject, signal) => {
|
|
66
|
+
const functor = () => {
|
|
67
|
+
this.close();
|
|
68
|
+
};
|
|
69
|
+
signal.addEventListener("abort", functor);
|
|
70
|
+
let retrying = false;
|
|
71
|
+
const cancelError = this.addEventListener("error", () => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
var _a, _b;
|
|
73
|
+
if (this.retryOnDisconnect && !signal.aborted && this.connectionAttemptCount < this.maxReconnectAttempt) {
|
|
74
|
+
this.connectionAttemptCount++;
|
|
75
|
+
retrying = true;
|
|
76
|
+
(_a = this.getSocket()) === null || _a === void 0 ? void 0 : _a.close();
|
|
77
|
+
yield future.Future.sleep({
|
|
78
|
+
milliseconds: this.backoffPeriodMs * Math.pow(this.exponentialFactor, ++this.backoffPeriods),
|
|
79
|
+
});
|
|
80
|
+
this.createSocket();
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
this.connectionAttemptCount = 0;
|
|
84
|
+
retrying = false;
|
|
85
|
+
cancelError();
|
|
86
|
+
cancelOpen();
|
|
87
|
+
reject(new NetworkError.NetworkError(http.HTTPStatus.EXPECTATION_FAILED));
|
|
88
|
+
(_b = this.getSocket()) === null || _b === void 0 ? void 0 : _b.close();
|
|
89
|
+
}
|
|
90
|
+
}));
|
|
91
|
+
const cancelOpen = this.addEventListener("open", () => {
|
|
92
|
+
this.connectionAttemptCount = 0;
|
|
93
|
+
this.backoffPeriods = -1;
|
|
94
|
+
retrying = false;
|
|
95
|
+
resolve();
|
|
96
|
+
signal.removeEventListener("abort", functor);
|
|
97
|
+
cancelError();
|
|
98
|
+
cancelOpen();
|
|
99
|
+
});
|
|
100
|
+
const cancelClose = this.addEventListener("close", () => {
|
|
101
|
+
if (retrying)
|
|
102
|
+
return;
|
|
103
|
+
if (!this.manuallyClosed && this.retryOnDisconnect && !signal.aborted) {
|
|
104
|
+
delete this.openFuture;
|
|
105
|
+
cancelError();
|
|
106
|
+
cancelOpen();
|
|
107
|
+
cancelClose();
|
|
108
|
+
this.open()
|
|
109
|
+
.thenApply(() => resolve())
|
|
110
|
+
.catch(reject);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
retrying = false;
|
|
114
|
+
this.signal.dispatchEvent(new CustomEvent("abort"));
|
|
115
|
+
cancelQueue();
|
|
116
|
+
reject(new NetworkError.NetworkError(http.HTTPStatus.EXPECTATION_FAILED));
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
const cancelQueue = this.addEventListener("message", (evt) => {
|
|
120
|
+
const data = evt.data instanceof ArrayBuffer ? evt.data : new TextEncoder().encode(evt.data).buffer;
|
|
121
|
+
const result = this.decoder.decode(data);
|
|
122
|
+
for (const value of this.messageQueues) {
|
|
123
|
+
if (value instanceof Pair.Pair && value.second(result)) {
|
|
124
|
+
value.first.enqueue(result);
|
|
125
|
+
}
|
|
126
|
+
else if (Array.isArray(value)) {
|
|
127
|
+
value.push(result);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
this.dataReadyEvent.set();
|
|
131
|
+
});
|
|
132
|
+
this.createSocket();
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return this.openFuture;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Wait for the socket connection closed.
|
|
139
|
+
* @remark
|
|
140
|
+
* This doesn't actually attempt to close the socket, only waits for the connection to close
|
|
141
|
+
*/
|
|
142
|
+
closedFuture() {
|
|
143
|
+
if (this.closeFuture)
|
|
144
|
+
return this.closeFuture;
|
|
145
|
+
throw new NetworkError.NetworkError(http.HTTPStatus.FORBIDDEN, "Stream not opened");
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Closes the socket if currently open
|
|
149
|
+
*/
|
|
150
|
+
close() {
|
|
151
|
+
var _a;
|
|
152
|
+
this.manuallyClosed = true;
|
|
153
|
+
(_a = this.getSocket()) === null || _a === void 0 ? void 0 : _a.close();
|
|
154
|
+
this.messageQueues = [];
|
|
155
|
+
this.signal.dispatchEvent(new CustomEvent("abort"));
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Sends data via socket
|
|
159
|
+
* @param data
|
|
160
|
+
*/
|
|
161
|
+
send(data) {
|
|
162
|
+
var _a;
|
|
163
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
164
|
+
(_a = this.getSocket()) === null || _a === void 0 ? void 0 : _a.send(data instanceof Blob ? yield data.arrayBuffer() : data);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
streamView(lens, objectMaxSize, expiryPeriod) {
|
|
168
|
+
const queue = new Queue.Queue(objectMaxSize, expiryPeriod);
|
|
169
|
+
const tuple = Pair.pair(queue, lens);
|
|
170
|
+
this.messageQueues.push(tuple);
|
|
171
|
+
return queue.streamEntries.cancelOnSignal(this.signal).onCompletion(() => {
|
|
172
|
+
this.messageQueues = this.messageQueues.filter((v) => v !== tuple);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Gets the stream for messages received via this socket
|
|
177
|
+
*/
|
|
178
|
+
stream() {
|
|
179
|
+
const queue = [];
|
|
180
|
+
this.messageQueues.push(queue);
|
|
181
|
+
return new stream.Stream((signal) => {
|
|
182
|
+
const data = queue.shift();
|
|
183
|
+
if (data === undefined) {
|
|
184
|
+
this.dataReadyEvent.clear();
|
|
185
|
+
return this.dataReadyEvent
|
|
186
|
+
.wait()
|
|
187
|
+
.thenApply(() => queue.shift())
|
|
188
|
+
.catch((error) => {
|
|
189
|
+
if (error instanceof FutureCancelled.FutureCancelled) {
|
|
190
|
+
return new stream_state.ExecutorState(true);
|
|
191
|
+
}
|
|
192
|
+
throw error;
|
|
193
|
+
})
|
|
194
|
+
.registerSignal(signal);
|
|
195
|
+
}
|
|
196
|
+
return data;
|
|
197
|
+
})
|
|
198
|
+
.cancelOnSignal(this.signal)
|
|
199
|
+
.onCompletion(() => {
|
|
200
|
+
this.messageQueues = this.messageQueues.filter((v) => v !== queue);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
addEventListener(type, functor) {
|
|
204
|
+
this.socketListeners.push([type, functor]);
|
|
205
|
+
if (this.socket) {
|
|
206
|
+
this.socket.addEventListener(type, functor);
|
|
207
|
+
}
|
|
208
|
+
return () => {
|
|
209
|
+
this.socketListeners = this.socketListeners.filter(([t, f]) => f !== functor && t !== type);
|
|
210
|
+
if (this.socket)
|
|
211
|
+
this.socket.removeEventListener(type, functor);
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
createSocket() {
|
|
215
|
+
const socket = new WebSocket(this.url);
|
|
216
|
+
socket.binaryType = "arraybuffer";
|
|
217
|
+
this.socketListeners.forEach(([type, functor]) => socket.addEventListener(type, functor));
|
|
218
|
+
this.socket = socket;
|
|
219
|
+
future.Future.sleep(2)
|
|
220
|
+
.thenApply(() => {
|
|
221
|
+
if (socket.readyState === 0) {
|
|
222
|
+
socket.close();
|
|
223
|
+
const evt = new Event("error");
|
|
224
|
+
this.socketListeners.forEach(([type, functor]) => {
|
|
225
|
+
if (type === "error") {
|
|
226
|
+
functor(evt);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
.schedule();
|
|
232
|
+
return socket;
|
|
233
|
+
}
|
|
234
|
+
getSocket() {
|
|
235
|
+
return this.socket;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
exports.StreamableWebSocket = StreamableWebSocket;
|
package/socket.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Stream } from "./stream";
|
|
2
|
+
import { Future, WaitPeriod } from "./future";
|
|
3
|
+
import { Decoder } from "./data/decoders";
|
|
4
|
+
interface WebSocketConfiguration {
|
|
5
|
+
retryOnDisconnect?: boolean;
|
|
6
|
+
cacheSize?: number;
|
|
7
|
+
cacheExpiryPeriod?: WaitPeriod;
|
|
8
|
+
exponentialFactor?: number;
|
|
9
|
+
backoffPeriodMs?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Future-based web sockets
|
|
13
|
+
*/
|
|
14
|
+
export declare class StreamableWebSocket<T> {
|
|
15
|
+
private readonly maxReconnectAttempt;
|
|
16
|
+
private readonly retryOnDisconnect;
|
|
17
|
+
private openFuture?;
|
|
18
|
+
private closeFuture?;
|
|
19
|
+
private socketListeners;
|
|
20
|
+
private messageQueues;
|
|
21
|
+
private readonly url;
|
|
22
|
+
private socket?;
|
|
23
|
+
private manuallyClosed;
|
|
24
|
+
private readonly cacheSize;
|
|
25
|
+
private readonly backoffPeriodMs;
|
|
26
|
+
private readonly exponentialFactor;
|
|
27
|
+
private readonly signal;
|
|
28
|
+
private backoffPeriods;
|
|
29
|
+
private readonly evt;
|
|
30
|
+
private readonly dataReadyEvent;
|
|
31
|
+
private readonly dataProcessingLock;
|
|
32
|
+
readonly decoder: Decoder<T>;
|
|
33
|
+
private connectionAttemptCount;
|
|
34
|
+
constructor(url: string, decoder: Decoder<T>, { retryOnDisconnect, cacheSize, cacheExpiryPeriod, exponentialFactor, backoffPeriodMs, }?: WebSocketConfiguration, maxReconnectAttempt?: number);
|
|
35
|
+
get opened(): boolean;
|
|
36
|
+
get closed(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* opens the current web socket connection
|
|
39
|
+
*/
|
|
40
|
+
open(): Future<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Wait for the socket connection closed.
|
|
43
|
+
* @remark
|
|
44
|
+
* This doesn't actually attempt to close the socket, only waits for the connection to close
|
|
45
|
+
*/
|
|
46
|
+
closedFuture(): Future<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Closes the socket if currently open
|
|
49
|
+
*/
|
|
50
|
+
close(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Sends data via socket
|
|
53
|
+
* @param data
|
|
54
|
+
*/
|
|
55
|
+
send(data: string | ArrayBufferView | Blob | ArrayBufferLike): Promise<void>;
|
|
56
|
+
streamView(lens: (v: T) => boolean, objectMaxSize?: number, expiryPeriod?: WaitPeriod): Stream<T>;
|
|
57
|
+
/**
|
|
58
|
+
* Gets the stream for messages received via this socket
|
|
59
|
+
*/
|
|
60
|
+
stream(): Stream<T>;
|
|
61
|
+
private addEventListener;
|
|
62
|
+
private createSocket;
|
|
63
|
+
private getSocket;
|
|
64
|
+
}
|
|
65
|
+
export {};
|
package/socket.mjs
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { __awaiter } from './_virtual/_tslib.mjs';
|
|
2
|
+
import { AbortError } from './errors/AbortError.mjs';
|
|
3
|
+
import { FutureCancelled } from './errors/FutureCancelled.mjs';
|
|
4
|
+
import { NetworkError } from './errors/NetworkError.mjs';
|
|
5
|
+
import './networking/decorators/options.mjs';
|
|
6
|
+
import './networking/decorators/requests.mjs';
|
|
7
|
+
import { HTTPStatus } from './networking/http.mjs';
|
|
8
|
+
import 'ramda';
|
|
9
|
+
import 'uuid';
|
|
10
|
+
import { Stream } from './stream.mjs';
|
|
11
|
+
import { Future } from './future/future.mjs';
|
|
12
|
+
import { FutureEvent, Lock } from './synchronize.mjs';
|
|
13
|
+
import { ExecutorState } from './stream/state.mjs';
|
|
14
|
+
import WebSocket from 'modern-isomorphic-ws';
|
|
15
|
+
import './data-structures/object/WatchableObject.mjs';
|
|
16
|
+
import 'object-hash';
|
|
17
|
+
import { Queue } from './data-structures/object/Queue.mjs';
|
|
18
|
+
import { Pair, pair } from './data-structures/array/Pair.mjs';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Future-based web sockets
|
|
22
|
+
*/
|
|
23
|
+
class StreamableWebSocket {
|
|
24
|
+
constructor(url, decoder, { retryOnDisconnect, cacheSize, cacheExpiryPeriod, exponentialFactor, backoffPeriodMs, } = {}, maxReconnectAttempt = 3) {
|
|
25
|
+
this.maxReconnectAttempt = maxReconnectAttempt;
|
|
26
|
+
this.connectionAttemptCount = 0;
|
|
27
|
+
this.signal = new AbortController().signal;
|
|
28
|
+
this.decoder = decoder;
|
|
29
|
+
this.socketListeners = [];
|
|
30
|
+
this.url = url;
|
|
31
|
+
this.cacheSize = cacheSize !== null && cacheSize !== void 0 ? cacheSize : 10000;
|
|
32
|
+
this.manuallyClosed = false;
|
|
33
|
+
this.retryOnDisconnect = retryOnDisconnect !== null && retryOnDisconnect !== void 0 ? retryOnDisconnect : true;
|
|
34
|
+
this.exponentialFactor = exponentialFactor !== null && exponentialFactor !== void 0 ? exponentialFactor : 2;
|
|
35
|
+
this.backoffPeriodMs = backoffPeriodMs !== null && backoffPeriodMs !== void 0 ? backoffPeriodMs : 10;
|
|
36
|
+
this.backoffPeriods = -1;
|
|
37
|
+
this.messageQueues = [];
|
|
38
|
+
this.evt = new EventTarget();
|
|
39
|
+
this.dataReadyEvent = new FutureEvent();
|
|
40
|
+
this.dataProcessingLock = new Lock();
|
|
41
|
+
}
|
|
42
|
+
get opened() {
|
|
43
|
+
return this.socket && this.socket.readyState === WebSocket.OPEN;
|
|
44
|
+
}
|
|
45
|
+
get closed() {
|
|
46
|
+
return this.socket && this.socket.readyState === WebSocket.CLOSED;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* opens the current web socket connection
|
|
50
|
+
*/
|
|
51
|
+
open() {
|
|
52
|
+
var _a;
|
|
53
|
+
if (!this.openFuture || ((_a = this.openFuture) === null || _a === void 0 ? void 0 : _a.failed)) {
|
|
54
|
+
this.closeFuture = new Future((resolve, reject, signal) => {
|
|
55
|
+
this.signal.addEventListener("abort", () => {
|
|
56
|
+
resolve();
|
|
57
|
+
});
|
|
58
|
+
signal.onabort = () => {
|
|
59
|
+
this.signal.removeEventListener("abort", resolve);
|
|
60
|
+
reject(new AbortError());
|
|
61
|
+
};
|
|
62
|
+
}).schedule();
|
|
63
|
+
this.openFuture = new Future((resolve, reject, signal) => {
|
|
64
|
+
const functor = () => {
|
|
65
|
+
this.close();
|
|
66
|
+
};
|
|
67
|
+
signal.addEventListener("abort", functor);
|
|
68
|
+
let retrying = false;
|
|
69
|
+
const cancelError = this.addEventListener("error", () => __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
if (this.retryOnDisconnect && !signal.aborted && this.connectionAttemptCount < this.maxReconnectAttempt) {
|
|
72
|
+
this.connectionAttemptCount++;
|
|
73
|
+
retrying = true;
|
|
74
|
+
(_a = this.getSocket()) === null || _a === void 0 ? void 0 : _a.close();
|
|
75
|
+
yield Future.sleep({
|
|
76
|
+
milliseconds: this.backoffPeriodMs * Math.pow(this.exponentialFactor, ++this.backoffPeriods),
|
|
77
|
+
});
|
|
78
|
+
this.createSocket();
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.connectionAttemptCount = 0;
|
|
82
|
+
retrying = false;
|
|
83
|
+
cancelError();
|
|
84
|
+
cancelOpen();
|
|
85
|
+
reject(new NetworkError(HTTPStatus.EXPECTATION_FAILED));
|
|
86
|
+
(_b = this.getSocket()) === null || _b === void 0 ? void 0 : _b.close();
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
89
|
+
const cancelOpen = this.addEventListener("open", () => {
|
|
90
|
+
this.connectionAttemptCount = 0;
|
|
91
|
+
this.backoffPeriods = -1;
|
|
92
|
+
retrying = false;
|
|
93
|
+
resolve();
|
|
94
|
+
signal.removeEventListener("abort", functor);
|
|
95
|
+
cancelError();
|
|
96
|
+
cancelOpen();
|
|
97
|
+
});
|
|
98
|
+
const cancelClose = this.addEventListener("close", () => {
|
|
99
|
+
if (retrying)
|
|
100
|
+
return;
|
|
101
|
+
if (!this.manuallyClosed && this.retryOnDisconnect && !signal.aborted) {
|
|
102
|
+
delete this.openFuture;
|
|
103
|
+
cancelError();
|
|
104
|
+
cancelOpen();
|
|
105
|
+
cancelClose();
|
|
106
|
+
this.open()
|
|
107
|
+
.thenApply(() => resolve())
|
|
108
|
+
.catch(reject);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
retrying = false;
|
|
112
|
+
this.signal.dispatchEvent(new CustomEvent("abort"));
|
|
113
|
+
cancelQueue();
|
|
114
|
+
reject(new NetworkError(HTTPStatus.EXPECTATION_FAILED));
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
const cancelQueue = this.addEventListener("message", (evt) => {
|
|
118
|
+
const data = evt.data instanceof ArrayBuffer ? evt.data : new TextEncoder().encode(evt.data).buffer;
|
|
119
|
+
const result = this.decoder.decode(data);
|
|
120
|
+
for (const value of this.messageQueues) {
|
|
121
|
+
if (value instanceof Pair && value.second(result)) {
|
|
122
|
+
value.first.enqueue(result);
|
|
123
|
+
}
|
|
124
|
+
else if (Array.isArray(value)) {
|
|
125
|
+
value.push(result);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
this.dataReadyEvent.set();
|
|
129
|
+
});
|
|
130
|
+
this.createSocket();
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return this.openFuture;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Wait for the socket connection closed.
|
|
137
|
+
* @remark
|
|
138
|
+
* This doesn't actually attempt to close the socket, only waits for the connection to close
|
|
139
|
+
*/
|
|
140
|
+
closedFuture() {
|
|
141
|
+
if (this.closeFuture)
|
|
142
|
+
return this.closeFuture;
|
|
143
|
+
throw new NetworkError(HTTPStatus.FORBIDDEN, "Stream not opened");
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Closes the socket if currently open
|
|
147
|
+
*/
|
|
148
|
+
close() {
|
|
149
|
+
var _a;
|
|
150
|
+
this.manuallyClosed = true;
|
|
151
|
+
(_a = this.getSocket()) === null || _a === void 0 ? void 0 : _a.close();
|
|
152
|
+
this.messageQueues = [];
|
|
153
|
+
this.signal.dispatchEvent(new CustomEvent("abort"));
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Sends data via socket
|
|
157
|
+
* @param data
|
|
158
|
+
*/
|
|
159
|
+
send(data) {
|
|
160
|
+
var _a;
|
|
161
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
162
|
+
(_a = this.getSocket()) === null || _a === void 0 ? void 0 : _a.send(data instanceof Blob ? yield data.arrayBuffer() : data);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
streamView(lens, objectMaxSize, expiryPeriod) {
|
|
166
|
+
const queue = new Queue(objectMaxSize, expiryPeriod);
|
|
167
|
+
const tuple = pair(queue, lens);
|
|
168
|
+
this.messageQueues.push(tuple);
|
|
169
|
+
return queue.streamEntries.cancelOnSignal(this.signal).onCompletion(() => {
|
|
170
|
+
this.messageQueues = this.messageQueues.filter((v) => v !== tuple);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Gets the stream for messages received via this socket
|
|
175
|
+
*/
|
|
176
|
+
stream() {
|
|
177
|
+
const queue = [];
|
|
178
|
+
this.messageQueues.push(queue);
|
|
179
|
+
return new Stream((signal) => {
|
|
180
|
+
const data = queue.shift();
|
|
181
|
+
if (data === undefined) {
|
|
182
|
+
this.dataReadyEvent.clear();
|
|
183
|
+
return this.dataReadyEvent
|
|
184
|
+
.wait()
|
|
185
|
+
.thenApply(() => queue.shift())
|
|
186
|
+
.catch((error) => {
|
|
187
|
+
if (error instanceof FutureCancelled) {
|
|
188
|
+
return new ExecutorState(true);
|
|
189
|
+
}
|
|
190
|
+
throw error;
|
|
191
|
+
})
|
|
192
|
+
.registerSignal(signal);
|
|
193
|
+
}
|
|
194
|
+
return data;
|
|
195
|
+
})
|
|
196
|
+
.cancelOnSignal(this.signal)
|
|
197
|
+
.onCompletion(() => {
|
|
198
|
+
this.messageQueues = this.messageQueues.filter((v) => v !== queue);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
addEventListener(type, functor) {
|
|
202
|
+
this.socketListeners.push([type, functor]);
|
|
203
|
+
if (this.socket) {
|
|
204
|
+
this.socket.addEventListener(type, functor);
|
|
205
|
+
}
|
|
206
|
+
return () => {
|
|
207
|
+
this.socketListeners = this.socketListeners.filter(([t, f]) => f !== functor && t !== type);
|
|
208
|
+
if (this.socket)
|
|
209
|
+
this.socket.removeEventListener(type, functor);
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
createSocket() {
|
|
213
|
+
const socket = new WebSocket(this.url);
|
|
214
|
+
socket.binaryType = "arraybuffer";
|
|
215
|
+
this.socketListeners.forEach(([type, functor]) => socket.addEventListener(type, functor));
|
|
216
|
+
this.socket = socket;
|
|
217
|
+
Future.sleep(2)
|
|
218
|
+
.thenApply(() => {
|
|
219
|
+
if (socket.readyState === 0) {
|
|
220
|
+
socket.close();
|
|
221
|
+
const evt = new Event("error");
|
|
222
|
+
this.socketListeners.forEach(([type, functor]) => {
|
|
223
|
+
if (type === "error") {
|
|
224
|
+
functor(evt);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
.schedule();
|
|
230
|
+
return socket;
|
|
231
|
+
}
|
|
232
|
+
getSocket() {
|
|
233
|
+
return this.socket;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export { StreamableWebSocket };
|
package/store.cjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var manager = require('./data/store/manager.cjs');
|
|
4
|
+
var web = require('./data/store/web.cjs');
|
|
5
|
+
var json = require('./data/store/json.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports.CacheManager = manager.CacheManager;
|
|
10
|
+
exports.LocalWebStore = web.LocalWebStore;
|
|
11
|
+
exports.SessionWebStore = web.SessionWebStore;
|
|
12
|
+
exports.JSONFileStore = json.JSONFileStore;
|
package/store.mjs
ADDED