Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2a7f2a4

Browse files
Add custom error class (#398)
1 parent 265a2a7 commit 2a7f2a4

File tree

2 files changed

+60
-52
lines changed

2 files changed

+60
-52
lines changed

‎src/index.spec.ts

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
stringify,
77
pathToRegexp,
88
TokenData,
9+
PathError,
910
} from "./index.js";
1011
import {
1112
PARSER_TESTS,
@@ -18,44 +19,62 @@ import {
1819
* Dynamically generate the entire test suite.
1920
*/
2021
describe("path-to-regexp", () => {
22+
describe("ParseError", () => {
23+
it("should contain original path and debug url", () => {
24+
const error = new PathError(
25+
"Unexpected END at index 7, expected }",
26+
"/{:foo,",
27+
);
28+
29+
expect(error).toBeInstanceOf(TypeError);
30+
expect(error.message).toBe(
31+
"Unexpected END at index 7, expected }: /{:foo,; visit https://git.new/pathToRegexpError for info",
32+
);
33+
expect(error.originalPath).toBe("/{:foo,");
34+
});
35+
36+
it("should omit original url when undefined", () => {
37+
const error = new PathError(
38+
"Unexpected END at index 7, expected }",
39+
undefined,
40+
);
41+
42+
expect(error).toBeInstanceOf(TypeError);
43+
expect(error.message).toBe(
44+
"Unexpected END at index 7, expected }; visit https://git.new/pathToRegexpError for info",
45+
);
46+
expect(error.originalPath).toBeUndefined();
47+
});
48+
});
49+
2150
describe("parse errors", () => {
2251
it("should throw on unbalanced group", () => {
2352
expect(() => parse("/{:foo,")).toThrow(
24-
new TypeError(
25-
"Unexpected END at index 7, expected }: /{:foo,; visit https://git.new/pathToRegexpError for info",
26-
),
53+
new PathError("Unexpected END at index 7, expected }", "/{:foo,"),
2754
);
2855
});
2956

3057
it("should throw on nested unbalanced group", () => {
3158
expect(() => parse("/{:foo/{x,y}")).toThrow(
32-
new TypeError(
33-
"Unexpected END at index 12, expected }: /{:foo/{x,y}; visit https://git.new/pathToRegexpError for info",
34-
),
59+
new PathError("Unexpected END at index 12, expected }", "/{:foo/{x,y}"),
3560
);
3661
});
3762

3863
it("should throw on missing param name", () => {
3964
expect(() => parse("/:/")).toThrow(
40-
new TypeError(
41-
"Missing parameter name at index 2: /:/; visit https://git.new/pathToRegexpError for info",
42-
),
65+
new PathError("Missing parameter name at index 2", "/:/"),
4366
);
4467
});
4568

4669
it("should throw on missing wildcard name", () => {
4770
expect(() => parse("/*/")).toThrow(
48-
new TypeError(
49-
"Missing parameter name at index 2: /*/; visit https://git.new/pathToRegexpError for info",
50-
),
71+
new PathError("Missing parameter name at index 2", "/*/"),
5172
);
5273
});
5374

5475
it("should throw on unterminated quote", () => {
5576
expect(() => parse('/:"foo')).toThrow(
56-
new TypeError(
57-
'Unterminated quote at index 2: /:"foo; visit https://git.new/pathToRegexpError for info',
58-
),
77+
new PathError("Unterminated quote at index 2", '/:"foo'),
5978
);
6079
});
6180
});
@@ -105,9 +124,7 @@ describe("path-to-regexp", () => {
105124
describe("pathToRegexp errors", () => {
106125
it("should throw when missing text between params", () => {
107126
expect(() => pathToRegexp("/:foo:bar")).toThrow(
108-
new TypeError(
109-
'Missing text before "bar": /:foo:bar; visit https://git.new/pathToRegexpError for info',
110-
),
127+
new PathError('Missing text before "bar" param', "/:foo:bar"),
111128
);
112129
});
113130

@@ -119,11 +136,7 @@ describe("path-to-regexp", () => {
119136
{ type: "param", name: "b" },
120137
]),
121138
),
122-
).toThrow(
123-
new TypeError(
124-
'Missing text before "b"; visit https://git.new/pathToRegexpError for info',
125-
),
126-
);
139+
).toThrow(new PathError('Missing text before "b" param', undefined));
127140
});
128141

129142
it("should throw with `originalPath` when missing text between params using TokenData", () => {
@@ -137,11 +150,7 @@ describe("path-to-regexp", () => {
137150
"/[a][b]",
138151
),
139152
),
140-
).toThrow(
141-
new TypeError(
142-
'Missing text before "b": /[a][b]; visit https://git.new/pathToRegexpError for info',
143-
),
144-
);
153+
).toThrow(new PathError('Missing text before "b" param', "/[a][b]"));
145154
});
146155

147156
it("should contain the error line", () => {

‎src/index.ts

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const DEFAULT_DELIMITER = "/";
22
const NOOP_VALUE = (value: string) => value;
33
const ID_START = /^[$_\p{ID_Start}]$/u;
44
const ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
5-
const DEBUG_URL = "https://git.new/pathToRegexpError";
65

76
/**
87
* Encode a string into another string.
@@ -112,16 +111,6 @@ function escape(str: string) {
112111
return str.replace(/[.+*?^${}()[\]|/\\]/g, "\\$&");
113112
}
114113

115-
/**
116-
* Format error so it's easier to debug.
117-
*/
118-
function errorMessage(text: string, originalPath: string | undefined) {
119-
let message = text;
120-
if (originalPath !== undefined) message += `: ${originalPath}`;
121-
message += `; visit ${DEBUG_URL} for info`;
122-
return message;
123-
}
124-
125114
/**
126115
* Plain text.
127116
*/
@@ -179,6 +168,21 @@ export class TokenData {
179168
) {}
180169
}
181170

171+
/**
172+
* ParseError is thrown when there is an error processing the path.
173+
*/
174+
export class PathError extends TypeError {
175+
constructor(
176+
message: string,
177+
public readonly originalPath: string | undefined,
178+
) {
179+
let text = message;
180+
if (originalPath) text += `: ${originalPath}`;
181+
text += `; visit https://git.new/pathToRegexpError for info`;
182+
super(text);
183+
}
184+
}
185+
182186
/**
183187
* Parse a string for the raw tokens.
184188
*/
@@ -215,16 +219,12 @@ export function parse(str: string, options: ParseOptions = {}): TokenData {
215219
}
216220

217221
if (pos) {
218-
throw new TypeError(
219-
errorMessage(`Unterminated quote at index ${pos}`, str),
220-
);
222+
throw new PathError(`Unterminated quote at index ${pos}`, str);
221223
}
222224
}
223225

224226
if (!value) {
225-
throw new TypeError(
226-
errorMessage(`Missing parameter name at index ${index}`, str),
227-
);
227+
throw new PathError(`Missing parameter name at index ${index}`, str);
228228
}
229229

230230
return value;
@@ -292,11 +292,9 @@ export function parse(str: string, options: ParseOptions = {}): TokenData {
292292
continue;
293293
}
294294

295-
throw new TypeError(
296-
errorMessage(
297-
`Unexpected ${type} at index ${index}, expected ${endType}`,
298-
str,
299-
),
295+
throw new PathError(
296+
`Unexpected ${type} at index ${index}, expected ${endType}`,
297+
str,
300298
);
301299
}
302300

@@ -564,8 +562,9 @@ function toRegExpSource(
564562

565563
if (token.type === "param" || token.type === "wildcard") {
566564
if (!isSafeSegmentParam && !backtrack) {
567-
throw new TypeError(
568-
errorMessage(`Missing text before "${token.name}"`, originalPath),
565+
throw new PathError(
566+
`Missing text before "${token.name}" ${token.type}`,
567+
originalPath,
569568
);
570569
}
571570

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /