Skip to content

Commit 92a1128

Browse files
committed
wip errors
Signed-off-by: Alberto Ricart <[email protected]>
1 parent c12d5cd commit 92a1128

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+428
-364
lines changed

core/deno.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nats-io/nats-core",
3-
"version": "3.0.0-32",
3+
"version": "3.0.0-34",
44
"exports": {
55
".": "./src/mod.ts",
66
"./internal": "./src/internal_mod.ts"

core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nats-io/nats-core",
3-
"version": "3.0.0-32",
3+
"version": "3.0.0-34",
44
"files": [
55
"lib/",
66
"LICENSE",

core/src/core.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*/
1515

1616
import { nuid } from "./nuid.ts";
17-
import { errors, InvalidArgumentError } from "./errors.ts";
17+
import { InvalidArgumentError } from "./errors.ts";
1818

1919
/**
2020
* Events reported by the {@link NatsConnection#status} iterator.
@@ -663,11 +663,9 @@ export function createInbox(prefix = ""): string {
663663
prefix.split(".")
664664
.forEach((v) => {
665665
if (v === "*" || v === ">") {
666-
throw new errors.InvalidArgumentError(
667-
InvalidArgumentError.format(
668-
"prefix",
669-
`cannot have wildcards ('${prefix}')`,
670-
),
666+
throw InvalidArgumentError.format(
667+
"prefix",
668+
`cannot have wildcards ('${prefix}')`,
671669
);
672670
}
673671
});

core/src/errors.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,21 @@ export class InvalidArgumentError extends Error {
3333
this.name = "InvalidArgumentError";
3434
}
3535

36-
static format(name: string, message: string): string {
37-
return `'${name}' ${message}`;
38-
}
39-
40-
static formatMultiple(names: string[], message: string): string {
41-
names = names.map((n) => `'${n}'`);
42-
return `${names.join(",")} ${message}`;
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);
4351
}
4452
}
4553

@@ -186,6 +194,10 @@ export class RequestError extends Error {
186194
super(message, options);
187195
this.name = "RequestError";
188196
}
197+
198+
isNoResponders(): boolean {
199+
return this.cause instanceof NoRespondersError;
200+
}
189201
}
190202

191203
/**

core/src/headers.ts

+8-17
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import { TD, TE } from "./encoders.ts";
1919
import type { MsgHdrs } from "./core.ts";
2020
import { Match } from "./core.ts";
21-
import { errors } from "./errors.ts";
21+
import { InvalidArgumentError } from "./errors.ts";
2222

2323
// https://www.ietf.org/rfc/rfc822.txt
2424
// 3.1.2. STRUCTURE OF HEADER FIELDS
@@ -48,11 +48,9 @@ export function canonicalMIMEHeaderKey(k: string): string {
4848
for (let i = 0; i < k.length; i++) {
4949
let c = k.charCodeAt(i);
5050
if (c === colon || c < start || c > end) {
51-
throw new errors.InvalidArgumentError(
52-
errors.InvalidArgumentError.format(
53-
"header",
54-
`'${k[i]}' is not a valid character in a header name`,
55-
),
51+
throw InvalidArgumentError.format(
52+
"header",
53+
`'${k[i]}' is not a valid character in a header name`,
5654
);
5755
}
5856
if (upper && a <= c && c <= z) {
@@ -68,12 +66,7 @@ export function canonicalMIMEHeaderKey(k: string): string {
6866

6967
export function headers(code = 0, description = ""): MsgHdrs {
7068
if ((code === 0 && description !== "") || (code > 0 && description === "")) {
71-
throw new errors.InvalidArgumentError(
72-
errors.InvalidArgumentError.format(
73-
"description",
74-
"is required",
75-
),
76-
);
69+
throw InvalidArgumentError.format("description", "is required");
7770
}
7871
return new MsgHdrsImpl(code, description);
7972
}
@@ -178,11 +171,9 @@ export class MsgHdrsImpl implements MsgHdrs {
178171
static validHeaderValue(k: string): string {
179172
const inv = /[\r\n]/;
180173
if (inv.test(k)) {
181-
throw new errors.InvalidArgumentError(
182-
errors.InvalidArgumentError.format(
183-
"header",
184-
"values cannot contain \\r or \\n",
185-
),
174+
throw InvalidArgumentError.format(
175+
"header",
176+
"values cannot contain \\r or \\n",
186177
);
187178
}
188179
return k.trim();

core/src/internal_mod.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,19 @@ export { SHA256 } from "./sha256.ts";
139139

140140
export { wsconnect, wsUrlParseFn } from "./ws_transport.ts";
141141

142-
export { errors } from "./errors.ts";
142+
export {
143+
AuthorizationError,
144+
ClosedConnectionError,
145+
ConnectionError,
146+
DrainingConnectionError,
147+
errors,
148+
InvalidArgumentError,
149+
InvalidOperationError,
150+
InvalidSubjectError,
151+
NoRespondersError,
152+
PermissionViolationError,
153+
ProtocolError,
154+
RequestError,
155+
TimeoutError,
156+
UserAuthenticationExpiredError,
157+
} from "./errors.ts";

core/src/mod.ts

+13
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,27 @@
1414
*/
1515

1616
export {
17+
AuthorizationError,
1718
backoff,
1819
Bench,
1920
buildAuthenticator,
2021
canonicalMIMEHeaderKey,
22+
ClosedConnectionError,
23+
ConnectionError,
2124
createInbox,
2225
credsAuthenticator,
2326
deadline,
2427
DebugEvents,
2528
deferred,
2629
delay,
30+
DrainingConnectionError,
2731
Empty,
2832
errors,
2933
Events,
3034
headers,
35+
InvalidArgumentError,
36+
InvalidOperationError,
37+
InvalidSubjectError,
3138
jwtAuthenticator,
3239
Match,
3340
Metric,
@@ -36,11 +43,17 @@ export {
3643
nanos,
3744
nkeyAuthenticator,
3845
nkeys,
46+
NoRespondersError,
3947
Nuid,
4048
nuid,
49+
PermissionViolationError,
50+
ProtocolError,
51+
RequestError,
4152
RequestStrategy,
4253
syncIterator,
54+
TimeoutError,
4355
tokenAuthenticator,
56+
UserAuthenticationExpiredError,
4457
usernamePasswordAuthenticator,
4558
wsconnect,
4659
} from "./internal_mod.ts";

core/src/nats.ts

+22-26
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,13 @@ import { parseSemVer } from "./semver.ts";
2222

2323
import { parseOptions } from "./options.ts";
2424
import { QueuedIteratorImpl } from "./queued_iterator.ts";
25-
import { RequestMany, RequestOne } from "./request.ts";
26-
2725
import type { RequestManyOptionsInternal } from "./request.ts";
28-
29-
import { createInbox, RequestStrategy } from "./core.ts";
30-
import type { Dispatcher } from "./core.ts";
26+
import { RequestMany, RequestOne } from "./request.ts";
3127

3228
import type {
3329
ConnectionOptions,
3430
Context,
31+
Dispatcher,
3532
Msg,
3633
NatsConnection,
3734
Payload,
@@ -45,7 +42,8 @@ import type {
4542
Subscription,
4643
SubscriptionOptions,
4744
} from "./core.ts";
48-
import { errors, InvalidArgumentError } from "./errors.ts";
45+
import { createInbox, RequestStrategy } from "./core.ts";
46+
import { errors, InvalidArgumentError, TimeoutError } from "./errors.ts";
4947

5048
export class NatsConnectionImpl implements NatsConnection {
5149
options: ConnectionOptions;
@@ -110,6 +108,9 @@ export class NatsConnectionImpl implements NatsConnection {
110108
options?: PublishOptions,
111109
): void {
112110
this._check(subject, false, true);
111+
if (options?.reply) {
112+
this._check(options.reply, false, true);
113+
}
113114
this.protocol.publish(subject, data, options);
114115
}
115116

@@ -185,10 +186,7 @@ export class NatsConnectionImpl implements NatsConnection {
185186
opts.maxWait = opts.maxWait || 1000;
186187
if (opts.maxWait < 1) {
187188
return Promise.reject(
188-
new errors.InvalidArgumentError(InvalidArgumentError.format(
189-
"timeout",
190-
"must be greater than 0",
191-
)),
189+
InvalidArgumentError.format("timeout", "must be greater than 0"),
192190
);
193191
}
194192

@@ -353,18 +351,14 @@ export class NatsConnectionImpl implements NatsConnection {
353351
opts.timeout = opts.timeout || 1000;
354352
if (opts.timeout < 1) {
355353
return Promise.reject(
356-
new errors.InvalidArgumentError(
357-
InvalidArgumentError.format("timeout", `must be greater than 0`),
358-
),
354+
InvalidArgumentError.format("timeout", `must be greater than 0`),
359355
);
360356
}
361357
if (!opts.noMux && opts.reply) {
362358
return Promise.reject(
363-
new errors.InvalidArgumentError(
364-
InvalidArgumentError.formatMultiple(
365-
["reply", "noMux"],
366-
"are mutually exclusive",
367-
),
359+
InvalidArgumentError.format(
360+
["reply", "noMux"],
361+
"are mutually exclusive",
368362
),
369363
);
370364
}
@@ -381,18 +375,20 @@ export class NatsConnectionImpl implements NatsConnection {
381375
max: 1,
382376
timeout: opts.timeout,
383377
callback: (err, msg) => {
384-
// check for no responders
378+
// check for no responders status
385379
if (msg && msg.data?.length === 0 && msg.headers?.code === 503) {
386380
err = new errors.NoRespondersError(subject);
387381
}
388382
if (err) {
389-
// if we have a context, use that as the wrapper
390-
if (errCtx) {
391-
errCtx.message = err.message;
392-
errCtx.cause = err;
393-
err = errCtx;
394-
} else {
395-
err = new errors.RequestError(err.message, { cause: err });
383+
// we have a proper stack on timeout
384+
if (!(err instanceof TimeoutError)) {
385+
if (errCtx) {
386+
errCtx.message = err.message;
387+
errCtx.cause = err;
388+
err = errCtx;
389+
} else {
390+
err = new errors.RequestError(err.message, { cause: err });
391+
}
396392
}
397393
d.reject(err);
398394
sub.unsubscribe();

core/src/options.ts

+8-14
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
tokenAuthenticator,
2424
usernamePasswordAuthenticator,
2525
} from "./authenticator.ts";
26-
import { errors } from "./errors.ts";
26+
import { errors, InvalidArgumentError } from "./errors.ts";
2727

2828
export const DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;
2929
export const DEFAULT_JITTER = 100;
@@ -84,11 +84,9 @@ export function parseOptions(opts?: ConnectionOptions): ConnectionOptions {
8484
}
8585

8686
if (opts.servers.length > 0 && opts.port) {
87-
throw new errors.InvalidArgumentError(
88-
errors.InvalidArgumentError.formatMultiple(
89-
["servers", "port"],
90-
"are mutually exclusive",
91-
),
87+
throw InvalidArgumentError.format(
88+
["servers", "port"],
89+
"are mutually exclusive",
9290
);
9391
}
9492

@@ -133,11 +131,9 @@ export function parseOptions(opts?: ConnectionOptions): ConnectionOptions {
133131

134132
if (options.resolve) {
135133
if (typeof getResolveFn() !== "function") {
136-
throw new errors.InvalidArgumentError(
137-
errors.InvalidArgumentError.format(
138-
"resolve",
139-
"is not supported in the current runtime",
140-
),
134+
throw InvalidArgumentError.format(
135+
"resolve",
136+
"is not supported in the current runtime",
141137
);
142138
}
143139
}
@@ -159,8 +155,6 @@ export function checkOptions(info: ServerInfo, options: ConnectionOptions) {
159155

160156
export function checkUnsupportedOption(prop: string, v?: unknown) {
161157
if (v) {
162-
throw new errors.InvalidArgumentError(
163-
errors.InvalidArgumentError.format(prop, "is not supported"),
164-
);
158+
throw InvalidArgumentError.format(prop, "is not supported");
165159
}
166160
}

core/src/protocol.ts

+6-12
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@ import {
5050
DEFAULT_PING_INTERVAL,
5151
DEFAULT_RECONNECT_TIME_WAIT,
5252
} from "./options.ts";
53+
import { errors, InvalidArgumentError } from "./errors.ts";
54+
5355
import type {
5456
AuthorizationError,
5557
PermissionViolationError,
5658
UserAuthenticationExpiredError,
5759
} from "./errors.ts";
58-
import { errors } from "./errors.ts";
5960

6061
const FLUSH_THRESHOLD = 1024 * 32;
6162

@@ -870,11 +871,9 @@ export class ProtocolHandler implements Dispatcher<ParserEvent> {
870871
let hlen = 0;
871872
if (options.headers) {
872873
if (this.info && !this.info.headers) {
873-
throw new errors.InvalidArgumentError(
874-
errors.InvalidArgumentError.format(
875-
"headers",
876-
"are not available on this server",
877-
),
874+
InvalidArgumentError.format(
875+
"headers",
876+
"are not available on this server",
878877
);
879878
}
880879
const hdrs = options.headers as MsgHdrsImpl;
@@ -884,12 +883,7 @@ export class ProtocolHandler implements Dispatcher<ParserEvent> {
884883
}
885884

886885
if (this.info && len > this.info.max_payload) {
887-
throw new errors.InvalidArgumentError(
888-
errors.InvalidArgumentError.format(
889-
"payload",
890-
"max_payload size exceeded",
891-
),
892-
);
886+
throw InvalidArgumentError.format("payload", "max_payload size exceeded");
893887
}
894888
this.outBytes += len;
895889
this.outMsgs++;

0 commit comments

Comments
 (0)