pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/angular/angular-cli/commit/d06ff3f408d30e0db11a2bc5f65d3ffa81b22643

c08.css" /> fix(@angular/cli): update min Node.js support to 20.19, 22.12, and 24.0 · angular/angular-cli@d06ff3f · GitHub
Skip to content

Commit d06ff3f

Browse files
committed
fix(@angular/cli): update min Node.js support to 20.19, 22.12, and 24.0
Bumps the minimum Node.js support for `@angular/cli`. This update ensures compatibility with a growing number of upstream dependencies, such as Undici and Pacote, that are adopting newer Node.js versions. These versions where selected as `require(esm)` is enabled by default. This change also prepares us for future package releases that will likely rely on this behavior.
1 parent 87f4121 commit d06ff3f

File tree

9 files changed

+77
-66
lines changed

9 files changed

+77
-66
lines changed

WORKSPACE

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
workspace(name = "angular_cli")
22

3-
DEFAULT_NODE_VERSION = "20.11.1"
4-
53
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
64

75
http_archive(
@@ -61,65 +59,65 @@ rules_pkg_dependencies()
6159
# Setup the Node.js toolchain
6260
load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
6361

64-
NODE_20_REPO = {
65-
"20.11.1-darwin_arm64": ("node-v20.11.1-darwin-arm64.tar.gz", "node-v20.11.1-darwin-arm64", "e0065c61f340e85106a99c4b54746c5cee09d59b08c5712f67f99e92aa44995d"),
66-
"20.11.1-darwin_amd64": ("node-v20.11.1-darwin-x64.tar.gz", "node-v20.11.1-darwin-x64", "c52e7fb0709dbe63a4cbe08ac8af3479188692937a7bd8e776e0eedfa33bb848"),
67-
"20.11.1-linux_arm64": ("node-v20.11.1-linux-arm64.tar.xz", "node-v20.11.1-linux-arm64", "c957f29eb4e341903520caf362534f0acd1db7be79c502ae8e283994eed07fe1"),
68-
"20.11.1-linux_ppc64le": ("node-v20.11.1-linux-ppc64le.tar.xz", "node-v20.11.1-linux-ppc64le", "51343cacf5cdf5c4b5e93e919d19dd373d6ef43d5f2c666eae299f26e31d08b5"),
69-
"20.11.1-linux_s390x": ("node-v20.11.1-linux-s390x.tar.xz", "node-v20.11.1-linux-s390x", "b32616b705cd0ddbb230b95c693e3d7a37becc2ced9bcadea8dc824cceed6be0"),
70-
"20.11.1-linux_amd64": ("node-v20.11.1-linux-x64.tar.xz", "node-v20.11.1-linux-x64", "d8dab549b09672b03356aa2257699f3de3b58c96e74eb26a8b495fbdc9cf6fbe"),
71-
"20.11.1-windows_amd64": ("node-v20.11.1-win-x64.zip", "node-v20.11.1-win-x64", "bc032628d77d206ffa7f133518a6225a9c5d6d9210ead30d67e294ff37044bda"),
62+
# Set the default nodejs toolchain to the latest supported major version
63+
64+
NODE_24_VERSION = "24.0.0"
65+
66+
NODE_24_REPO = {
67+
"24.0.0-darwin_arm64": ("node-v24.0.0-darwin-arm64.tar.gz", "node-v24.0.0-darwin-arm64", "194e2f3dd3ec8c2adcaa713ed40f44c5ca38467880e160974ceac1659be60121"),
68+
"24.0.0-darwin_amd64": ("node-v24.0.0-darwin-x64.tar.gz", "node-v24.0.0-darwin-x64", "f716b3ce14a7e37a6cbf97c9de10d444d7da07ef833cd8da81dd944d111e6a4a"),
69+
"24.0.0-linux_arm64": ("node-v24.0.0-linux-arm64.tar.xz", "node-v24.0.0-linux-arm64", "d40ec7ffe0b82b02dce94208c84351424099bd70fa3a42b65c46d95322305040"),
70+
"24.0.0-linux_ppc64le": ("node-v24.0.0-linux-ppc64le.tar.xz", "node-v24.0.0-linux-ppc64le", "cfa0e8d51a2f9a446f1bfb81cdf4c7e95336ad622e2aa230e3fa1d093c63d77d"),
71+
"24.0.0-linux_s390x": ("node-v24.0.0-linux-s390x.tar.xz", "node-v24.0.0-linux-s390x", "e37a04c7ee05416ec1234fd3255e05b6b81287eb0424a57441c8b69f0a155021"),
72+
"24.0.0-linux_amd64": ("node-v24.0.0-linux-x64.tar.xz", "node-v24.0.0-linux-x64", "59b8af617dccd7f9f68cc8451b2aee1e86d6bd5cb92cd51dd6216a31b707efd7"),
73+
"24.0.0-windows_amd64": ("node-v24.0.0-win-x64.zip", "node-v24.0.0-win-x64", "3d0fff80c87bb9a8d7f49f2f27832aa34a1477d137af46f5b14df5498be81304"),
7274
}
7375

74-
# Set the default nodejs toolchain to the latest supported major version
7576
nodejs_register_toolchains(
7677
name = "nodejs",
77-
# The below can be removed once @rules_nodejs/nodejs is updated to latest which contains https://github.com/bazelbuild/rules_nodejs/pull/3701
78-
node_repositories = NODE_20_REPO,
79-
node_version = DEFAULT_NODE_VERSION,
78+
node_repositories = NODE_24_REPO,
79+
node_version = NODE_24_VERSION,
8080
)
8181

8282
nodejs_register_toolchains(
8383
name = "node20",
84-
# The below can be removed once @rules_nodejs/nodejs is updated to latest which contains https://github.com/bazelbuild/rules_nodejs/pull/3701
85-
node_repositories = NODE_20_REPO,
86-
node_version = "20.11.1",
84+
node_repositories = {
85+
"20.19.0-darwin_arm64": ("node-v20.19.0-darwin-arm64.tar.gz", "node-v20.19.0-darwin-arm64", "c016cd1975a264a29dc1b07c6fbe60d5df0a0c2beb4113c0450e3d998d1a0d9c"),
86+
"20.19.0-darwin_amd64": ("node-v20.19.0-darwin-x64.tar.gz", "node-v20.19.0-darwin-x64", "a8554af97d6491fdbdabe63d3a1cfb9571228d25a3ad9aed2df856facb131b20"),
87+
"20.19.0-linux_arm64": ("node-v20.19.0-linux-arm64.tar.xz", "node-v20.19.0-linux-arm64", "dbe339e55eb393955a213e6b872066880bb9feceaa494f4d44c7aac205ec2ab9"),
88+
"20.19.0-linux_ppc64le": ("node-v20.19.0-linux-ppc64le.tar.xz", "node-v20.19.0-linux-ppc64le", "84937108f005679e60b486ed8e801cebfe923f02b76d8e710463d32f82181f65"),
89+
"20.19.0-linux_s390x": ("node-v20.19.0-linux-s390x.tar.xz", "node-v20.19.0-linux-s390x", "11f8ee99d792a83bba7b29911e0229dd6cd5e88987d7416346067db1cc76d89a"),
90+
"20.19.0-linux_amd64": ("node-v20.19.0-linux-x64.tar.xz", "node-v20.19.0-linux-x64", "b4e336584d62abefad31baecff7af167268be9bb7dd11f1297112e6eed3ca0d5"),
91+
"20.19.0-windows_amd64": ("node-v20.19.0-win-x64.zip", "node-v20.19.0-win-x64", "be72284c7bc62de07d5a9fd0ae196879842c085f11f7f2b60bf8864c0c9d6a4f"),
92+
},
93+
node_version = "20.19.0",
8794
)
8895

8996
nodejs_register_toolchains(
9097
name = "node22",
91-
# The below can be removed once @rules_nodejs/nodejs is updated to latest which contains https://github.com/bazelbuild/rules_nodejs/pull/3701
9298
node_repositories = {
93-
"22.11.0-darwin_arm64": ("node-v22.11.0-darwin-arm64.tar.gz", "node-v22.11.0-darwin-arm64", "2e89afe6f4e3aa6c7e21c560d8a0453d84807e97850bbb819b998531a22bdfde"),
94-
"22.11.0-darwin_amd64": ("node-v22.11.0-darwin-x64.tar.gz", "node-v22.11.0-darwin-x64", "668d30b9512137b5f5baeef6c1bb4c46efff9a761ba990a034fb6b28b9da2465"),
95-
"22.11.0-linux_arm64": ("node-v22.11.0-linux-arm64.tar.xz", "node-v22.11.0-linux-arm64", "6031d04b98f59ff0f7cb98566f65b115ecd893d3b7870821171708cdbaf7ae6e"),
96-
"22.11.0-linux_ppc64le": ("node-v22.11.0-linux-ppc64le.tar.xz", "node-v22.11.0-linux-ppc64le", "d1d49d7d611b104b6d616e18ac439479d8296aa20e3741432de0e85f4735a81e"),
97-
"22.11.0-linux_s390x": ("node-v22.11.0-linux-s390x.tar.xz", "node-v22.11.0-linux-s390x", "f474ed77d6b13d66d07589aee1c2b9175be4c1b165483e608ac1674643064a99"),
98-
"22.11.0-linux_amd64": ("node-v22.11.0-linux-x64.tar.xz", "node-v22.11.0-linux-x64", "83bf07dd343002a26211cf1fcd46a9d9534219aad42ee02847816940bf610a72"),
99-
"22.11.0-windows_amd64": ("node-v22.11.0-win-x64.zip", "node-v22.11.0-win-x64", "905373a059aecaf7f48c1ce10ffbd5334457ca00f678747f19db5ea7d256c236"),
99+
"22.12.0-darwin_arm64": ("node-v22.12.0-darwin-arm64.tar.gz", "node-v22.12.0-darwin-arm64", "293dcc6c2408da21562d135b0412525e381bb6fe150d688edb58fe850d0f3e13"),
100+
"22.12.0-darwin_amd64": ("node-v22.12.0-darwin-x64.tar.gz", "node-v22.12.0-darwin-x64", "52bc25dd026db7247c3c00439afdb83e95087248267f02d6c1a7250d1f896173"),
101+
"22.12.0-linux_arm64": ("node-v22.12.0-linux-arm64.tar.xz", "node-v22.12.0-linux-arm64", "8cfd5a8b9afae5a2e0bd86b0148ca31d2589c0ea669c2d0b11c132e35d90ed68"),
102+
"22.12.0-linux_ppc64le": ("node-v22.12.0-linux-ppc64le.tar.xz", "node-v22.12.0-linux-ppc64le", "199a606ba1ee86cce6d6b369c71f9d00873d2836a6662592afc3b6a5923e2004"),
103+
"22.12.0-linux_s390x": ("node-v22.12.0-linux-s390x.tar.xz", "node-v22.12.0-linux-s390x", "9b517f8006eb4b451d40c461cbe64f93c6455566dbe2613387ab02412bc06d35"),
104+
"22.12.0-linux_amd64": ("node-v22.12.0-linux-x64.tar.xz", "node-v22.12.0-linux-x64", "22982235e1b71fa8850f82edd09cdae7e3f32df1764a9ec298c72d25ef2c164f"),
105+
"22.12.0-windows_amd64": ("node-v22.12.0-win-x64.zip", "node-v22.12.0-win-x64", "2b8f2256382f97ad51e29ff71f702961af466c4616393f767455501e6aece9b8"),
100106
},
101-
node_version = "22.11.0",
107+
node_version = "22.12.0",
102108
)
103109

104110
nodejs_register_toolchains(
105111
name = "node24",
106-
node_repositories = {
107-
"24.0.0-darwin_arm64": ("node-v24.0.0-darwin-arm64.tar.gz", "node-v24.0.0-darwin-arm64", "194e2f3dd3ec8c2adcaa713ed40f44c5ca38467880e160974ceac1659be60121"),
108-
"24.0.0-darwin_amd64": ("node-v24.0.0-darwin-x64.tar.gz", "node-v24.0.0-darwin-x64", "f716b3ce14a7e37a6cbf97c9de10d444d7da07ef833cd8da81dd944d111e6a4a"),
109-
"24.0.0-linux_arm64": ("node-v24.0.0-linux-arm64.tar.xz", "node-v24.0.0-linux-arm64", "d40ec7ffe0b82b02dce94208c84351424099bd70fa3a42b65c46d95322305040"),
110-
"24.0.0-linux_ppc64le": ("node-v24.0.0-linux-ppc64le.tar.xz", "node-v24.0.0-linux-ppc64le", "cfa0e8d51a2f9a446f1bfb81cdf4c7e95336ad622e2aa230e3fa1d093c63d77d"),
111-
"24.0.0-linux_s390x": ("node-v24.0.0-linux-s390x.tar.xz", "node-v24.0.0-linux-s390x", "e37a04c7ee05416ec1234fd3255e05b6b81287eb0424a57441c8b69f0a155021"),
112-
"24.0.0-linux_amd64": ("node-v24.0.0-linux-x64.tar.xz", "node-v24.0.0-linux-x64", "59b8af617dccd7f9f68cc8451b2aee1e86d6bd5cb92cd51dd6216a31b707efd7"),
113-
"24.0.0-windows_amd64": ("node-v24.0.0-win-x64.zip", "node-v24.0.0-win-x64", "3d0fff80c87bb9a8d7f49f2f27832aa34a1477d137af46f5b14df5498be81304"),
114-
},
115-
node_version = "24.0.0",
112+
node_repositories = NODE_24_REPO,
113+
node_version = NODE_24_VERSION,
116114
)
117115

118116
load("@aspect_rules_js//js:toolchains.bzl", "rules_js_register_toolchains")
119117

120118
rules_js_register_toolchains(
121-
node_repositories = NODE_20_REPO,
122-
node_version = DEFAULT_NODE_VERSION,
119+
node_repositories = NODE_24_REPO,
120+
node_version = NODE_24_VERSION,
123121
)
124122

125123
http_archive(

constants.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Engine versions to stamp in a release package.json
2-
RELEASE_ENGINES_NODE = "^20.11.1 || ^22.11.0 || >=24.0.0"
2+
RELEASE_ENGINES_NODE = "^20.19.0 || ^22.12.0 || >=24.0.0"
33
RELEASE_ENGINES_NPM = "^6.11.0 || ^7.5.6 || >=8.0.0"
44
RELEASE_ENGINES_YARN = ">= 1.13.0"
55

docs/DEVELOPER.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ To get started locally, follow these instructions:
77
1. If you haven't done it already, [make a fork of this repo](https://github.com/angular/angular-cli/fork).
88
2. If you are on Windows, see [the extra steps needed for contributing on Windows](#windows)
99
3. Clone to your local computer using `git`.
10-
4. Make sure that you have Node `v20.18.1` or higher installed. See instructions [here](https://nodejs.org/en/download/).
10+
4. Make sure that you have Node `v20.19.0` or higher installed. See instructions [here](https://nodejs.org/en/download/).
1111
5. Install `pnpm`.
1212
- You can install pnpm by running `npm i -g pnpm@9`.
1313
- See detailed instructions [here](https://pnpm.io/installation).

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"packageManager": "pnpm@9.15.9",
3636
"engines": {
37-
"node": "^20.11.1 || >=22.11.0",
37+
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
3838
"npm": "Please use pnpm instead of NPM to install dependencies",
3939
"yarn": "Please use pnpm instead of Yarn to install dependencies",
4040
"pnpm": "^9.15.6"

packages/angular/build/src/utils/load-proxy-config.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ export async function loadProxyConfiguration(
5353
// Load the ESM configuration file using the TypeScript dynamic import workaround.
5454
// Once TypeScript provides support for keeping the dynamic import this workaround can be
5555
// changed to a direct dynamic import.
56-
proxyConfiguration = (await loadEsmModule<{ default: unknown }>(pathToFileURL(proxyPath)))
57-
.default;
56+
proxyConfiguration = await loadEsmModule<{ default: unknown }>(pathToFileURL(proxyPath));
5857
break;
5958
case '.cjs':
6059
proxyConfiguration = require(proxyPath);
@@ -71,15 +70,18 @@ export async function loadProxyConfiguration(
7170
// Load the ESM configuration file using the TypeScript dynamic import workaround.
7271
// Once TypeScript provides support for keeping the dynamic import this workaround can be
7372
// changed to a direct dynamic import.
74-
proxyConfiguration = (await loadEsmModule<{ default: unknown }>(pathToFileURL(proxyPath)))
75-
.default;
73+
proxyConfiguration = await loadEsmModule<{ default: unknown }>(pathToFileURL(proxyPath));
7674
break;
7775
}
7876

7977
throw e;
8078
}
8179
}
8280

81+
if ('default' in proxyConfiguration) {
82+
proxyConfiguration = proxyConfiguration.default;
83+
}
84+
8385
return normalizeProxyConfiguration(proxyConfiguration);
8486
}
8587

packages/angular/cli/lib/cli/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { writeErrorToLogFile } from '../../src/utilities/log-file';
1616

1717
export { VERSION } from '../../src/utilities/version';
1818

19-
const MIN_NODEJS_VERSION = [20, 11] as const;
19+
const MIN_NODEJS_VERSION = [20, 19] as const;
2020

2121
/* eslint-disable no-console */
2222
export default async function (options: { cliArgs: string[] }) {

packages/angular_devkit/architect/node/node-modules-architect-host.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,19 +310,22 @@ export function loadEsmModule<T>(modulePath: string | URL): Promise<T> {
310310

311311
// eslint-disable-next-line @typescript-eslint/no-explicit-any
312312
async function getBuilder(builderPath: string): Promise<any> {
313+
let builder;
313314
switch (path.extname(builderPath)) {
314315
case '.mjs':
315316
// Load the ESM configuration file using the TypeScript dynamic import workaround.
316317
// Once TypeScript provides support for keeping the dynamic import this workaround can be
317318
// changed to a direct dynamic import.
318-
return (await loadEsmModule<{ default: unknown }>(pathToFileURL(builderPath))).default;
319+
builder = (await loadEsmModule<{ default: unknown }>(pathToFileURL(builderPath))).default;
320+
break;
319321
case '.cjs':
320-
return localRequire(builderPath);
322+
builder = localRequire(builderPath);
323+
break;
321324
default:
322325
// The file could be either CommonJS or ESM.
323326
// CommonJS is tried first then ESM if loading fails.
324327
try {
325-
return localRequire(builderPath);
328+
builder = localRequire(builderPath);
326329
} catch (e) {
327330
if (
328331
(e as NodeJS.ErrnoException).code === 'ERR_REQUIRE_ESM' ||
@@ -331,10 +334,13 @@ async function getBuilder(builderPath: string): Promise<any> {
331334
// Load the ESM configuration file using the TypeScript dynamic import workaround.
332335
// Once TypeScript provides support for keeping the dynamic import this workaround can be
333336
// changed to a direct dynamic import.
334-
return (await loadEsmModule<{ default: unknown }>(pathToFileURL(builderPath))).default;
337+
builder = await loadEsmModule<{ default: unknown }>(pathToFileURL(builderPath));
335338
}
336339

337340
throw e;
338341
}
342+
break;
339343
}
344+
345+
return 'default' in builder ? builder.default : builder;
340346
}

packages/angular_devkit/build_angular/src/tools/webpack/configs/dev-server.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ async function addProxyConfig(
169169
throw new Error(`Proxy configuration file ${proxyPath} does not exist.`);
170170
}
171171

172-
let proxyConfiguration: Record<string, object> | object[];
172+
let proxyConfiguration;
173173

174174
switch (extname(proxyPath)) {
175175
case '.json': {
@@ -194,11 +194,9 @@ async function addProxyConfig(
194194
// Load the ESM configuration file using the TypeScript dynamic import workaround.
195195
// Once TypeScript provides support for keeping the dynamic import this workaround can be
196196
// changed to a direct dynamic import.
197-
proxyConfiguration = (
198-
await loadEsmModule<{ default: Record<string, object> | object[] }>(
199-
pathToFileURL(proxyPath),
200-
)
201-
).default;
197+
proxyConfiguration = await loadEsmModule<{ default: Record<string, object> | object[] }>(
198+
pathToFileURL(proxyPath),
199+
);
202200
break;
203201
case '.cjs':
204202
proxyConfiguration = require(proxyPath);
@@ -217,14 +215,16 @@ async function addProxyConfig(
217215
// Load the ESM configuration file using the TypeScript dynamic import workaround.
218216
// Once TypeScript provides support for keeping the dynamic import this workaround can be
219217
// changed to a direct dynamic import.
220-
proxyConfiguration = (
221-
await loadEsmModule<{ default: Record<string, object> | object[] }>(
222-
pathToFileURL(proxyPath),
223-
)
224-
).default;
218+
proxyConfiguration = await loadEsmModule<{ default: Record<string, object> | object[] }>(
219+
pathToFileURL(proxyPath),
220+
);
225221
}
226222
}
227223

224+
if ('default' in proxyConfiguration) {
225+
proxyConfiguration = proxyConfiguration.default;
226+
}
227+
228228
return normalizeProxyConfiguration(proxyConfiguration);
229229
}
230230

packages/angular_devkit/build_webpack/src/utils.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,23 @@ export async function getWebpackConfig(configPath: string): Promise<Configuratio
7676
throw new Error(`Webpack configuration file ${configPath} does not exist.`);
7777
}
7878

79+
let config;
7980
switch (path.extname(configPath)) {
8081
case '.mjs':
8182
// Load the ESM configuration file using the TypeScript dynamic import workaround.
8283
// Once TypeScript provides support for keeping the dynamic import this workaround can be
8384
// changed to a direct dynamic import.
84-
return (await loadEsmModule<{ default: Configuration }>(pathToFileURL(configPath))).default;
85+
config = await loadEsmModule<{ default: Configuration }>(pathToFileURL(configPath));
86+
break;
8587
case '.cjs':
86-
return require(configPath);
88+
config = require(configPath);
89+
break;
8790
default:
8891
// The file could be either CommonJS or ESM.
8992
// CommonJS is tried first then ESM if loading fails.
9093
try {
91-
return require(configPath);
94+
config = require(configPath);
95+
break;
9296
} catch (e) {
9397
if (
9498
(e as NodeJS.ErrnoException).code === 'ERR_REQUIRE_ESM' ||
@@ -97,11 +101,12 @@ export async function getWebpackConfig(configPath: string): Promise<Configuratio
97101
// Load the ESM configuration file using the TypeScript dynamic import workaround.
98102
// Once TypeScript provides support for keeping the dynamic import this workaround can be
99103
// changed to a direct dynamic import.
100-
return (await loadEsmModule<{ default: Configuration }>(pathToFileURL(configPath)))
101-
.default;
104+
config = await loadEsmModule<{ default: Configuration }>(pathToFileURL(configPath));
102105
}
103106

104107
throw e;
105108
}
106109
}
110+
111+
return 'default' in config ? config.default : config;
107112
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy