Skip to content

Commit ebe2e09

Browse files
authored
Merge pull request #35 from tkrotoff/remove-old-browsers-support
Remove old browsers support
2 parents e070b8d + 2691778 commit ebe2e09

30 files changed

+1653
-8537
lines changed

.github/workflows/node.js.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111

1212
strategy:
1313
matrix:
14-
node-version: [14.x, 16.x, 18.x]
14+
node-version: [18.x]
1515

1616
steps:
1717
- uses: actions/checkout@v3

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 0.16.0 (2023/03/03)
2+
3+
- Breaking change: drop old browsers support (#28)
4+
- Remove node-fetch from Node.js example (#36)
5+
- Update npm packages
6+
- Remove Node.js 14 & 16 from CI
7+
18
## 0.15.0 (2022/12/01)
29

310
- Breaking change: createHttpError & createJSONHttpError params are no longer optional

README.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,17 @@ Or copy-paste [Http.ts](src/Http.ts) into your source code.
8888

8989
## JavaScript runtimes support
9090

91-
@tkrotoff/fetch supports Node.js, all modern browsers + IE 11
91+
@tkrotoff/fetch supports Node.js and modern browsers
9292

93-
### With Node.js you need:
93+
### Node.js
9494

95-
- Nothing if Node.js >= 18
96-
- [node-fetch](https://github.com/node-fetch/node-fetch) if Node.js < 18
95+
- Nothing is needed if Node.js >= 18.0
96+
- Use [`--experimental-fetch`](https://nodejs.org/docs/latest-v16.x/api/cli.html#--experimental-fetch) if Node.js >= 16.15 < 18.0
97+
- [node-fetch](https://github.com/node-fetch/node-fetch) if Node.js < 16.15
9798

9899
Check [examples/node](examples/node)
99100

100-
### With IE 11 you need:
101-
102-
- [whatwg-fetch](https://github.com/github/fetch) polyfill
103-
- [core-js](https://github.com/zloirock/core-js) for other modern JS features like async/await
104-
- to transpile @tkrotoff/fetch code to ES5
101+
### Browsers
105102

106103
Check [examples/web](examples/web)
107104

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/* eslint-disable no-throw-literal, jest/no-conditional-expect */
2+
3+
import { getErrorMessage } from './getErrorMessage';
4+
5+
test('throw new Error()', () => {
6+
try {
7+
throw new Error('message');
8+
} catch (e) {
9+
expect(getErrorMessage(e)).toEqual('message');
10+
}
11+
});
12+
13+
test('throw without new Error()', () => {
14+
try {
15+
throw 'message';
16+
} catch (e) {
17+
expect(getErrorMessage(e)).toEqual('"message"');
18+
}
19+
20+
try {
21+
throw 666;
22+
} catch (e) {
23+
expect(getErrorMessage(e)).toEqual('666');
24+
}
25+
26+
try {
27+
throw { error: 'message' };
28+
} catch (e) {
29+
expect(getErrorMessage(e)).toEqual('{"error":"message"}');
30+
}
31+
32+
try {
33+
throw [1, 2, 3];
34+
} catch (e) {
35+
expect(getErrorMessage(e)).toEqual('[1,2,3]');
36+
}
37+
38+
try {
39+
throw undefined;
40+
} catch (e) {
41+
expect(getErrorMessage(e)).toEqual('');
42+
}
43+
44+
try {
45+
// eslint-disable-next-line unicorn/no-null
46+
throw null;
47+
} catch (e) {
48+
expect(getErrorMessage(e)).toEqual('null');
49+
}
50+
});
51+
52+
test('circular reference', () => {
53+
{
54+
const circular = {
55+
error: 'message'
56+
};
57+
// @ts-ignore
58+
circular.myself = circular;
59+
60+
try {
61+
JSON.stringify(circular);
62+
} catch (e) {
63+
expect(getErrorMessage(e)).toEqual(
64+
'Converting circular structure to JSON\n' +
65+
" --> starting at object with constructor 'Object'\n" +
66+
" --- property 'myself' closes the circle"
67+
);
68+
}
69+
70+
try {
71+
throw circular;
72+
} catch (e) {
73+
expect(getErrorMessage(e)).toEqual('[object Object]');
74+
}
75+
}
76+
77+
{
78+
const circular = [1, 2, 3];
79+
// @ts-ignore
80+
circular[0] = circular;
81+
82+
try {
83+
JSON.stringify(circular);
84+
} catch (e) {
85+
expect(getErrorMessage(e)).toEqual(
86+
'Converting circular structure to JSON\n' +
87+
" --> starting at object with constructor 'Array'\n" +
88+
' --- index 0 closes the circle'
89+
);
90+
}
91+
92+
try {
93+
throw circular;
94+
} catch (e) {
95+
expect(getErrorMessage(e)).toEqual(',2,3');
96+
}
97+
}
98+
99+
{
100+
class Circular {
101+
error = 'message';
102+
103+
myself = this;
104+
}
105+
106+
const circular = new Circular();
107+
108+
try {
109+
JSON.stringify(circular);
110+
} catch (e) {
111+
expect(getErrorMessage(e)).toEqual(
112+
'Converting circular structure to JSON\n' +
113+
" --> starting at object with constructor 'Circular'\n" +
114+
" --- property 'myself' closes the circle"
115+
);
116+
}
117+
118+
try {
119+
throw circular;
120+
} catch (e) {
121+
expect(getErrorMessage(e)).toEqual('[object Object]');
122+
}
123+
}
124+
});

examples/node/getErrorMessage.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// https://kentcdodds.com/blog/get-a-catch-block-error-message-with-typescript
2+
3+
type ErrorWithMessage = {
4+
message: string;
5+
};
6+
7+
function isErrorWithMessage(error: unknown): error is ErrorWithMessage {
8+
return (
9+
typeof error === 'object' &&
10+
error !== null &&
11+
'message' in error &&
12+
typeof (error as Record<string, unknown>).message === 'string'
13+
);
14+
}
15+
16+
function toErrorWithMessage(maybeError: unknown): ErrorWithMessage {
17+
if (isErrorWithMessage(maybeError)) return maybeError;
18+
19+
try {
20+
return new Error(JSON.stringify(maybeError));
21+
} catch {
22+
// Fallback in case there's an error stringifying the maybeError
23+
// like with circular references for example
24+
return new Error(String(maybeError));
25+
}
26+
}
27+
28+
export function getErrorMessage(error: unknown) {
29+
return toErrorWithMessage(error).message;
30+
}

examples/node/index.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,19 @@
1-
import { AbortController, AbortSignal } from 'abort-controller';
2-
import * as nodeFetch from 'node-fetch';
3-
41
import {
52
abortRequestExample,
63
del200OKExample,
74
get200OKExample,
85
get404NotFoundExample,
96
get500InternalServerErrorExample,
107
postJSON201CreatedExample
11-
} from './requests.js';
12-
13-
globalThis.fetch = nodeFetch.default as any;
14-
globalThis.Headers = nodeFetch.Headers as any;
15-
globalThis.Response = nodeFetch.Response as any;
16-
17-
// FIXME Remove when support for Node.js < 15.0.0 is dropped, https://nodejs.org/en/blog/release/v15.0.0/
18-
globalThis.AbortController = AbortController as any;
19-
globalThis.AbortSignal = AbortSignal as any;
8+
} from './requests';
209

21-
await get200OKExample();
22-
await postJSON201CreatedExample();
23-
await del200OKExample();
24-
await get404NotFoundExample();
25-
await get500InternalServerErrorExample();
26-
await abortRequestExample();
10+
// FIXME Remove when ESM is enabled
11+
// eslint-disable-next-line func-names, unicorn/prefer-top-level-await
12+
(async function () {
13+
await get200OKExample();
14+
await postJSON201CreatedExample();
15+
await del200OKExample();
16+
await get404NotFoundExample();
17+
await get500InternalServerErrorExample();
18+
await abortRequestExample();
19+
})();

examples/node/jest.config.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
// @ts-check
22

3-
// [How to set transformIgnorePatterns to fix "Jest encountered an unexpected token"](https://github.com/nrwl/nx/issues/812)
4-
const esModules = ['node-fetch', 'data-uri-to-buffer', 'fetch-blob', 'formdata-polyfill'];
5-
63
/** @type import('@jest/types').Config.InitialOptions */
74
const config = {
85
testEnvironment: 'node',
@@ -14,8 +11,6 @@ const config = {
1411
// Let's be strict and use *.test.js only
1512
testRegex: '\\.test\\.ts$',
1613

17-
transformIgnorePatterns: [`/node_modules/(?!${esModules.join('|')})`],
18-
1914
coverageThreshold: {
2015
global: {
2116
statements: 100,
@@ -32,4 +27,4 @@ const config = {
3227
// restoreMocks: true
3328
};
3429

35-
export default config;
30+
module.exports = config;

examples/node/jest.setup.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
1-
import { AbortController, AbortSignal } from 'abort-controller';
21
import assert from 'node:assert';
3-
import * as nodeFetch from 'node-fetch';
42

53
// [console.assert not throwing with v22.4.0](https://github.com/facebook/jest/issues/5634)
64
// eslint-disable-next-line no-console
75
console.assert = assert;
86

9-
globalThis.Headers = nodeFetch.Headers as any;
10-
globalThis.Response = nodeFetch.Response as any;
11-
12-
// FIXME Remove when support for Node.js < 15.0.0 is dropped, https://nodejs.org/en/blog/release/v15.0.0/
13-
globalThis.AbortController = AbortController as any;
14-
globalThis.AbortSignal = AbortSignal as any;
15-
167
(globalThis.fetch as any) = () => {
178
throw new Error('You should mock fetch()');
189
};

examples/node/package.json

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,23 @@
33
"version": "1.0.0",
44
"private": true,
55
"description": "@tkrotoff/fetch Node.js example",
6-
"type": "module",
76
"scripts": {
87
"clean": "rm -rf build coverage",
98
"clean:all": "npm run clean && rm -rf node_modules package-lock.json",
10-
"start": "node --loader ts-node/esm index.ts",
9+
"start": "ts-node index.ts",
1110
"test": "jest --verbose",
1211
"test:coverage": "jest --coverage",
1312
"tsc": "tsc",
1413
"npm:update": "npm run clean:all && npx npm-check-updates --upgrade && npm install"
1514
},
1615
"dependencies": {
1716
"@tkrotoff/fetch": "file:../..",
18-
"abort-controller": "^3.0.0",
19-
"node-fetch": "^3.3.0",
2017
"ts-node": "^10.9.1",
21-
"typescript": "^4.9.3"
18+
"typescript": "^4.9.5"
2219
},
2320
"devDependencies": {
2421
"@babel/preset-env": "^7.20.2",
25-
"@babel/preset-typescript": "^7.18.6",
26-
"jest": "^29.3.1"
22+
"@babel/preset-typescript": "^7.21.0",
23+
"jest": "^29.4.3"
2724
}
2825
}

examples/node/requests.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,7 @@ test('getCorsBlockedExample()', async () => {
9696
});
9797

9898
test('abortRequestExample()', async () => {
99-
// DOMException does not exist with node-fetch
100-
//const abortError = new DOMException('The operation was aborted.', 'AbortError')
101-
const abortError = new Error('The operation was aborted.');
102-
abortError.name = 'AbortError';
99+
const abortError = new DOMException('This operation was aborted', 'AbortError');
103100

104101
const mock = jest.spyOn(Http, 'get').mockImplementation((_input, init) => {
105102
// Mock aborted request

0 commit comments

Comments
 (0)