Skip to content

Commit 1f92d64

Browse files
Princesseuhmatthewpnatemoo-re
authored
Drop Node 14 support (#5782)
* chore: Update engines field * fix(deps): Remove node-fetch * feat(polyfills): Remove node-fetch for undici * feat(webapi): Remove node-fetch from the webapis polyfills for undici * feat(core): Remove node-fetch for undici in Astro core * feat(telemetry): Remove node-fetch for undici * feat(node): Remove node-fetch for undici in node integration * feat(vercel): Remove node-fetch for undici in Vercel integration * chore: update lockfile * chore: update lockfile * chore: changeset * fix(set): Fix set directives not streaming correctly on Node 16 * Try another approach * Debugging * Debug fetch * Use global fetch if there is one * changeset for lit * Remove web-streams-polyfill * Remove web-streams-polyfill license note * Update .changeset/stupid-wolves-explain.md Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com> Co-authored-by: Matthew Phillips <matthew@skypack.dev> Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
1 parent 9bb08bf commit 1f92d64

File tree

36 files changed

+147
-387
lines changed

36 files changed

+147
-387
lines changed

.changeset/chatty-rivers-camp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/lit': patch
3+
---
4+
5+
Only shim fetch if not already present

.changeset/curvy-beds-warn.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'astro': major
3+
'@astrojs/prism': major
4+
'create-astro': major
5+
'@astrojs/mdx': minor
6+
'@astrojs/node': major
7+
'@astrojs/preact': major
8+
'@astrojs/react': major
9+
'@astrojs/solid-js': major
10+
'@astrojs/svelte': major
11+
'@astrojs/vercel': major
12+
'@astrojs/vue': major
13+
'@astrojs/telemetry': major
14+
---
15+
16+
Remove support for Node 14. Minimum supported Node version is now >=16.12.0
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@astrojs/webapi': major
3+
---
4+
5+
Replace node-fetch's polyfill with undici.
6+
7+
Since `undici` does not support it, this change also removes custom support for the `file:` protocol

packages/astro-prism/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@
3535
"@types/prismjs": "1.26.0"
3636
},
3737
"engines": {
38-
"node": "^14.18.0 || >=16.12.0"
38+
"node": ">=16.12.0"
3939
}
4040
}

packages/astro/astro.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ async function main() {
5050
// it's okay to hard-code the valid Node versions here since they will not change over time.
5151
if (typeof require === 'undefined') {
5252
console.error(`\nNode.js v${version} is not supported by Astro!
53-
Please upgrade to a version of Node.js with complete ESM support: "^14.18.0 || >=16.12.0"\n`);
53+
Please upgrade to a supported version of Node.js: ">=16.12.0"\n`);
5454
}
5555

5656
// Not supported: Report the most helpful error message possible.

packages/astro/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@
199199
"eol": "^0.9.1",
200200
"memfs": "^3.4.7",
201201
"mocha": "^9.2.2",
202-
"node-fetch": "^3.2.5",
203202
"node-mocks-http": "^1.11.0",
204203
"rehype-autolink-headings": "^6.1.1",
205204
"rehype-slug": "^5.0.1",
@@ -208,10 +207,11 @@
208207
"rollup": "^3.9.0",
209208
"sass": "^1.52.2",
210209
"srcset-parse": "^1.1.0",
210+
"undici": "^5.14.0",
211211
"unified": "^10.1.2"
212212
},
213213
"engines": {
214-
"node": "^14.18.0 || >=16.12.0",
214+
"node": ">=16.12.0",
215215
"npm": ">=6.14.0"
216216
}
217217
}

packages/astro/src/runtime/server/escape.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { escape } from 'html-escaper';
2+
import { streamAsyncIterator } from './util.js';
23

34
// Leverage the battle-tested `html-escaper` npm package.
45
export const escapeHTML = escape;
@@ -58,9 +59,19 @@ export function isHTMLBytes(value: any): value is HTMLBytes {
5859
return Object.prototype.toString.call(value) === '[object HTMLBytes]';
5960
}
6061

61-
async function* unescapeChunksAsync(iterable: AsyncIterable<Uint8Array>): any {
62-
for await (const chunk of iterable) {
63-
yield unescapeHTML(chunk as BlessedType);
62+
function hasGetReader(obj: unknown): obj is ReadableStream {
63+
return typeof (obj as any).getReader === 'function';
64+
}
65+
66+
async function* unescapeChunksAsync(iterable: ReadableStream | string): any {
67+
if (hasGetReader(iterable)) {
68+
for await (const chunk of streamAsyncIterator(iterable)) {
69+
yield unescapeHTML(chunk as BlessedType);
70+
}
71+
} else {
72+
for await (const chunk of iterable) {
73+
yield unescapeHTML(chunk as BlessedType);
74+
}
6475
}
6576
}
6677

@@ -82,7 +93,7 @@ export function unescapeHTML(
8293
}
8394
// If a response, stream out the chunks
8495
else if (str instanceof Response && str.body) {
85-
const body = str.body as unknown as AsyncIterable<Uint8Array>;
96+
const body = str.body;
8697
return unescapeChunksAsync(body);
8798
}
8899
// If a promise, await the result and mark that.
@@ -92,7 +103,7 @@ export function unescapeHTML(
92103
});
93104
} else if (Symbol.iterator in str) {
94105
return unescapeChunks(str);
95-
} else if (Symbol.asyncIterator in str) {
106+
} else if (Symbol.asyncIterator in str || hasGetReader(str)) {
96107
return unescapeChunksAsync(str);
97108
}
98109
}

packages/astro/src/runtime/server/response.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { streamAsyncIterator } from './util.js';
2+
13
const isNodeJS =
24
typeof process === 'object' && Object.prototype.toString.call(process) === '[object process]';
35

@@ -21,9 +23,9 @@ function createResponseClass() {
2123
async text(): Promise<string> {
2224
if (this.#isStream && isNodeJS) {
2325
let decoder = new TextDecoder();
24-
let body = this.#body as AsyncIterable<Uint8Array>;
26+
let body = this.#body;
2527
let out = '';
26-
for await (let chunk of body) {
28+
for await (let chunk of streamAsyncIterator(body)) {
2729
out += decoder.decode(chunk);
2830
}
2931
return out;
@@ -33,10 +35,10 @@ function createResponseClass() {
3335

3436
async arrayBuffer(): Promise<ArrayBuffer> {
3537
if (this.#isStream && isNodeJS) {
36-
let body = this.#body as AsyncIterable<Uint8Array>;
38+
let body = this.#body;
3739
let chunks: Uint8Array[] = [];
3840
let len = 0;
39-
for await (let chunk of body) {
41+
for await (let chunk of streamAsyncIterator(body)) {
4042
chunks.push(chunk);
4143
len += chunk.length;
4244
}

packages/astro/src/runtime/server/util.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,17 @@ export function serializeListValue(value: any) {
3131
export function isPromise<T = any>(value: any): value is Promise<T> {
3232
return !!value && typeof value === 'object' && typeof value.then === 'function';
3333
}
34+
35+
export async function* streamAsyncIterator(stream: ReadableStream) {
36+
const reader = stream.getReader();
37+
38+
try {
39+
while (true) {
40+
const { done, value } = await reader.read();
41+
if (done) return;
42+
yield value;
43+
}
44+
} finally {
45+
reader.releaseLock();
46+
}
47+
}

packages/astro/test/ssr-api-route.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from 'chai';
2-
import { loadFixture } from './test-utils.js';
2+
import { File, FormData } from 'undici';
33
import testAdapter from './test-adapter.js';
4-
import { FormData, File } from 'node-fetch';
4+
import { loadFixture } from './test-utils.js';
55

66
describe('API routes in SSR', () => {
77
/** @type {import('./test-utils').Fixture} */

0 commit comments

Comments
 (0)