@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.
Files changed (32) hide show
  1. package/externals/nats.js/core/src/authenticator.ts +159 -0
  2. package/externals/nats.js/core/src/bench.ts +426 -0
  3. package/externals/nats.js/core/src/codec.ts +28 -0
  4. package/externals/nats.js/core/src/core.ts +1219 -0
  5. package/externals/nats.js/core/src/databuffer.ts +129 -0
  6. package/externals/nats.js/core/src/denobuffer.ts +248 -0
  7. package/externals/nats.js/core/src/encoders.ts +53 -0
  8. package/externals/nats.js/core/src/errors.ts +300 -0
  9. package/externals/nats.js/core/src/headers.ts +315 -0
  10. package/externals/nats.js/core/src/heartbeats.ts +114 -0
  11. package/externals/nats.js/core/src/idleheartbeat_monitor.ts +140 -0
  12. package/externals/nats.js/core/src/internal_mod.ts +167 -0
  13. package/externals/nats.js/core/src/ipparser.ts +215 -0
  14. package/externals/nats.js/core/src/mod.ts +113 -0
  15. package/externals/nats.js/core/src/msg.ts +120 -0
  16. package/externals/nats.js/core/src/muxsubscription.ts +111 -0
  17. package/externals/nats.js/core/src/nats.ts +650 -0
  18. package/externals/nats.js/core/src/nkeys.ts +1 -0
  19. package/externals/nats.js/core/src/nuid.ts +16 -0
  20. package/externals/nats.js/core/src/options.ts +202 -0
  21. package/externals/nats.js/core/src/parser.ts +756 -0
  22. package/externals/nats.js/core/src/protocol.ts +1304 -0
  23. package/externals/nats.js/core/src/queued_iterator.ts +171 -0
  24. package/externals/nats.js/core/src/request.ts +177 -0
  25. package/externals/nats.js/core/src/semver.ts +165 -0
  26. package/externals/nats.js/core/src/servers.ts +424 -0
  27. package/externals/nats.js/core/src/transport.ts +117 -0
  28. package/externals/nats.js/core/src/types.ts +17 -0
  29. package/externals/nats.js/core/src/util.ts +367 -0
  30. package/externals/nats.js/core/src/version.ts +2 -0
  31. package/externals/nats.js/core/src/ws_transport.ts +391 -0
  32. package/package.json +2 -1
@@ -0,0 +1,300 @@
1
+ /*
2
+ * Copyright 2024 Synadia Communications, Inc
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
+ /**
17
+ * Represents an error that is thrown when an invalid subject is encountered.
18
+ * This class extends the built-in Error object.
19
+ *
20
+ * @class
21
+ * @extends Error
22
+ */
23
+ export class InvalidSubjectError extends Error {
24
+ constructor(subject: string, options?: ErrorOptions) {
25
+ super(`illegal subject: '${subject}'`, options);
26
+ this.name = "InvalidSubjectError";
27
+ }
28
+ }
29
+
30
+ export class InvalidArgumentError extends Error {
31
+ constructor(message: string, options?: ErrorOptions) {
32
+ super(message, options);
33
+ this.name = "InvalidArgumentError";
34
+ }
35
+
36
+ static format(
37
+ property: string | string[],
38
+ message: string,
39
+ options?: ErrorOptions,
40
+ ): InvalidArgumentError {
41
+ if (Array.isArray(message) && message.length > 1) {
42
+ message = message[0];
43
+ }
44
+ if (Array.isArray(property)) {
45
+ property = property.map((n) => `'${n}'`);
46
+ property = property.join(",");
47
+ } else {
48
+ property = `'${property}'`;
49
+ }
50
+ return new InvalidArgumentError(`${property} ${message}`, options);
51
+ }
52
+ }
53
+
54
+ /**
55
+ * InvalidOperationError is a custom error class that extends the standard Error object.
56
+ * It represents an error that occurs when an invalid operation is attempted on one of
57
+ * objects returned by the API. For example, trying to iterate on an object that was
58
+ * configured with a callback.
59
+ *
60
+ * @class InvalidOperationError
61
+ * @extends {Error}
62
+ *
63
+ * @param {string} message - The error message that explains the reason for the error.
64
+ * @param {ErrorOptions} [options] - Optional parameter to provide additional error options.
65
+ */
66
+ export class InvalidOperationError extends Error {
67
+ constructor(message: string, options?: ErrorOptions) {
68
+ super(message, options);
69
+ this.name = "InvalidOperationError";
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Represents an error indicating that user authentication has expired.
75
+ * This error is typically thrown when a user attempts to access a connection
76
+ * but their authentication credentials have expired.
77
+ */
78
+ export class UserAuthenticationExpiredError extends Error {
79
+ constructor(message: string, options?: ErrorOptions) {
80
+ super(message, options);
81
+ this.name = "UserAuthenticationExpiredError";
82
+ }
83
+
84
+ static parse(s: string): UserAuthenticationExpiredError | null {
85
+ const ss = s.toLowerCase();
86
+ if (ss.indexOf("user authentication expired") !== -1) {
87
+ return new UserAuthenticationExpiredError(s);
88
+ }
89
+ return null;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Represents an error related to authorization issues.
95
+ * Note that these could represent an authorization violation,
96
+ * or that the account authentication configuration has expired,
97
+ * or an authentication timeout.
98
+ */
99
+ export class AuthorizationError extends Error {
100
+ constructor(message: string, options?: ErrorOptions) {
101
+ super(message, options);
102
+ this.name = "AuthorizationError";
103
+ }
104
+
105
+ static parse(s: string): AuthorizationError | null {
106
+ const messages = [
107
+ "authorization violation",
108
+ "account authentication expired",
109
+ "authentication timeout",
110
+ ];
111
+
112
+ const ss = s.toLowerCase();
113
+
114
+ for (let i = 0; i < messages.length; i++) {
115
+ if (ss.indexOf(messages[i]) !== -1) {
116
+ return new AuthorizationError(s);
117
+ }
118
+ }
119
+
120
+ return null;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Class representing an error thrown when an operation is attempted on a closed connection.
126
+ *
127
+ * This error is intended to signal that a connection-related operation could not be completed
128
+ * because the connection is no longer open or has been terminated.
129
+ *
130
+ * @class
131
+ * @extends Error
132
+ */
133
+ export class ClosedConnectionError extends Error {
134
+ constructor() {
135
+ super("closed connection");
136
+ this.name = "ClosedConnectionError";
137
+ }
138
+ }
139
+
140
+ /**
141
+ * The `ConnectionDrainingError` class represents a specific type of error
142
+ * that occurs when a connection is being drained.
143
+ *
144
+ * This error is typically used in scenarios where connections need to be
145
+ * gracefully closed or when they are transitioning to an inactive state.
146
+ *
147
+ * The error message is set to "connection draining" and the error name is
148
+ * overridden to "DrainingConnectionError".
149
+ */
150
+ export class DrainingConnectionError extends Error {
151
+ constructor() {
152
+ super("connection draining");
153
+ this.name = "DrainingConnectionError";
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Represents an error that occurs when a network connection fails.
159
+ * Extends the built-in Error class to provide additional context for connection-related issues.
160
+ *
161
+ * @param {string} message - A human-readable description of the error.
162
+ * @param {ErrorOptions} [options] - Optional settings for customizing the error behavior.
163
+ */
164
+ export class ConnectionError extends Error {
165
+ constructor(message: string, options?: ErrorOptions) {
166
+ super(message, options);
167
+ this.name = "ConnectionError";
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Represents an error encountered during protocol operations.
173
+ * This class extends the built-in `Error` class, providing a specific
174
+ * error type called `ProtocolError`.
175
+ *
176
+ * @param {string} message - A descriptive message describing the error.
177
+ * @param {ErrorOptions} [options] - Optional parameters to include additional details.
178
+ */
179
+ export class ProtocolError extends Error {
180
+ constructor(message: string, options?: ErrorOptions) {
181
+ super(message, options);
182
+ this.name = "ProtocolError";
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Class representing an error that occurs during an request operation
188
+ * (such as TimeoutError, or NoRespondersError, or some other error).
189
+ *
190
+ * @extends Error
191
+ */
192
+ export class RequestError extends Error {
193
+ constructor(message = "", options?: ErrorOptions) {
194
+ super(message, options);
195
+ this.name = "RequestError";
196
+ }
197
+
198
+ isNoResponders(): boolean {
199
+ return this.cause instanceof NoRespondersError;
200
+ }
201
+ }
202
+
203
+ /**
204
+ * TimeoutError is a custom error class that extends the built-in Error class.
205
+ * It is used to represent an error that occurs when an operation exceeds a
206
+ * predefined time limit.
207
+ *
208
+ * @class
209
+ * @extends {Error}
210
+ */
211
+ export class TimeoutError extends Error {
212
+ constructor(options?: ErrorOptions) {
213
+ super("timeout", options);
214
+ this.name = "TimeoutError";
215
+ }
216
+ }
217
+
218
+ /**
219
+ * NoRespondersError is an error thrown when no responders (no service is
220
+ * subscribing to the subject) are found for a given subject. This error
221
+ * is typically found as the cause for a RequestError
222
+ *
223
+ * @extends Error
224
+ *
225
+ * @param {string} subject - The subject for which no responders were found.
226
+ * @param {ErrorOptions} [options] - Optional error options.
227
+ */
228
+ export class NoRespondersError extends Error {
229
+ subject: string;
230
+ constructor(subject: string, options?: ErrorOptions) {
231
+ super(`no responders: '${subject}'`, options);
232
+ this.subject = subject;
233
+ this.name = "NoResponders";
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Class representing a Permission Violation Error.
239
+ * It provides information about the operation (either "publish" or "subscription")
240
+ * and the subject used for the operation and the optional queue (if a subscription).
241
+ *
242
+ * This error is terminal for a subscription.
243
+ */
244
+ export class PermissionViolationError extends Error {
245
+ operation: "publish" | "subscription";
246
+ subject: string;
247
+ queue?: string;
248
+
249
+ constructor(
250
+ message: string,
251
+ operation: "publish" | "subscription",
252
+ subject: string,
253
+ queue?: string,
254
+ options?: ErrorOptions,
255
+ ) {
256
+ super(message, options);
257
+ this.name = "PermissionViolationError";
258
+ this.operation = operation;
259
+ this.subject = subject;
260
+ this.queue = queue;
261
+ }
262
+
263
+ static parse(s: string): PermissionViolationError | null {
264
+ const t = s ? s.toLowerCase() : "";
265
+ if (t.indexOf("permissions violation") === -1) {
266
+ return null;
267
+ }
268
+ let operation: "publish" | "subscription" = "publish";
269
+ let subject = "";
270
+ let queue: string | undefined = undefined;
271
+ const m = s.match(/(Publish|Subscription) to "(\S+)"/);
272
+ if (m) {
273
+ operation = m[1].toLowerCase() as "publish" | "subscription";
274
+ subject = m[2];
275
+ if (operation === "subscription") {
276
+ const qm = s.match(/using queue "(\S+)"/);
277
+ if (qm) {
278
+ queue = qm[1];
279
+ }
280
+ }
281
+ }
282
+ return new PermissionViolationError(s, operation, subject, queue);
283
+ }
284
+ }
285
+
286
+ export const errors = {
287
+ AuthorizationError,
288
+ ClosedConnectionError,
289
+ ConnectionError,
290
+ DrainingConnectionError,
291
+ InvalidArgumentError,
292
+ InvalidOperationError,
293
+ InvalidSubjectError,
294
+ NoRespondersError,
295
+ PermissionViolationError,
296
+ ProtocolError,
297
+ RequestError,
298
+ TimeoutError,
299
+ UserAuthenticationExpiredError,
300
+ };
@@ -0,0 +1,315 @@
1
+ /*
2
+ * Copyright 2020-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
+ // Heavily inspired by Golang's https://golang.org/src/net/http/header.go
17
+
18
+ import { TD, TE } from "./encoders.ts";
19
+ import type { MsgHdrs } from "./core.ts";
20
+ import { Match } from "./core.ts";
21
+ import { InvalidArgumentError } from "./errors.ts";
22
+
23
+ // https://www.ietf.org/rfc/rfc822.txt
24
+ // 3.1.2. STRUCTURE OF HEADER FIELDS
25
+ //
26
+ // Once a field has been unfolded, it may be viewed as being com-
27
+ // posed of a field-name followed by a colon (":"), followed by a
28
+ // field-body, and terminated by a carriage-return/line-feed.
29
+ // The field-name must be composed of printable ASCII characters
30
+ // (i.e., characters that have values between 33. and 126.,
31
+ // decimal, except colon). The field-body may be composed of any
32
+ // ASCII characters, except CR or LF. (While CR and/or LF may be
33
+ // present in the actual text, they are removed by the action of
34
+ // unfolding the field.)
35
+ export function canonicalMIMEHeaderKey(k: string): string {
36
+ const a = 97;
37
+ const A = 65;
38
+ const Z = 90;
39
+ const z = 122;
40
+ const dash = 45;
41
+ const colon = 58;
42
+ const start = 33;
43
+ const end = 126;
44
+ const toLower = a - A;
45
+
46
+ let upper = true;
47
+ const buf: number[] = new Array(k.length);
48
+ for (let i = 0; i < k.length; i++) {
49
+ let c = k.charCodeAt(i);
50
+ if (c === colon || c < start || c > end) {
51
+ throw InvalidArgumentError.format(
52
+ "header",
53
+ `'${k[i]}' is not a valid character in a header name`,
54
+ );
55
+ }
56
+ if (upper && a <= c && c <= z) {
57
+ c -= toLower;
58
+ } else if (!upper && A <= c && c <= Z) {
59
+ c += toLower;
60
+ }
61
+ buf[i] = c;
62
+ upper = c == dash;
63
+ }
64
+ return String.fromCharCode(...buf);
65
+ }
66
+
67
+ export function headers(code = 0, description = ""): MsgHdrs {
68
+ if (code === 0 && description !== "") {
69
+ throw InvalidArgumentError.format("code", "is required");
70
+ } else if (code > 0 && description === "") {
71
+ throw InvalidArgumentError.format("description", "is required");
72
+ }
73
+ return new MsgHdrsImpl(code, description);
74
+ }
75
+
76
+ const HEADER = "NATS/1.0";
77
+
78
+ export class MsgHdrsImpl implements MsgHdrs {
79
+ _code: number;
80
+ headers: Map<string, string[]>;
81
+ _description: string;
82
+
83
+ constructor(code = 0, description = "") {
84
+ this._code = code;
85
+ this._description = description;
86
+ this.headers = new Map();
87
+ }
88
+
89
+ [Symbol.iterator](): IterableIterator<[string, string[]]> {
90
+ return this.headers.entries();
91
+ }
92
+
93
+ size(): number {
94
+ return this.headers.size;
95
+ }
96
+
97
+ equals(mh: MsgHdrsImpl): boolean {
98
+ if (
99
+ mh && this.headers.size === mh.headers.size &&
100
+ this._code === mh._code
101
+ ) {
102
+ for (const [k, v] of this.headers) {
103
+ const a = mh.values(k);
104
+ if (v.length !== a.length) {
105
+ return false;
106
+ }
107
+ const vv = [...v].sort();
108
+ const aa = [...a].sort();
109
+ for (let i = 0; i < vv.length; i++) {
110
+ if (vv[i] !== aa[i]) {
111
+ return false;
112
+ }
113
+ }
114
+ }
115
+ return true;
116
+ }
117
+ return false;
118
+ }
119
+
120
+ static decode(a: Uint8Array): MsgHdrsImpl {
121
+ const mh = new MsgHdrsImpl();
122
+ const s = TD.decode(a);
123
+ const lines = s.split("\r\n");
124
+ const h = lines[0];
125
+ if (h !== HEADER) {
126
+ // malformed headers could add extra space without adding a code or description
127
+ let str = h.replace(HEADER, "").trim();
128
+ if (str.length > 0) {
129
+ mh._code = parseInt(str, 10);
130
+ if (isNaN(mh._code)) {
131
+ mh._code = 0;
132
+ }
133
+ const scode = mh._code.toString();
134
+ str = str.replace(scode, "");
135
+ mh._description = str.trim();
136
+ }
137
+ }
138
+ if (lines.length >= 1) {
139
+ lines.slice(1).map((s) => {
140
+ if (s) {
141
+ const idx = s.indexOf(":");
142
+ if (idx > -1) {
143
+ const k = s.slice(0, idx);
144
+ const v = s.slice(idx + 1).trim();
145
+ mh.append(k, v);
146
+ }
147
+ }
148
+ });
149
+ }
150
+ return mh;
151
+ }
152
+
153
+ toString(): string {
154
+ if (this.headers.size === 0 && this._code === 0) {
155
+ return "";
156
+ }
157
+ let s = HEADER;
158
+ if (this._code > 0 && this._description !== "") {
159
+ s += ` ${this._code} ${this._description}`;
160
+ }
161
+ for (const [k, v] of this.headers) {
162
+ for (let i = 0; i < v.length; i++) {
163
+ s = `${s}\r\n${k}: ${v[i]}`;
164
+ }
165
+ }
166
+ return `${s}\r\n\r\n`;
167
+ }
168
+
169
+ encode(): Uint8Array {
170
+ return TE.encode(this.toString());
171
+ }
172
+
173
+ static validHeaderValue(k: string): string {
174
+ const inv = /[\r\n]/;
175
+ if (inv.test(k)) {
176
+ throw InvalidArgumentError.format(
177
+ "header",
178
+ "values cannot contain \\r or \\n",
179
+ );
180
+ }
181
+ return k.trim();
182
+ }
183
+
184
+ keys(): string[] {
185
+ const keys = [];
186
+ for (const sk of this.headers.keys()) {
187
+ keys.push(sk);
188
+ }
189
+ return keys;
190
+ }
191
+
192
+ findKeys(k: string, match: Match = Match.Exact): string[] {
193
+ const keys = this.keys();
194
+ switch (match) {
195
+ case Match.Exact:
196
+ return keys.filter((v) => {
197
+ return v === k;
198
+ });
199
+ case Match.CanonicalMIME:
200
+ k = canonicalMIMEHeaderKey(k);
201
+ return keys.filter((v) => {
202
+ return v === k;
203
+ });
204
+ default: {
205
+ const lci = k.toLowerCase();
206
+ return keys.filter((v) => {
207
+ return lci === v.toLowerCase();
208
+ });
209
+ }
210
+ }
211
+ }
212
+
213
+ get(k: string, match = Match.Exact): string {
214
+ const keys = this.findKeys(k, match);
215
+ if (keys.length) {
216
+ const v = this.headers.get(keys[0]);
217
+ if (v) {
218
+ return Array.isArray(v) ? v[0] : v;
219
+ }
220
+ }
221
+ return "";
222
+ }
223
+
224
+ last(k: string, match = Match.Exact): string {
225
+ const keys = this.findKeys(k, match);
226
+ if (keys.length) {
227
+ const v = this.headers.get(keys[0]);
228
+ if (v) {
229
+ return Array.isArray(v) ? v[v.length - 1] : v;
230
+ }
231
+ }
232
+ return "";
233
+ }
234
+
235
+ has(k: string, match: Match = Match.Exact): boolean {
236
+ return this.findKeys(k, match).length > 0;
237
+ }
238
+
239
+ set(k: string, v: string, match: Match = Match.Exact): void {
240
+ this.delete(k, match);
241
+ this.append(k, v, match);
242
+ }
243
+
244
+ append(k: string, v: string, match: Match = Match.Exact): void {
245
+ // validate the key
246
+ const ck = canonicalMIMEHeaderKey(k);
247
+ if (match === Match.CanonicalMIME) {
248
+ k = ck;
249
+ }
250
+ // if we get non-sensical ignores/etc, we should try
251
+ // to do the right thing and use the first key that matches
252
+ const keys = this.findKeys(k, match);
253
+ k = keys.length > 0 ? keys[0] : k;
254
+
255
+ const value = MsgHdrsImpl.validHeaderValue(v);
256
+ let a = this.headers.get(k);
257
+ if (!a) {
258
+ a = [];
259
+ this.headers.set(k, a);
260
+ }
261
+ a.push(value);
262
+ }
263
+
264
+ values(k: string, match: Match = Match.Exact): string[] {
265
+ const buf: string[] = [];
266
+ const keys = this.findKeys(k, match);
267
+ keys.forEach((v) => {
268
+ const values = this.headers.get(v);
269
+ if (values) {
270
+ buf.push(...values);
271
+ }
272
+ });
273
+ return buf;
274
+ }
275
+
276
+ delete(k: string, match: Match = Match.Exact): void {
277
+ const keys = this.findKeys(k, match);
278
+ keys.forEach((v) => {
279
+ this.headers.delete(v);
280
+ });
281
+ }
282
+
283
+ get hasError(): boolean {
284
+ return this._code >= 300;
285
+ }
286
+
287
+ get status(): string {
288
+ return `${this._code} ${this._description}`.trim();
289
+ }
290
+
291
+ toRecord(): Record<string, string[]> {
292
+ const data = {} as Record<string, string[]>;
293
+ this.keys().forEach((v) => {
294
+ data[v] = this.values(v);
295
+ });
296
+ return data;
297
+ }
298
+
299
+ get code(): number {
300
+ return this._code;
301
+ }
302
+
303
+ get description(): string {
304
+ return this._description;
305
+ }
306
+
307
+ static fromRecord(r: Record<string, string[]>): MsgHdrs {
308
+ const h = new MsgHdrsImpl();
309
+ for (const k in r) {
310
+ const v = r[k];
311
+ h.headers.set(k, Array.isArray(v) ? v : [`${v}`]);
312
+ }
313
+ return h;
314
+ }
315
+ }