@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,114 @@
1
+ /*
2
+ * Copyright 2020-2024 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 type { Deferred } from "./util.ts";
17
+ import { deferred } from "./util.ts";
18
+ import type { Status } from "./core.ts";
19
+
20
+ export interface PH {
21
+ flush(p?: Deferred<void>): Promise<void>;
22
+ disconnect(): void;
23
+ dispatchStatus(status: Status): void;
24
+ }
25
+
26
+ export class Heartbeat {
27
+ ph: PH;
28
+ interval: number;
29
+ maxOut: number;
30
+ timeout: number;
31
+ timer?: number;
32
+ pendings: Promise<void>[];
33
+
34
+ constructor(ph: PH, interval: number, maxOut: number, timeout = 0) {
35
+ this.ph = ph;
36
+ this.interval = interval;
37
+ this.maxOut = maxOut;
38
+ this.timeout = timeout;
39
+ this.pendings = [];
40
+ }
41
+
42
+ // api to start the heartbeats, since this can be
43
+ // spuriously called from dial, ensure we don't
44
+ // leak timers
45
+ start() {
46
+ this.cancel();
47
+ this._schedule();
48
+ }
49
+
50
+ // api for canceling the heartbeats, if stale is
51
+ // true it will initiate a client disconnect
52
+ cancel(stale?: boolean) {
53
+ if (this.timer) {
54
+ clearTimeout(this.timer);
55
+ this.timer = undefined;
56
+ }
57
+ this._reset();
58
+ if (stale) {
59
+ this.ph.disconnect();
60
+ }
61
+ }
62
+
63
+ _schedule() {
64
+ // @ts-ignore: node is not a number - we treat this opaquely
65
+ this.timer = setTimeout(() => {
66
+ this.ph.dispatchStatus(
67
+ { type: "ping", pendingPings: this.pendings.length + 1 },
68
+ );
69
+ if (this.pendings.length === this.maxOut) {
70
+ this.cancel(true);
71
+ return;
72
+ }
73
+ const ping = deferred<void>();
74
+
75
+ // if no PONG within `timeout` ms, kill
76
+ // the connection without waiting for the next interval tick.
77
+ let pingTimer: ReturnType<typeof setTimeout> | undefined;
78
+ if (this.timeout > 0) {
79
+ pingTimer = setTimeout(() => {
80
+ pingTimer = undefined;
81
+ this.cancel(true);
82
+ }, this.timeout);
83
+ }
84
+ const clearPingTimer = () => {
85
+ if (pingTimer !== undefined) {
86
+ clearTimeout(pingTimer);
87
+ pingTimer = undefined;
88
+ }
89
+ };
90
+
91
+ this.ph.flush(ping)
92
+ .then(() => {
93
+ clearPingTimer();
94
+ this._reset();
95
+ })
96
+ .catch(() => {
97
+ // we disconnected - pongs were rejected
98
+ clearPingTimer();
99
+ this.cancel();
100
+ });
101
+ this.pendings.push(ping);
102
+ this._schedule();
103
+ }, this.interval);
104
+ }
105
+
106
+ _reset() {
107
+ // clear pendings after resolving them
108
+ this.pendings = this.pendings.filter((p) => {
109
+ const d = p as Deferred<void>;
110
+ d.resolve();
111
+ return false;
112
+ });
113
+ }
114
+ }
@@ -0,0 +1,140 @@
1
+ /*
2
+ * Copyright 2022 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
+ /**
17
+ * Called with the number of missed heartbeats.
18
+ * If the function returns true, the monitor will cancel monitoring.
19
+ */
20
+ export type IdleHeartbeatFn = (n: number) => boolean;
21
+
22
+ /**
23
+ * IdleHeartbeatOptions
24
+ */
25
+ export type IdleHeartbeatOptions = {
26
+ /**
27
+ * @field maxOut - optional maximum number of missed heartbeats before notifying (default is 2)
28
+ */
29
+ maxOut: number;
30
+ /**
31
+ * @field cancelAfter - optional timer to auto cancel monitoring in millis
32
+ */
33
+ cancelAfter: number;
34
+ };
35
+
36
+ export class IdleHeartbeatMonitor {
37
+ interval: number;
38
+ maxOut: number;
39
+ cancelAfter: number;
40
+ timer?: number;
41
+ autoCancelTimer?: number;
42
+ last!: number;
43
+ missed: number;
44
+ count: number;
45
+ callback: IdleHeartbeatFn;
46
+
47
+ /**
48
+ * Constructor
49
+ * @param interval in millis to check
50
+ * @param cb a callback to report when heartbeats are missed
51
+ * @param opts monitor options @see IdleHeartbeatOptions
52
+ */
53
+ constructor(
54
+ interval: number,
55
+ cb: IdleHeartbeatFn,
56
+ opts: Partial<IdleHeartbeatOptions> = { maxOut: 2 },
57
+ ) {
58
+ this.interval = interval;
59
+ this.maxOut = opts?.maxOut || 2;
60
+ this.cancelAfter = opts?.cancelAfter || 0;
61
+ this.last = Date.now();
62
+ this.missed = 0;
63
+ this.count = 0;
64
+ this.callback = cb;
65
+
66
+ this._schedule();
67
+ }
68
+
69
+ /**
70
+ * cancel monitoring
71
+ */
72
+ cancel() {
73
+ if (this.autoCancelTimer) {
74
+ clearTimeout(this.autoCancelTimer);
75
+ }
76
+ if (this.timer) {
77
+ clearInterval(this.timer);
78
+ }
79
+ this.timer = 0;
80
+ this.autoCancelTimer = 0;
81
+ this.missed = 0;
82
+ }
83
+
84
+ /**
85
+ * work signals that there was work performed
86
+ */
87
+ work() {
88
+ this.last = Date.now();
89
+ this.missed = 0;
90
+ }
91
+
92
+ /**
93
+ * internal api to change the interval, cancelAfter and maxOut
94
+ * @param interval
95
+ * @param cancelAfter
96
+ * @param maxOut
97
+ */
98
+ _change(interval: number, cancelAfter = 0, maxOut = 2) {
99
+ this.interval = interval;
100
+ this.maxOut = maxOut;
101
+ this.cancelAfter = cancelAfter;
102
+ this.restart();
103
+ }
104
+
105
+ /**
106
+ * cancels and restarts the monitoring
107
+ */
108
+ restart() {
109
+ this.cancel();
110
+ this._schedule();
111
+ }
112
+
113
+ /**
114
+ * internal api called to start monitoring
115
+ */
116
+ _schedule() {
117
+ if (this.cancelAfter > 0) {
118
+ // @ts-ignore: in node is not a number - we treat this opaquely
119
+ this.autoCancelTimer = setTimeout(() => {
120
+ this.cancel();
121
+ }, this.cancelAfter);
122
+ }
123
+ // @ts-ignore: in node is not a number - we treat this opaquely
124
+ this.timer = setInterval(() => {
125
+ this.count++;
126
+ if ((Date.now() - this.last) > this.interval) {
127
+ this.missed++;
128
+ }
129
+ if (this.missed >= this.maxOut) {
130
+ try {
131
+ if (this.callback(this.missed) === true) {
132
+ this.cancel();
133
+ }
134
+ } catch (err) {
135
+ console.log(err);
136
+ }
137
+ }
138
+ }, this.interval);
139
+ }
140
+ }
@@ -0,0 +1,167 @@
1
+ /*
2
+ * Copyright 2024 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 { NatsConnectionImpl } from "./nats.ts";
17
+ export { Nuid, nuid } from "./nuid.ts";
18
+
19
+ export { MsgImpl } from "./msg.ts";
20
+ export { getResolveFn, setTransportFactory } from "./transport.ts";
21
+ export type { Transport, TransportFactory } from "./transport.ts";
22
+ export { Connect, INFO, ProtocolHandler } from "./protocol.ts";
23
+ export type {
24
+ Backoff,
25
+ Deferred,
26
+ Delay,
27
+ ErrorResult,
28
+ Perf,
29
+ Prettify,
30
+ Result,
31
+ Timeout,
32
+ ValueResult,
33
+ WithRequired,
34
+ } from "./util.ts";
35
+ export {
36
+ backoff,
37
+ collect,
38
+ deadline,
39
+ deferred,
40
+ delay,
41
+ extend,
42
+ millis,
43
+ nanos,
44
+ render,
45
+ SimpleMutex,
46
+ timeout,
47
+ } from "./util.ts";
48
+ export { canonicalMIMEHeaderKey, headers, MsgHdrsImpl } from "./headers.ts";
49
+ export { Heartbeat } from "./heartbeats.ts";
50
+ export type { PH } from "./heartbeats.ts";
51
+ export { MuxSubscription } from "./muxsubscription.ts";
52
+ export { DataBuffer } from "./databuffer.ts";
53
+ export {
54
+ buildAuthenticator,
55
+ checkOptions,
56
+ checkUnsupportedOption,
57
+ DEFAULT_MAX_RECONNECT_ATTEMPTS,
58
+ defaultOptions,
59
+ hasWsProtocol,
60
+ parseOptions,
61
+ } from "./options.ts";
62
+ export { RequestOne } from "./request.ts";
63
+ export {
64
+ credsAuthenticator,
65
+ jwtAuthenticator,
66
+ nkeyAuthenticator,
67
+ tokenAuthenticator,
68
+ usernamePasswordAuthenticator,
69
+ } from "./authenticator.ts";
70
+ export type { Codec } from "./codec.ts";
71
+ export * from "./nkeys.ts";
72
+ export { QueuedIteratorImpl } from "./queued_iterator.ts";
73
+ export type { MsgArg, ParserEvent } from "./parser.ts";
74
+ export { describe, Kind, Parser, State } from "./parser.ts";
75
+ export { DenoBuffer, MAX_SIZE, readAll, writeAll } from "./denobuffer.ts";
76
+ export { Bench, Metric } from "./bench.ts";
77
+ export type { BenchOpts } from "./bench.ts";
78
+ export { TD, TE } from "./encoders.ts";
79
+ export { ipV4, isIP, parseIP } from "./ipparser.ts";
80
+
81
+ export type { SemVer } from "./semver.ts";
82
+ export { compare, Feature, Features, parseSemVer } from "./semver.ts";
83
+ export { Empty } from "./types.ts";
84
+ export { extractProtocolMessage, protoLen } from "./transport.ts";
85
+
86
+ export type {
87
+ Auth,
88
+ Authenticator,
89
+ CallbackFn,
90
+ CallbackOptionalErrorFn,
91
+ ClientPingStatus,
92
+ CloseStatus,
93
+ ClusterUpdateStatus,
94
+ ConnectionClosedListener,
95
+ ConnectionOptions,
96
+ DisconnectStatus,
97
+ Dispatcher,
98
+ ForceReconnectStatus,
99
+ JwtAuth,
100
+ LDMStatus,
101
+ Msg,
102
+ MsgCallback,
103
+ MsgHdrs,
104
+ Nanos,
105
+ NatsConnection,
106
+ NKeyAuth,
107
+ NoAuth,
108
+ Payload,
109
+ Publisher,
110
+ PublishOptions,
111
+ QueuedIterator,
112
+ ReconnectingStatus,
113
+ ReconnectStatus,
114
+ ReconnectToServerHandler,
115
+ Request,
116
+ RequestManyOptions,
117
+ RequestOptions,
118
+ RequestStrategy,
119
+ ReviverFn,
120
+ Server,
121
+ ServerErrorStatus,
122
+ ServerInfo,
123
+ ServersChanged,
124
+ SlowConsumerStatus,
125
+ StaleConnectionStatus,
126
+ Stats,
127
+ Status,
128
+ SubOpts,
129
+ Subscription,
130
+ SubscriptionOptions,
131
+ SyncIterator,
132
+ TlsOptions,
133
+ TokenAuth,
134
+ UserPass,
135
+ } from "./core.ts";
136
+
137
+ export { createInbox, Match, syncIterator } from "./core.ts";
138
+ export { SubscriptionImpl, Subscriptions } from "./protocol.ts";
139
+
140
+ export type {
141
+ IdleHeartbeatFn,
142
+ IdleHeartbeatOptions,
143
+ } from "./idleheartbeat_monitor.ts";
144
+ export { IdleHeartbeatMonitor } from "./idleheartbeat_monitor.ts";
145
+
146
+ export { isIPV4OrHostname, Servers } from "./servers.ts";
147
+
148
+ export { wsconnect, wsUrlParseFn } from "./ws_transport.ts";
149
+
150
+ export type { WsConnectionOptions, WsSocketFactory } from "./ws_transport.ts";
151
+
152
+ export {
153
+ AuthorizationError,
154
+ ClosedConnectionError,
155
+ ConnectionError,
156
+ DrainingConnectionError,
157
+ errors,
158
+ InvalidArgumentError,
159
+ InvalidOperationError,
160
+ InvalidSubjectError,
161
+ NoRespondersError,
162
+ PermissionViolationError,
163
+ ProtocolError,
164
+ RequestError,
165
+ TimeoutError,
166
+ UserAuthenticationExpiredError,
167
+ } from "./errors.ts";
@@ -0,0 +1,215 @@
1
+ /*
2
+ * Copyright 2020-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
+ // JavaScript port of go net/ip/ParseIP
17
+ // https://github.com/golang/go/blob/master/src/net/ip.go
18
+ // Copyright 2009 The Go Authors. All rights reserved.
19
+ // Use of this source code is governed by a BSD-style
20
+ // license that can be found in the LICENSE file.
21
+
22
+ const IPv4LEN = 4;
23
+ const IPv6LEN = 16;
24
+ const ASCII0 = 48;
25
+ const ASCII9 = 57;
26
+ const ASCIIA = 65;
27
+ const ASCIIF = 70;
28
+ const ASCIIa = 97;
29
+ const ASCIIf = 102;
30
+ const big = 0xFFFFFF;
31
+
32
+ export function ipV4(a: number, b: number, c: number, d: number): Uint8Array {
33
+ const ip = new Uint8Array(IPv6LEN);
34
+ const prefix = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff];
35
+ prefix.forEach((v, idx) => {
36
+ ip[idx] = v;
37
+ });
38
+ ip[12] = a;
39
+ ip[13] = b;
40
+ ip[14] = c;
41
+ ip[15] = d;
42
+
43
+ return ip;
44
+ }
45
+
46
+ export function isIP(h: string): boolean {
47
+ return parseIP(h) !== undefined;
48
+ }
49
+
50
+ export function parseIP(h: string): Uint8Array | undefined {
51
+ for (let i = 0; i < h.length; i++) {
52
+ switch (h[i]) {
53
+ case ".":
54
+ return parseIPv4(h);
55
+ case ":":
56
+ return parseIPv6(h);
57
+ }
58
+ }
59
+ return;
60
+ }
61
+
62
+ function parseIPv4(s: string): Uint8Array | undefined {
63
+ const ip = new Uint8Array(IPv4LEN);
64
+ for (let i = 0; i < IPv4LEN; i++) {
65
+ if (s.length === 0) {
66
+ return undefined;
67
+ }
68
+ if (i > 0) {
69
+ if (s[0] !== ".") {
70
+ return undefined;
71
+ }
72
+ s = s.substring(1);
73
+ }
74
+ const { n, c, ok } = dtoi(s);
75
+ if (!ok || n > 0xFF) {
76
+ return undefined;
77
+ }
78
+ s = s.substring(c);
79
+ ip[i] = n;
80
+ }
81
+ return ipV4(ip[0], ip[1], ip[2], ip[3]);
82
+ }
83
+
84
+ function parseIPv6(s: string): Uint8Array | undefined {
85
+ const ip = new Uint8Array(IPv6LEN);
86
+ let ellipsis = -1;
87
+
88
+ if (s.length >= 2 && s[0] === ":" && s[1] === ":") {
89
+ ellipsis = 0;
90
+ s = s.substring(2);
91
+ if (s.length === 0) {
92
+ return ip;
93
+ }
94
+ }
95
+
96
+ let i = 0;
97
+ while (i < IPv6LEN) {
98
+ const { n, c, ok } = xtoi(s);
99
+ if (!ok || n > 0xFFFF) {
100
+ return undefined;
101
+ }
102
+
103
+ if (c < s.length && s[c] === ".") {
104
+ if (ellipsis < 0 && i != IPv6LEN - IPv4LEN) {
105
+ return undefined;
106
+ }
107
+ if (i + IPv4LEN > IPv6LEN) {
108
+ return undefined;
109
+ }
110
+ const ip4 = parseIPv4(s);
111
+ if (ip4 === undefined) {
112
+ return undefined;
113
+ }
114
+ ip[i] = ip4[12];
115
+ ip[i + 1] = ip4[13];
116
+ ip[i + 2] = ip4[14];
117
+ ip[i + 3] = ip4[15];
118
+ s = "";
119
+ i += IPv4LEN;
120
+ break;
121
+ }
122
+
123
+ ip[i] = n >> 8;
124
+ ip[i + 1] = n;
125
+ i += 2;
126
+
127
+ s = s.substring(c);
128
+ if (s.length === 0) {
129
+ break;
130
+ }
131
+
132
+ if (s[0] !== ":" || s.length == 1) {
133
+ return undefined;
134
+ }
135
+
136
+ s = s.substring(1);
137
+
138
+ if (s[0] === ":") {
139
+ if (ellipsis >= 0) {
140
+ return undefined;
141
+ }
142
+ ellipsis = i;
143
+ s = s.substring(1);
144
+ if (s.length === 0) {
145
+ break;
146
+ }
147
+ }
148
+ }
149
+
150
+ if (s.length !== 0) {
151
+ return undefined;
152
+ }
153
+
154
+ if (i < IPv6LEN) {
155
+ if (ellipsis < 0) {
156
+ return undefined;
157
+ }
158
+
159
+ const n = IPv6LEN - i;
160
+ for (let j = i - 1; j >= ellipsis; j--) {
161
+ ip[j + n] = ip[j];
162
+ }
163
+ for (let j = ellipsis + n - 1; j >= ellipsis; j--) {
164
+ ip[j] = 0;
165
+ }
166
+ } else if (ellipsis >= 0) {
167
+ return undefined;
168
+ }
169
+ return ip;
170
+ }
171
+
172
+ function dtoi(s: string): { n: number; c: number; ok: boolean } {
173
+ let i = 0;
174
+ let n = 0;
175
+ for (
176
+ i = 0;
177
+ i < s.length && ASCII0 <= s.charCodeAt(i) && s.charCodeAt(i) <= ASCII9;
178
+ i++
179
+ ) {
180
+ n = n * 10 + (s.charCodeAt(i) - ASCII0);
181
+ if (n >= big) {
182
+ return { n: big, c: i, ok: false };
183
+ }
184
+ }
185
+ if (i === 0) {
186
+ return { n: 0, c: 0, ok: false };
187
+ }
188
+ return { n: n, c: i, ok: true };
189
+ }
190
+
191
+ function xtoi(s: string): { n: number; c: number; ok: boolean } {
192
+ let n = 0;
193
+ let i = 0;
194
+ for (i = 0; i < s.length; i++) {
195
+ if (ASCII0 <= s.charCodeAt(i) && s.charCodeAt(i) <= ASCII9) {
196
+ n *= 16;
197
+ n += s.charCodeAt(i) - ASCII0;
198
+ } else if (ASCIIa <= s.charCodeAt(i) && s.charCodeAt(i) <= ASCIIf) {
199
+ n *= 16;
200
+ n += (s.charCodeAt(i) - ASCIIa) + 10;
201
+ } else if (ASCIIA <= s.charCodeAt(i) && s.charCodeAt(i) <= ASCIIF) {
202
+ n *= 16;
203
+ n += (s.charCodeAt(i) - ASCIIA) + 10;
204
+ } else {
205
+ break;
206
+ }
207
+ if (n >= big) {
208
+ return { n: 0, c: i, ok: false };
209
+ }
210
+ }
211
+ if (i === 0) {
212
+ return { n: 0, c: i, ok: false };
213
+ }
214
+ return { n: n, c: i, ok: true };
215
+ }