Skip to content

Commit c4d2319

Browse files
tommy-mitchellsindresorhus
andauthoredApr 7, 2023
Add TypeScript definition, bump dependencies, target Node.js 16 (#36)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
1 parent d641294 commit c4d2319

File tree

4 files changed

+172
-11
lines changed

4 files changed

+172
-11
lines changed
 

‎.github/workflows/main.yml

+3-4
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13+
- 18
1314
- 16
14-
- 14
15-
- 12
1615
steps:
17-
- uses: actions/checkout@v2
18-
- uses: actions/setup-node@v2
16+
- uses: actions/checkout@v3
17+
- uses: actions/setup-node@v3
1918
with:
2019
node-version: ${{ matrix.node-version }}
2120
- run: npm install

‎index.d.ts

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import type {JsonObject} from 'type-fest';
2+
3+
/**
4+
Exposed for `instanceof` checking.
5+
*/
6+
export type JSONError = Error & { // eslint-disable-line @typescript-eslint/naming-convention
7+
/**
8+
The filename displayed in the error message, if any.
9+
*/
10+
fileName: string;
11+
12+
/**
13+
The printable section of the JSON which produces the error.
14+
*/
15+
readonly codeFrame: string;
16+
};
17+
18+
// Get 'reviver' parameter from JSON.parse()
19+
type ReviverFn = Parameters<typeof JSON['parse']>['1'];
20+
21+
/**
22+
Parse JSON with more helpful errors.
23+
24+
@param string - A valid JSON string.
25+
@param reviver - Prescribes how the value originally produced by parsing is transformed, before being returned. See [`JSON.parse` docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter
26+
) for more.
27+
@param filename - The filename displayed in the error message.
28+
@returns A parsed JSON object.
29+
@throws A {@link JSONError} when there is a parsing error.
30+
31+
@example
32+
```
33+
import parseJson, {JSONError} from 'parse-json';
34+
35+
const json = '{\n\t"foo": true,\n}';
36+
37+
parseJson(json);
38+
// JSONError: Unexpected token } in JSON at position 16 while parsing near '{ "foo": true,}'
39+
//
40+
// 1 | {
41+
// 2 | "foo": true,
42+
// > 3 | }
43+
// | ^
44+
45+
parseJson(json, 'foo.json');
46+
// JSONError: Unexpected token } in JSON at position 16 while parsing near '{ "foo": true,}' in foo.json
47+
//
48+
// 1 | {
49+
// 2 | "foo": true,
50+
// > 3 | }
51+
// | ^
52+
53+
// You can also add the filename at a later point
54+
try {
55+
parseJson(json);
56+
} catch (error) {
57+
if (error instanceof JSONError) {
58+
error.fileName = 'foo.json';
59+
}
60+
61+
throw error;
62+
}
63+
// JSONError: Unexpected token } in JSON at position 16 while parsing near '{ "foo": true,}' in foo.json
64+
//
65+
// 1 | {
66+
// 2 | "foo": true,
67+
// > 3 | }
68+
// | ^
69+
```
70+
*/
71+
export default function parseJson(string: string, reviver?: ReviverFn, filename?: string): JsonObject;
72+
73+
/**
74+
Parse JSON with more helpful errors.
75+
76+
@param string - A valid JSON string.
77+
@param filename - The filename displayed in the error message.
78+
@returns A parsed JSON object.
79+
@throws A {@link JSONError} when there is a parsing error.
80+
81+
@example
82+
```
83+
import parseJson, {JSONError} from 'parse-json';
84+
85+
const json = '{\n\t"foo": true,\n}';
86+
87+
parseJson(json);
88+
// JSONError: Unexpected token } in JSON at position 16 while parsing near '{ "foo": true,}'
89+
//
90+
// 1 | {
91+
// 2 | "foo": true,
92+
// > 3 | }
93+
// | ^
94+
95+
parseJson(json, 'foo.json');
96+
// JSONError: Unexpected token } in JSON at position 16 while parsing near '{ "foo": true,}' in foo.json
97+
//
98+
// 1 | {
99+
// 2 | "foo": true,
100+
// > 3 | }
101+
// | ^
102+
103+
// You can also add the filename at a later point
104+
try {
105+
parseJson(json);
106+
} catch (error) {
107+
if (error instanceof JSONError) {
108+
error.fileName = 'foo.json';
109+
}
110+
111+
throw error;
112+
}
113+
// JSONError: Unexpected token } in JSON at position 16 while parsing near '{ "foo": true,}' in foo.json
114+
//
115+
// 1 | {
116+
// 2 | "foo": true,
117+
// > 3 | }
118+
// | ^
119+
```
120+
*/
121+
export default function parseJson(string: string, filename?: string): JsonObject;

‎index.test-d.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {expectType, expectError} from 'tsd';
2+
import type {JsonObject} from 'type-fest';
3+
import parseJson, {type JSONError} from './index.js';
4+
5+
expectError(parseJson());
6+
expectError(parseJson({foo: true}));
7+
expectType<JsonObject>(parseJson('{"foo": true}'));
8+
expectType<JsonObject>(parseJson('{"foo": true}', 'foo.json'));
9+
expectType<JsonObject>(parseJson('{"foo": true}', (key, value) => String(value)));
10+
expectType<JsonObject>(parseJson('{"foo": true}', (key, value) => String(value), 'foo.json'));
11+
12+
expectType<string>((() => {
13+
let x: string;
14+
parseJson('{"foo": true}', (key, value) => x = key); // eslint-disable-line no-return-assign
15+
return x!;
16+
})());
17+
18+
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return */
19+
expectType<any>((() => {
20+
let x: any;
21+
parseJson('{"foo": true}', (key, value) => x = value); // eslint-disable-line no-return-assign
22+
return x;
23+
})());
24+
/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return */
25+
26+
const jsonError: JSONError = {
27+
name: 'JSONError',
28+
message: 'Unexpected token } in JSON at position 16 while parsing near \'{ "foo": true,}\'',
29+
fileName: 'foo.json',
30+
codeFrame: `
31+
1 | {
32+
2 | "foo": true,
33+
> 3 | }
34+
| ^
35+
`,
36+
};
37+
38+
expectError(jsonError.codeFrame = '');

‎package.json

+10-7
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
"type": "module",
1414
"exports": "./index.js",
1515
"engines": {
16-
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
16+
"node": ">=16"
1717
},
1818
"scripts": {
19-
"test": "xo && nyc ava"
19+
"test": "xo && nyc ava && tsd"
2020
},
2121
"files": [
2222
"index.js",
23+
"index.d.ts",
2324
"vendor"
2425
],
2526
"keywords": [
@@ -34,14 +35,16 @@
3435
"string"
3536
],
3637
"dependencies": {
37-
"@babel/code-frame": "^7.16.0",
38+
"@babel/code-frame": "^7.21.4",
3839
"error-ex": "^1.3.2",
39-
"json-parse-even-better-errors": "^2.3.1",
40-
"lines-and-columns": "^2.0.2"
40+
"json-parse-even-better-errors": "^3.0.0",
41+
"lines-and-columns": "^2.0.3",
42+
"type-fest": "^3.8.0"
4143
},
4244
"devDependencies": {
43-
"ava": "^3.15.0",
45+
"ava": "^5.2.0",
4446
"nyc": "^15.1.0",
45-
"xo": "^0.46.4"
47+
"tsd": "^0.28.1",
48+
"xo": "^0.54.0"
4649
}
4750
}

0 commit comments

Comments
 (0)
Please sign in to comment.