@camera.ui/rpc 1.0.3 → 1.0.4
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/externals/nats.js/core/src/authenticator.ts +159 -0
- package/externals/nats.js/core/src/bench.ts +426 -0
- package/externals/nats.js/core/src/codec.ts +28 -0
- package/externals/nats.js/core/src/core.ts +1219 -0
- package/externals/nats.js/core/src/databuffer.ts +129 -0
- package/externals/nats.js/core/src/denobuffer.ts +248 -0
- package/externals/nats.js/core/src/encoders.ts +53 -0
- package/externals/nats.js/core/src/errors.ts +300 -0
- package/externals/nats.js/core/src/headers.ts +315 -0
- package/externals/nats.js/core/src/heartbeats.ts +114 -0
- package/externals/nats.js/core/src/idleheartbeat_monitor.ts +140 -0
- package/externals/nats.js/core/src/internal_mod.ts +167 -0
- package/externals/nats.js/core/src/ipparser.ts +215 -0
- package/externals/nats.js/core/src/mod.ts +113 -0
- package/externals/nats.js/core/src/msg.ts +120 -0
- package/externals/nats.js/core/src/muxsubscription.ts +111 -0
- package/externals/nats.js/core/src/nats.ts +650 -0
- package/externals/nats.js/core/src/nkeys.ts +1 -0
- package/externals/nats.js/core/src/nuid.ts +16 -0
- package/externals/nats.js/core/src/options.ts +202 -0
- package/externals/nats.js/core/src/parser.ts +756 -0
- package/externals/nats.js/core/src/protocol.ts +1304 -0
- package/externals/nats.js/core/src/queued_iterator.ts +171 -0
- package/externals/nats.js/core/src/request.ts +177 -0
- package/externals/nats.js/core/src/semver.ts +165 -0
- package/externals/nats.js/core/src/servers.ts +424 -0
- package/externals/nats.js/core/src/transport.ts +117 -0
- package/externals/nats.js/core/src/types.ts +17 -0
- package/externals/nats.js/core/src/util.ts +367 -0
- package/externals/nats.js/core/src/version.ts +2 -0
- package/externals/nats.js/core/src/ws_transport.ts +391 -0
- package/package.json +2 -1
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2018-2023 The NATS Authors
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { deferred } from "./util.ts";
|
|
17
|
+
import { ProtocolHandler, SubscriptionImpl } from "./protocol.ts";
|
|
18
|
+
import { Empty } from "./encoders.ts";
|
|
19
|
+
import { headers } from "./headers.ts";
|
|
20
|
+
|
|
21
|
+
import type { Features, SemVer } from "./semver.ts";
|
|
22
|
+
import { parseSemVer } from "./semver.ts";
|
|
23
|
+
|
|
24
|
+
import { parseOptions } from "./options.ts";
|
|
25
|
+
import { QueuedIteratorImpl } from "./queued_iterator.ts";
|
|
26
|
+
import type { RequestManyOptionsInternal } from "./request.ts";
|
|
27
|
+
import { RequestMany, RequestOne } from "./request.ts";
|
|
28
|
+
|
|
29
|
+
import type {
|
|
30
|
+
ConnectionClosedListener,
|
|
31
|
+
ConnectionOptions,
|
|
32
|
+
Context,
|
|
33
|
+
Msg,
|
|
34
|
+
NatsConnection,
|
|
35
|
+
Payload,
|
|
36
|
+
PublishOptions,
|
|
37
|
+
QueuedIterator,
|
|
38
|
+
RequestManyOptions,
|
|
39
|
+
RequestOptions,
|
|
40
|
+
Server,
|
|
41
|
+
ServerInfo,
|
|
42
|
+
Stats,
|
|
43
|
+
Status,
|
|
44
|
+
Subscription,
|
|
45
|
+
SubscriptionOptions,
|
|
46
|
+
} from "./core.ts";
|
|
47
|
+
import { createInbox } from "./core.ts";
|
|
48
|
+
import { errors, InvalidArgumentError, TimeoutError } from "./errors.ts";
|
|
49
|
+
|
|
50
|
+
const whitespaceRegex = /[ \n\r\t]/;
|
|
51
|
+
|
|
52
|
+
export class NatsConnectionImpl implements NatsConnection {
|
|
53
|
+
options: ConnectionOptions;
|
|
54
|
+
protocol!: ProtocolHandler;
|
|
55
|
+
draining: boolean;
|
|
56
|
+
closeListeners?: CloseListeners;
|
|
57
|
+
|
|
58
|
+
private constructor(opts: ConnectionOptions) {
|
|
59
|
+
this.draining = false;
|
|
60
|
+
this.options = parseOptions(opts);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public static connect(opts: ConnectionOptions = {}): Promise<NatsConnection> {
|
|
64
|
+
return new Promise<NatsConnection>((resolve, reject) => {
|
|
65
|
+
const nc = new NatsConnectionImpl(opts);
|
|
66
|
+
ProtocolHandler.connect(nc.options, nc)
|
|
67
|
+
.then((ph: ProtocolHandler) => {
|
|
68
|
+
nc.protocol = ph;
|
|
69
|
+
resolve(nc);
|
|
70
|
+
})
|
|
71
|
+
.catch((err: Error) => {
|
|
72
|
+
reject(err);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
closed(): Promise<void | Error> {
|
|
78
|
+
return this.protocol.closed;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async close() {
|
|
82
|
+
await this.protocol.close();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// camera.ui fork patch — see ProtocolHandler.abortClose for semantics.
|
|
86
|
+
abortClose(err?: Error): void {
|
|
87
|
+
this.protocol.abortClose(err);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
_check(subject: string, sub: boolean, pub: boolean) {
|
|
91
|
+
if (this.isClosed()) {
|
|
92
|
+
throw new errors.ClosedConnectionError();
|
|
93
|
+
}
|
|
94
|
+
if (sub && this.isDraining()) {
|
|
95
|
+
throw new errors.DrainingConnectionError();
|
|
96
|
+
}
|
|
97
|
+
if (pub && this.protocol.noMorePublishing) {
|
|
98
|
+
throw new errors.DrainingConnectionError();
|
|
99
|
+
}
|
|
100
|
+
subject = subject || "";
|
|
101
|
+
if (subject.length === 0 || whitespaceRegex.test(subject)) {
|
|
102
|
+
throw new errors.InvalidSubjectError(subject);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
publish(
|
|
107
|
+
subject: string,
|
|
108
|
+
data?: Payload,
|
|
109
|
+
options?: PublishOptions,
|
|
110
|
+
): void {
|
|
111
|
+
this._check(subject, false, true);
|
|
112
|
+
if (options?.reply) {
|
|
113
|
+
this._check(options.reply, false, true);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (typeof options?.traceOnly === "boolean") {
|
|
117
|
+
const hdrs = options.headers || headers();
|
|
118
|
+
hdrs.set("Nats-Trace-Only", "true");
|
|
119
|
+
options.headers = hdrs;
|
|
120
|
+
}
|
|
121
|
+
if (typeof options?.traceDestination === "string") {
|
|
122
|
+
const hdrs = options.headers || headers();
|
|
123
|
+
hdrs.set("Nats-Trace-Dest", options.traceDestination);
|
|
124
|
+
options.headers = hdrs;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.protocol.publish(subject, data, options);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
publishMessage(msg: Msg): void {
|
|
131
|
+
return this.publish(msg.subject, msg.data, {
|
|
132
|
+
reply: msg.reply,
|
|
133
|
+
headers: msg.headers,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
respondMessage(msg: Msg): boolean {
|
|
138
|
+
if (msg.reply) {
|
|
139
|
+
this.publish(msg.reply, msg.data, {
|
|
140
|
+
reply: msg.reply,
|
|
141
|
+
headers: msg.headers,
|
|
142
|
+
});
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
subscribe(
|
|
149
|
+
subject: string,
|
|
150
|
+
opts: SubscriptionOptions = {},
|
|
151
|
+
): Subscription {
|
|
152
|
+
this._check(subject, true, false);
|
|
153
|
+
const sub = new SubscriptionImpl(this.protocol, subject, opts);
|
|
154
|
+
|
|
155
|
+
if (typeof opts.callback !== "function" && typeof opts.slow === "number") {
|
|
156
|
+
sub.setSlowNotificationFn(opts.slow, (pending: number) => {
|
|
157
|
+
this.protocol.dispatchStatus({
|
|
158
|
+
type: "slowConsumer",
|
|
159
|
+
sub,
|
|
160
|
+
pending,
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
this.protocol.subscribe(sub);
|
|
165
|
+
return sub;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
_resub(s: Subscription, subject: string, max?: number) {
|
|
169
|
+
this._check(subject, true, false);
|
|
170
|
+
const si = s as SubscriptionImpl;
|
|
171
|
+
// FIXME: need way of understanding a callbacks processed
|
|
172
|
+
// count without it, we cannot really do much - ie
|
|
173
|
+
// for rejected messages, the count would be lower, etc.
|
|
174
|
+
// To handle cases were for example KV is building a map
|
|
175
|
+
// the consumer would say how many messages we need to do
|
|
176
|
+
// a proper build before we can handle updates.
|
|
177
|
+
si.max = max; // this might clear it
|
|
178
|
+
if (max) {
|
|
179
|
+
// we cannot auto-unsub, because we don't know the
|
|
180
|
+
// number of messages we processed vs received
|
|
181
|
+
// allow the auto-unsub on processMsg to work if they
|
|
182
|
+
// we were called with a new max
|
|
183
|
+
si.max = max + si.received;
|
|
184
|
+
}
|
|
185
|
+
this.protocol.resub(si, subject);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// possibilities are:
|
|
189
|
+
// stop on error or any non-100 status
|
|
190
|
+
// AND:
|
|
191
|
+
// - wait for timer
|
|
192
|
+
// - wait for n messages or timer
|
|
193
|
+
// - wait for unknown messages, done when empty or reset timer expires (with possible alt wait)
|
|
194
|
+
// - wait for unknown messages, done when an empty payload is received or timer expires (with possible alt wait)
|
|
195
|
+
requestMany(
|
|
196
|
+
subject: string,
|
|
197
|
+
data: Payload = Empty,
|
|
198
|
+
opts: Partial<RequestManyOptions> = { maxWait: 1000, maxMessages: -1 },
|
|
199
|
+
): Promise<QueuedIterator<Msg>> {
|
|
200
|
+
const asyncTraces = !(this.protocol.options.noAsyncTraces || false);
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
this._check(subject, true, true);
|
|
204
|
+
} catch (err) {
|
|
205
|
+
return Promise.reject(err);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
opts.strategy = opts.strategy || "timer";
|
|
209
|
+
opts.maxWait = opts.maxWait || 1000;
|
|
210
|
+
if (opts.maxWait < 1) {
|
|
211
|
+
return Promise.reject(
|
|
212
|
+
InvalidArgumentError.format("timeout", "must be greater than 0"),
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// the iterator for user results
|
|
217
|
+
const qi = new QueuedIteratorImpl<Msg>();
|
|
218
|
+
function stop(err?: Error) {
|
|
219
|
+
qi.push(() => {
|
|
220
|
+
qi.stop(err);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// callback for the subscription or the mux handler
|
|
225
|
+
// simply pushes errors and messages into the iterator
|
|
226
|
+
function callback(err: Error | null, msg: Msg | null) {
|
|
227
|
+
if (err || msg === null) {
|
|
228
|
+
stop(err === null ? undefined : err);
|
|
229
|
+
} else {
|
|
230
|
+
qi.push(msg);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (opts.noMux) {
|
|
235
|
+
// we setup a subscription and manage it
|
|
236
|
+
const stack = asyncTraces ? new Error().stack : null;
|
|
237
|
+
let max = typeof opts.maxMessages === "number" && opts.maxMessages > 0
|
|
238
|
+
? opts.maxMessages
|
|
239
|
+
: -1;
|
|
240
|
+
|
|
241
|
+
const sub = this.subscribe(createInbox(this.options.inboxPrefix), {
|
|
242
|
+
callback: (err, msg) => {
|
|
243
|
+
// we only expect runtime errors or a no responders
|
|
244
|
+
if (
|
|
245
|
+
msg?.data?.length === 0 &&
|
|
246
|
+
msg?.headers?.status === "503"
|
|
247
|
+
) {
|
|
248
|
+
err = new errors.NoRespondersError(subject);
|
|
249
|
+
}
|
|
250
|
+
// augment any error with the current stack to provide context
|
|
251
|
+
// for the error in the user code
|
|
252
|
+
if (err) {
|
|
253
|
+
if (stack) {
|
|
254
|
+
err.stack += `\n\n${stack}`;
|
|
255
|
+
}
|
|
256
|
+
cancel(err);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
// push the message
|
|
260
|
+
callback(null, msg);
|
|
261
|
+
// see if the m request is completed
|
|
262
|
+
if (opts.strategy === "count") {
|
|
263
|
+
max--;
|
|
264
|
+
if (max === 0) {
|
|
265
|
+
cancel();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (opts.strategy === "stall") {
|
|
269
|
+
clearTimers();
|
|
270
|
+
timer = setTimeout(() => {
|
|
271
|
+
cancel();
|
|
272
|
+
}, 300);
|
|
273
|
+
}
|
|
274
|
+
if (opts.strategy === "sentinel") {
|
|
275
|
+
if (msg && msg.data.length === 0) {
|
|
276
|
+
cancel();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
(sub as SubscriptionImpl).requestSubject = subject;
|
|
282
|
+
|
|
283
|
+
sub.closed
|
|
284
|
+
.then(() => {
|
|
285
|
+
stop();
|
|
286
|
+
})
|
|
287
|
+
.catch((err: Error) => {
|
|
288
|
+
qi.stop(err);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const cancel = (err?: Error) => {
|
|
292
|
+
if (err) {
|
|
293
|
+
qi.push(() => {
|
|
294
|
+
throw err;
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
clearTimers();
|
|
298
|
+
sub.drain()
|
|
299
|
+
.then(() => {
|
|
300
|
+
stop();
|
|
301
|
+
})
|
|
302
|
+
.catch((_err: Error) => {
|
|
303
|
+
stop();
|
|
304
|
+
});
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
qi.iterClosed
|
|
308
|
+
.then(() => {
|
|
309
|
+
clearTimers();
|
|
310
|
+
sub?.unsubscribe();
|
|
311
|
+
})
|
|
312
|
+
.catch((_err) => {
|
|
313
|
+
clearTimers();
|
|
314
|
+
sub?.unsubscribe();
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const { headers, traceDestination, traceOnly } = opts;
|
|
318
|
+
try {
|
|
319
|
+
this.publish(subject, data, {
|
|
320
|
+
reply: sub.getSubject(),
|
|
321
|
+
headers,
|
|
322
|
+
traceDestination,
|
|
323
|
+
traceOnly,
|
|
324
|
+
});
|
|
325
|
+
} catch (err) {
|
|
326
|
+
cancel(err as Error);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
let timer = setTimeout(() => {
|
|
330
|
+
cancel();
|
|
331
|
+
}, opts.maxWait);
|
|
332
|
+
|
|
333
|
+
const clearTimers = () => {
|
|
334
|
+
if (timer) {
|
|
335
|
+
clearTimeout(timer);
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
} else {
|
|
339
|
+
// the ingestion is the RequestMany
|
|
340
|
+
const rmo = opts as RequestManyOptionsInternal;
|
|
341
|
+
rmo.callback = callback;
|
|
342
|
+
|
|
343
|
+
qi.iterClosed.then(() => {
|
|
344
|
+
r.cancel();
|
|
345
|
+
}).catch((err) => {
|
|
346
|
+
r.cancel(err);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
const r = new RequestMany(this.protocol.muxSubscriptions, subject, rmo);
|
|
350
|
+
this.protocol.request(r);
|
|
351
|
+
|
|
352
|
+
const { headers, traceDestination, traceOnly } = opts;
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
this.publish(
|
|
356
|
+
subject,
|
|
357
|
+
data,
|
|
358
|
+
{
|
|
359
|
+
reply: `${this.protocol.muxSubscriptions.baseInbox}${r.token}`,
|
|
360
|
+
headers,
|
|
361
|
+
traceDestination,
|
|
362
|
+
traceOnly,
|
|
363
|
+
},
|
|
364
|
+
);
|
|
365
|
+
} catch (err) {
|
|
366
|
+
r.cancel(err as Error);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return Promise.resolve(qi);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
request(
|
|
374
|
+
subject: string,
|
|
375
|
+
data?: Payload,
|
|
376
|
+
opts: RequestOptions = { timeout: 1000, noMux: false },
|
|
377
|
+
): Promise<Msg> {
|
|
378
|
+
try {
|
|
379
|
+
this._check(subject, true, true);
|
|
380
|
+
} catch (err) {
|
|
381
|
+
return Promise.reject(err);
|
|
382
|
+
}
|
|
383
|
+
const asyncTraces = !(this.protocol.options.noAsyncTraces || false);
|
|
384
|
+
opts.timeout = opts.timeout || 1000;
|
|
385
|
+
if (opts.timeout < 1) {
|
|
386
|
+
return Promise.reject(
|
|
387
|
+
InvalidArgumentError.format("timeout", `must be greater than 0`),
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
if (!opts.noMux && opts.reply) {
|
|
391
|
+
return Promise.reject(
|
|
392
|
+
InvalidArgumentError.format(
|
|
393
|
+
["reply", "noMux"],
|
|
394
|
+
"are mutually exclusive",
|
|
395
|
+
),
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (opts.noMux) {
|
|
400
|
+
const inbox = opts.reply
|
|
401
|
+
? opts.reply
|
|
402
|
+
: createInbox(this.options.inboxPrefix);
|
|
403
|
+
const d = deferred<Msg>();
|
|
404
|
+
const errCtx = asyncTraces ? new errors.RequestError("") : null;
|
|
405
|
+
const sub = this.subscribe(
|
|
406
|
+
inbox,
|
|
407
|
+
{
|
|
408
|
+
max: 1,
|
|
409
|
+
timeout: opts.timeout,
|
|
410
|
+
callback: (err, msg) => {
|
|
411
|
+
// check for no responders status
|
|
412
|
+
if (msg && msg.data?.length === 0 && msg.headers?.code === 503) {
|
|
413
|
+
err = new errors.NoRespondersError(subject);
|
|
414
|
+
}
|
|
415
|
+
if (err) {
|
|
416
|
+
// we have a proper stack on timeout
|
|
417
|
+
if (!(err instanceof TimeoutError)) {
|
|
418
|
+
if (errCtx) {
|
|
419
|
+
errCtx.message = err.message;
|
|
420
|
+
errCtx.cause = err;
|
|
421
|
+
err = errCtx;
|
|
422
|
+
} else {
|
|
423
|
+
err = new errors.RequestError(err.message, { cause: err });
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
d.reject(err);
|
|
427
|
+
sub.unsubscribe();
|
|
428
|
+
} else {
|
|
429
|
+
d.resolve(msg);
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
);
|
|
434
|
+
(sub as SubscriptionImpl).requestSubject = subject;
|
|
435
|
+
this.protocol.publish(subject, data, {
|
|
436
|
+
reply: inbox,
|
|
437
|
+
headers: opts.headers,
|
|
438
|
+
});
|
|
439
|
+
return d;
|
|
440
|
+
} else {
|
|
441
|
+
const r = new RequestOne(
|
|
442
|
+
this.protocol.muxSubscriptions,
|
|
443
|
+
subject,
|
|
444
|
+
opts,
|
|
445
|
+
asyncTraces,
|
|
446
|
+
);
|
|
447
|
+
this.protocol.request(r);
|
|
448
|
+
|
|
449
|
+
const { headers, traceDestination, traceOnly } = opts;
|
|
450
|
+
|
|
451
|
+
try {
|
|
452
|
+
this.publish(
|
|
453
|
+
subject,
|
|
454
|
+
data,
|
|
455
|
+
{
|
|
456
|
+
reply: `${this.protocol.muxSubscriptions.baseInbox}${r.token}`,
|
|
457
|
+
headers,
|
|
458
|
+
traceDestination,
|
|
459
|
+
traceOnly,
|
|
460
|
+
},
|
|
461
|
+
);
|
|
462
|
+
} catch (err) {
|
|
463
|
+
r.cancel(err as Error);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const p = Promise.race([r.timer, r.deferred]);
|
|
467
|
+
p.catch(() => {
|
|
468
|
+
r.cancel();
|
|
469
|
+
});
|
|
470
|
+
return p;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/** *
|
|
475
|
+
* Flushes to the server. Promise resolves when round-trip completes.
|
|
476
|
+
* @returns {Promise<void>}
|
|
477
|
+
*/
|
|
478
|
+
flush(): Promise<void> {
|
|
479
|
+
if (this.isClosed()) {
|
|
480
|
+
return Promise.reject(new errors.ClosedConnectionError());
|
|
481
|
+
}
|
|
482
|
+
return this.protocol.flush();
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
drain(): Promise<void> {
|
|
486
|
+
if (this.isClosed()) {
|
|
487
|
+
return Promise.reject(new errors.ClosedConnectionError());
|
|
488
|
+
}
|
|
489
|
+
if (this.isDraining()) {
|
|
490
|
+
return Promise.reject(new errors.DrainingConnectionError());
|
|
491
|
+
}
|
|
492
|
+
this.draining = true;
|
|
493
|
+
return this.protocol.drain();
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
async [Symbol.asyncDispose](): Promise<void> {
|
|
497
|
+
if (this.isClosed()) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (this.isDraining()) {
|
|
501
|
+
await this.closed();
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
await this.drain();
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
isClosed(): boolean {
|
|
508
|
+
return this.protocol.isClosed();
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
isDraining(): boolean {
|
|
512
|
+
return this.draining;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
getServer(): string {
|
|
516
|
+
const srv = this.protocol.getServer();
|
|
517
|
+
return srv ? srv.listen : "";
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
setServers(servers: string[]): void {
|
|
521
|
+
this.protocol.servers.setServers(servers);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
getServers(): ReadonlyArray<Server> {
|
|
525
|
+
return this.protocol.servers.snapshot();
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
status(): AsyncIterable<Status> {
|
|
529
|
+
const iter = new QueuedIteratorImpl<Status>();
|
|
530
|
+
iter.iterClosed.then(() => {
|
|
531
|
+
const idx = this.protocol.listeners.indexOf(iter);
|
|
532
|
+
if (idx > -1) {
|
|
533
|
+
this.protocol.listeners.splice(idx, 1);
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
this.protocol.listeners.push(iter);
|
|
537
|
+
return iter;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
get info(): ServerInfo | undefined {
|
|
541
|
+
return this.protocol.isClosed() ? undefined : this.protocol.info;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
async context(): Promise<Context> {
|
|
545
|
+
const r = await this.request(`$SYS.REQ.USER.INFO`);
|
|
546
|
+
return r.json<Context>((key, value) => {
|
|
547
|
+
if (key === "time") {
|
|
548
|
+
return new Date(Date.parse(value));
|
|
549
|
+
}
|
|
550
|
+
return value;
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
stats(): Stats {
|
|
555
|
+
return {
|
|
556
|
+
inBytes: this.protocol.inBytes,
|
|
557
|
+
outBytes: this.protocol.outBytes,
|
|
558
|
+
inMsgs: this.protocol.inMsgs,
|
|
559
|
+
outMsgs: this.protocol.outMsgs,
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
getServerVersion(): SemVer | undefined {
|
|
564
|
+
const info = this.info;
|
|
565
|
+
return info ? parseSemVer(info.version) : undefined;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
async rtt(): Promise<number> {
|
|
569
|
+
if (this.isClosed()) {
|
|
570
|
+
throw new errors.ClosedConnectionError();
|
|
571
|
+
}
|
|
572
|
+
if (!this.protocol.connected) {
|
|
573
|
+
throw new errors.RequestError("connection disconnected");
|
|
574
|
+
}
|
|
575
|
+
const start = Date.now();
|
|
576
|
+
await this.flush();
|
|
577
|
+
return Date.now() - start;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
get features(): Features {
|
|
581
|
+
return this.protocol.features;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
reconnect(): Promise<void> {
|
|
585
|
+
if (this.isClosed()) {
|
|
586
|
+
return Promise.reject(new errors.ClosedConnectionError());
|
|
587
|
+
}
|
|
588
|
+
if (this.isDraining()) {
|
|
589
|
+
return Promise.reject(new errors.DrainingConnectionError());
|
|
590
|
+
}
|
|
591
|
+
return this.protocol.reconnect();
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// camera.ui fork patch — see ProtocolHandler.forceReconnect for semantics.
|
|
595
|
+
forceReconnect(): Promise<void> {
|
|
596
|
+
if (this.isClosed()) {
|
|
597
|
+
return Promise.reject(new errors.ClosedConnectionError());
|
|
598
|
+
}
|
|
599
|
+
if (this.isDraining()) {
|
|
600
|
+
return Promise.reject(new errors.DrainingConnectionError());
|
|
601
|
+
}
|
|
602
|
+
return this.protocol.forceReconnect();
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// internal
|
|
606
|
+
addCloseListener(listener: ConnectionClosedListener) {
|
|
607
|
+
if (this.closeListeners === undefined) {
|
|
608
|
+
this.closeListeners = new CloseListeners(this.closed());
|
|
609
|
+
}
|
|
610
|
+
this.closeListeners.add(listener);
|
|
611
|
+
}
|
|
612
|
+
// internal
|
|
613
|
+
removeCloseListener(listener: ConnectionClosedListener) {
|
|
614
|
+
if (this.closeListeners) {
|
|
615
|
+
this.closeListeners.remove(listener);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
class CloseListeners {
|
|
621
|
+
listeners: ConnectionClosedListener[];
|
|
622
|
+
|
|
623
|
+
constructor(closed: Promise<void | Error>) {
|
|
624
|
+
this.listeners = [];
|
|
625
|
+
closed.then((err) => {
|
|
626
|
+
this.notify(err);
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
add(listener: ConnectionClosedListener) {
|
|
631
|
+
this.listeners.push(listener);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
remove(listener: ConnectionClosedListener) {
|
|
635
|
+
this.listeners = this.listeners.filter((l) => l !== listener);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
notify(err: void | Error) {
|
|
639
|
+
this.listeners.forEach((l) => {
|
|
640
|
+
if (typeof l.connectionClosedCallback === "function") {
|
|
641
|
+
try {
|
|
642
|
+
l.connectionClosedCallback(err);
|
|
643
|
+
} catch (_) {
|
|
644
|
+
// ignored
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
this.listeners = [];
|
|
649
|
+
}
|
|
650
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as nkeys from "@nats-io/nkeys";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2016-2021 The NATS Authors
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export { Nuid, nuid } from "@nats-io/nuid";
|