diff --git a/.circleci/config.yml b/.circleci/config.yml index d10266bda4..28d6a698a9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,14 +1,14 @@ version: 2.1 orbs: - browser-tools: circleci/browser-tools@1.4.1 + browser-tools: circleci/browser-tools@1.4.6 aliases: - &docker-node-image - - image: cimg/node:20.10 + - image: cimg/node:20.11 - &docker-node-browsers-image - - image: cimg/node:20.10-browsers + - image: cimg/node:20.11-browsers environment: CHROME_BIN: "/usr/bin/google-chrome" diff --git a/.nvmrc b/.nvmrc index fc0494728e..07533ba8b3 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20.10 +v20.11 diff --git a/package.json b/package.json index 4e2c181442..430c07e958 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@types/enzyme": "~3.10.18", "@types/enzyme-adapter-react-16": "~1.0.9", "@types/mocha": "~10.0.6", - "@types/node": "~20.10.7", + "@types/node": "~20.11.5", "@types/react": "~16.14.55", "@types/react-dom": "~16.9.24", "@types/react-transition-group": "~4.4.10", @@ -70,7 +70,7 @@ "@types/react": "16.14.55" }, "engines": { - "node": ">=20.10" + "node": ">=20.11" }, "repository": { "type": "git", diff --git a/packages/icons/scripts/common.mjs b/packages/icons/scripts/common.mjs index fbc14ba91e..f872e77888 100644 --- a/packages/icons/scripts/common.mjs +++ b/packages/icons/scripts/common.mjs @@ -17,11 +17,10 @@ import { writeFileSync } from "node:fs"; import { join, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; +import iconsMetadataJson from "../icons.json" with { type: "json" }; -export const scriptsDir = fileURLToPath(new URL(".", import.meta.url)); -export const iconResourcesDir = resolve(scriptsDir, "../../../resources/icons"); -export const generatedSrcDir = resolve(scriptsDir, "../src/generated"); +export const iconResourcesDir = resolve(import.meta.dirname, "../../../resources/icons"); +export const generatedSrcDir = resolve(import.meta.dirname, "../src/generated"); export const NS = "bp5"; /** @type { [16, 20] } */ export const ICON_SIZES = [16, 20]; @@ -46,18 +45,14 @@ export const ICON_RASTER_SCALING_FACTOR = 20; * @property {number} codepoint - icon font codepoint */ -const { default: iconsMetadataJson } = await import("../icons.json", { assert: { type: "json" }}); - /** @type {IconMetadata[]} */ -export const iconsMetadata = iconsMetadataJson.sort( - (a, b) => a.iconName.localeCompare(b.iconName), -); +export const iconsMetadata = iconsMetadataJson.sort((a, b) => a.iconName.localeCompare(b.iconName)); /** - * Writes lines to given filename in GENERATED_SRC_DIR. + * Writes lines to given filename in the generated sources directory. * * @param {string} filename - * @param {Array} lines + * @param {string[]} lines */ export function writeLinesToFile(filename, ...lines) { const outputPath = join(generatedSrcDir, filename); diff --git a/packages/icons/scripts/generate-icon-components.mjs b/packages/icons/scripts/generate-icon-components.mjs index e6aa5d23e5..3d34c9f59d 100644 --- a/packages/icons/scripts/generate-icon-components.mjs +++ b/packages/icons/scripts/generate-icon-components.mjs @@ -27,7 +27,7 @@ import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { join, resolve } from "node:path"; import { parse } from "svg-parser"; -import { generatedSrcDir, ICON_RASTER_SCALING_FACTOR, ICON_SIZES, scriptsDir } from "./common.mjs"; +import { generatedSrcDir, ICON_RASTER_SCALING_FACTOR, ICON_SIZES } from "./common.mjs"; Handlebars.registerHelper("pascalCase", iconName => pascalCase(iconName)); @@ -43,9 +43,13 @@ Handlebars.registerHelper("pascalCase", iconName => pascalCase(iconName)); * - https://github.com/facebook/react/pull/26130 * - https://github.com/palantir/blueprint/issues/6591 */ -const iconComponentTemplate = Handlebars.compile(readFileSync(resolve(scriptsDir, "iconComponent.tsx.hbs"), "utf8")); -const componentsIndexTemplate = Handlebars.compile(readFileSync(resolve(scriptsDir, "componentsIndex.ts.hbs"), "utf8")); -const indexTemplate = Handlebars.compile(readFileSync(resolve(scriptsDir, "index.ts.hbs"), "utf8")); +const iconComponentTemplate = Handlebars.compile( + readFileSync(resolve(import.meta.dirname, "iconComponent.tsx.hbs"), "utf8"), +); +const componentsIndexTemplate = Handlebars.compile( + readFileSync(resolve(import.meta.dirname, "componentsIndex.ts.hbs"), "utf8"), +); +const indexTemplate = Handlebars.compile(readFileSync(resolve(import.meta.dirname, "index.ts.hbs"), "utf8")); /** @type { { 16: {[iconName: string]: string}; 20: {[iconName: string]: string} } } */ const iconPaths = { diff --git a/packages/icons/scripts/generate-icon-fonts.mjs b/packages/icons/scripts/generate-icon-fonts.mjs index e21598957f..76fa9a992c 100644 --- a/packages/icons/scripts/generate-icon-fonts.mjs +++ b/packages/icons/scripts/generate-icon-fonts.mjs @@ -24,14 +24,7 @@ import { getLogger } from "@twbs/fantasticon/lib/cli/logger.js"; import { mkdirSync } from "node:fs"; import { join, resolve } from "node:path"; -import { - generatedSrcDir, - ICON_RASTER_SCALING_FACTOR, - iconResourcesDir, - iconsMetadata, - NS, - scriptsDir, -} from "./common.mjs"; +import { generatedSrcDir, ICON_RASTER_SCALING_FACTOR, iconResourcesDir, iconsMetadata, NS } from "./common.mjs"; const logger = getLogger(); @@ -71,8 +64,8 @@ async function generateFonts(size, prefix) { assetTypes: [OtherAssetType.CSS, OtherAssetType.SCSS, OtherAssetType.TS], templates: { // N.B. in icons-20, we don't generate CSS or the codepoints since we expect them to be the same as icons-16 - scss: resolve(scriptsDir, `./icons-${size}.scss.hbs`), - css: resolve(scriptsDir, "./icons.css.hbs"), + scss: resolve(import.meta.dirname, `icons-${size}.scss.hbs`), + css: resolve(import.meta.dirname, "icons.css.hbs"), }, pathOptions: { scss: join(generatedSrcDir, `${size}px`, "_icon-variables.scss"), diff --git a/packages/karma-build-scripts/createKarmaConfig.mjs b/packages/karma-build-scripts/createKarmaConfig.mjs index efc68604ed..ad1d59fc71 100644 --- a/packages/karma-build-scripts/createKarmaConfig.mjs +++ b/packages/karma-build-scripts/createKarmaConfig.mjs @@ -11,6 +11,8 @@ import { cwd, env } from "node:process"; import { karmaConfig as webpackConfig } from "@blueprintjs/webpack-build-scripts"; +// TODO: refactor to use `await import()`, requires breaking change to make this API async +// see https://nodejs.org/docs/latest-v20.x/api/esm.html#import-attributes const require = createRequire(import.meta.url); const coreManifest = require("../core/package.json"); diff --git a/packages/karma-build-scripts/package.json b/packages/karma-build-scripts/package.json index 0b4342d013..4fd46aeb14 100644 --- a/packages/karma-build-scripts/package.json +++ b/packages/karma-build-scripts/package.json @@ -23,6 +23,14 @@ "mocha": "^10.2.0", "webpack": "^5.89.0" }, + "peerDependencies": { + "@blueprintjs/core": "workspace:^" + }, + "peerDependenciesMeta": { + "@blueprintjs/core": { + "optional": true + } + }, "repository": { "type": "git", "url": "git@github.com:palantir/blueprint.git", diff --git a/packages/node-build-scripts/assert-package-layout.mjs b/packages/node-build-scripts/assert-package-layout.mjs index b1d305886d..43cf552192 100755 --- a/packages/node-build-scripts/assert-package-layout.mjs +++ b/packages/node-build-scripts/assert-package-layout.mjs @@ -16,7 +16,7 @@ import { cwd, exit } from "node:process"; // asserts that all main fields in package.json reference existing files const PACKAGE_MAIN_FIELDS = ["main", "module", "style", "types", "typings", "unpkg"]; -const { default: manifest } = await import(join(cwd(), "package.json"), { assert: { type: "json" }}); +const { default: manifest } = await import(join(cwd(), "package.json"), { with: { type: "json" } }); for (const field of PACKAGE_MAIN_FIELDS.filter(f => manifest[f] !== undefined)) { if (!existsSync(resolve(cwd(), manifest[field]))) { diff --git a/packages/node-build-scripts/package.json b/packages/node-build-scripts/package.json index 6ada3b1f9d..de59e74260 100644 --- a/packages/node-build-scripts/package.json +++ b/packages/node-build-scripts/package.json @@ -55,7 +55,7 @@ "jest": "^29.7.0" }, "engines": { - "node": ">=18.13" + "node": ">=20.11" }, "repository": { "type": "git", diff --git a/packages/node-build-scripts/src/__tests__/cssVariables.test.ts b/packages/node-build-scripts/src/__tests__/cssVariables.test.ts index 057574c7f1..c646af41d5 100644 --- a/packages/node-build-scripts/src/__tests__/cssVariables.test.ts +++ b/packages/node-build-scripts/src/__tests__/cssVariables.test.ts @@ -4,13 +4,11 @@ import { describe, expect, test } from "@jest/globals"; import { readFileSync } from "node:fs"; -import { dirname, join, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; +import { join, resolve } from "node:path"; import { generateLessVariables, generateScssVariables, getParsedVars } from "../cssVariables.mjs"; -const __dirname = dirname(fileURLToPath(import.meta.url)); -const FIXTURES_DIR = join(__dirname, "__fixtures__"); +const FIXTURES_DIR = join(import.meta.dirname, "__fixtures__"); const INPUT_DIR = resolve(FIXTURES_DIR, "input"); const EXPECTED_DIR = resolve(FIXTURES_DIR, "expected"); diff --git a/packages/node-build-scripts/src/utils.mjs b/packages/node-build-scripts/src/utils.mjs index ac42812e0d..350e56e145 100644 --- a/packages/node-build-scripts/src/utils.mjs +++ b/packages/node-build-scripts/src/utils.mjs @@ -18,7 +18,6 @@ import { basename, dirname, join, resolve } from "node:path"; import { cwd, env } from "node:process"; -import { fileURLToPath } from "node:url"; import { packageUpSync } from "package-up"; /** @@ -49,8 +48,7 @@ export function junitReportPath(dirName, fileName = basename(cwd())) { * @returns the root directory of this Blueprint monorepo */ export function getRootDir() { - const thisDirName = dirname(fileURLToPath(import.meta.url)); - const manifestFilePath = packageUpSync({ cwd: thisDirName }); + const manifestFilePath = packageUpSync({ cwd: import.meta.dirname }); if (manifestFilePath === undefined) { return undefined; } diff --git a/packages/stylelint-plugin/test/no-prefix-literal.test.mjs b/packages/stylelint-plugin/test/no-prefix-literal.test.mjs index 6b93d28617..6e8e1c00ad 100644 --- a/packages/stylelint-plugin/test/no-prefix-literal.test.mjs +++ b/packages/stylelint-plugin/test/no-prefix-literal.test.mjs @@ -13,10 +13,11 @@ * limitations under the License. */ +// @ts-check + import { expect } from "chai"; -import fs from "node:fs"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; +import { copyFileSync, mkdirSync, readFileSync, rmSync } from "node:fs"; +import { join } from "node:path"; import stylelint from "stylelint"; const config = { @@ -172,23 +173,22 @@ describe("no-prefix-literal", () => { }); describe("auto-fixer", () => { - const testDir = path.dirname(fileURLToPath(import.meta.url)); - const tmpDir = path.join(testDir, "tmp"); + const tmpDir = join(import.meta.dirname, "tmp"); before(() => { - fs.mkdirSync(tmpDir); + mkdirSync(tmpDir); }); after(() => { - fs.rmSync(tmpDir, { recursive: true, force: true }); + rmSync(tmpDir, { recursive: true, force: true }); }); it("Replaces selector text properly", async () => { const fixtureFilename = "contains-bp3.scss"; // path to the fixture we want to test - const fixturePath = path.join(testDir, "fixtures", "no-prefix-literal", fixtureFilename); + const fixturePath = join(import.meta.dirname, "fixtures", "no-prefix-literal", fixtureFilename); // path to a copy of the fixture which we can allow stylelint to mutate - const mutableFixturePath = path.join(tmpDir, fixtureFilename); - fs.copyFileSync(fixturePath, mutableFixturePath); + const mutableFixturePath = join(tmpDir, fixtureFilename); + copyFileSync(fixturePath, mutableFixturePath); const result = await stylelint.lint({ files: mutableFixturePath, @@ -200,7 +200,7 @@ describe("no-prefix-literal", () => { const warnings = result.results[0].warnings; expect(warnings).lengthOf(0); - const fixedSourceContents = fs.readFileSync(mutableFixturePath, { encoding: "utf-8" }); + const fixedSourceContents = readFileSync(mutableFixturePath, { encoding: "utf-8" }); expect(fixedSourceContents).to.contain(`@use "@blueprintjs/core/lib/scss/variables.scss" as bp;`); expect(fixedSourceContents).to.contain(".#{bp.$ns}-tag {"); }); diff --git a/packages/webpack-build-scripts/package.json b/packages/webpack-build-scripts/package.json index a6ea840dc5..84570c4241 100644 --- a/packages/webpack-build-scripts/package.json +++ b/packages/webpack-build-scripts/package.json @@ -39,6 +39,9 @@ "webpack-dev-server": "^4.15.1", "webpack-notifier": "^1.15.0" }, + "engines": { + "node": ">=20.11" + }, "repository": { "type": "git", "url": "git@github.com:palantir/blueprint.git", diff --git a/packages/webpack-build-scripts/utils.mjs b/packages/webpack-build-scripts/utils.mjs index 8036d8fd30..6407173623 100644 --- a/packages/webpack-build-scripts/utils.mjs +++ b/packages/webpack-build-scripts/utils.mjs @@ -2,18 +2,28 @@ * Copyright 2017 Palantir Technologies, Inc. All rights reserved. */ +// @ts-check + import { createRequire } from "node:module"; import { join } from "node:path"; import { cwd } from "node:process"; /** * Read a package name from package.json. + * + * @returns {string | undefined} */ export function getPackageName() { + // TODO: refactor to use `await import()`, requires breaking change to make this API async + // see https://nodejs.org/docs/latest-v20.x/api/esm.html#import-attributes const require = createRequire(import.meta.url); + /** @type {string | undefined} */ let name; try { name = require(join(cwd(), "package.json")).name; + if (name === undefined) { + throw new Error("package.json has no name field"); + } // strip NPM scope, if possible const nameSplit = name.split("/"); if (nameSplit.length > 1) { diff --git a/packages/webpack-build-scripts/webpack.config.base.mjs b/packages/webpack-build-scripts/webpack.config.base.mjs index b162c4aeea..08000e99ea 100644 --- a/packages/webpack-build-scripts/webpack.config.base.mjs +++ b/packages/webpack-build-scripts/webpack.config.base.mjs @@ -21,9 +21,9 @@ import cssnanoPlugin from "cssnano"; import ForkTsCheckerNotifierPlugin from "fork-ts-checker-notifier-webpack-plugin"; import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin"; import MiniCssExtractPlugin from "mini-css-extract-plugin"; -import { createRequire } from "node:module"; import { resolve } from "node:path"; import { cwd, env } from "node:process"; +import { fileURLToPath } from "node:url"; import TerserPlugin from "terser-webpack-plugin"; import webpack from "webpack"; import WebpackNotifierPlugin from "webpack-notifier"; @@ -32,10 +32,6 @@ import { sassNodeModulesLoadPaths } from "@blueprintjs/node-build-scripts"; import { getPackageName } from "./utils.mjs"; -// import.meta.resolve is still experimental under a CLI flag, so we create a require fn instead -// see https://nodejs.org/docs/latest-v18.x/api/esm.html#importmetaresolvespecifier-parent -const require = createRequire(import.meta.url); - // globals const IS_PRODUCTION = env.NODE_ENV === "production"; const DEV_PORT = env.PORT || 9001; @@ -90,16 +86,16 @@ const cssLoaders = [ ? { loader: MiniCssExtractPlugin.loader, } - : require.resolve("style-loader"), + : fileURLToPath(import.meta.resolve("style-loader")), { - loader: require.resolve("css-loader"), + loader: fileURLToPath(import.meta.resolve("css-loader")), options: { // necessary to minify @import-ed files using cssnano importLoaders: 1, }, }, { - loader: require.resolve("postcss-loader"), + loader: fileURLToPath(import.meta.resolve("postcss-loader")), options: { postcssOptions: { plugins: [autoprefixer, cssnanoPlugin({ preset: "default" })], @@ -112,7 +108,7 @@ const cssLoaders = [ const scssLoaders = [ ...cssLoaders, { - loader: require.resolve("sass-loader"), + loader: fileURLToPath(import.meta.resolve("sass-loader")), options: { sassOptions: { includePaths: sassNodeModulesLoadPaths, @@ -121,6 +117,9 @@ const scssLoaders = [ }, ]; +/** + * @type {webpack.Configuration & { devServer: object }} + */ export default { // to automatically find tsconfig.json context: cwd(), @@ -158,11 +157,11 @@ export default { rules: [ { test: /\.js$/, - use: require.resolve("source-map-loader"), + use: fileURLToPath(import.meta.resolve("source-map-loader")), }, { test: /\.tsx?$/, - loader: require.resolve("swc-loader"), + loader: fileURLToPath(import.meta.resolve("swc-loader")), exclude: /(node_modules)/, options: { jsc: { diff --git a/packages/webpack-build-scripts/webpack.config.karma.mjs b/packages/webpack-build-scripts/webpack.config.karma.mjs index 8c3e61819b..d29e911364 100644 --- a/packages/webpack-build-scripts/webpack.config.karma.mjs +++ b/packages/webpack-build-scripts/webpack.config.karma.mjs @@ -5,18 +5,16 @@ // @ts-check import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin"; -import { createRequire } from "node:module"; import { cwd } from "node:process"; +import { fileURLToPath } from "node:url"; import webpack from "webpack"; import { sassNodeModulesLoadPaths } from "@blueprintjs/node-build-scripts"; -// import.meta.resolve is still experimental under a CLI flag, so we create a require fn instead -// see https://nodejs.org/docs/latest-v18.x/api/esm.html#importmetaresolvespecifier-parent -const require = createRequire(import.meta.url); - /** * This differs significantly from the base webpack config, so we don't even end up extending from it. + * + * @type {webpack.Configuration} */ export default { bail: true, @@ -27,9 +25,9 @@ export default { resolve: { extensions: [".css", ".js", ".ts", ".tsx"], fallback: { - assert: require.resolve("assert/"), + assert: fileURLToPath(import.meta.resolve("assert/")), buffer: false, - stream: require.resolve("stream-browserify"), + stream: fileURLToPath(import.meta.resolve("stream-browserify")), }, }, @@ -37,11 +35,11 @@ export default { rules: [ { test: /\.js$/, - use: require.resolve("source-map-loader"), + use: fileURLToPath(import.meta.resolve("source-map-loader")), }, { test: /\.tsx?$/, - loader: require.resolve("swc-loader"), + loader: fileURLToPath(import.meta.resolve("swc-loader")), options: { jsc: { parser: { @@ -66,12 +64,15 @@ export default { }, { test: /\.css$/, - use: [require.resolve("style-loader"), require.resolve("css-loader")], + use: [ + fileURLToPath(import.meta.resolve("style-loader")), + fileURLToPath(import.meta.resolve("css-loader")), + ], }, { enforce: "post", test: /src\/.*\.tsx?$/, - loader: require.resolve("istanbul-instrumenter-loader"), + loader: fileURLToPath(import.meta.resolve("istanbul-instrumenter-loader")), options: { esModules: true, }, @@ -80,10 +81,10 @@ export default { // allow some custom styles to be written for tests (sometimes just for debugging purposes) test: /\.scss$/, use: [ - require.resolve("style-loader"), - require.resolve("css-loader"), + fileURLToPath(import.meta.resolve("style-loader")), + fileURLToPath(import.meta.resolve("css-loader")), { - loader: require.resolve("sass-loader"), + loader: fileURLToPath(import.meta.resolve("sass-loader")), options: { sassOptions: { includePaths: sassNodeModulesLoadPaths, diff --git a/scripts/get-publishable-paths-from-semver-tags.mjs b/scripts/get-publishable-paths-from-semver-tags.mjs index c4af5bf39d..c5c6af1472 100755 --- a/scripts/get-publishable-paths-from-semver-tags.mjs +++ b/scripts/get-publishable-paths-from-semver-tags.mjs @@ -14,6 +14,7 @@ import yargs from "yargs"; const cli = yargs(argv.slice(2)).usage("$0 ").help(); const args = await cli.argv; const commitish = args._[0] || "HEAD"; +const monorepoRootDir = join(import.meta.dirname, ".."); exec(`git tag --points-at ${commitish}`, async (err, stdout) => { if (err) { @@ -37,18 +38,18 @@ exec(`git tag --points-at ${commitish}`, async (err, stdout) => { }) .filter(name => name != null); - const taggedPackages = taggedPackageNames - .map(async name => { - const nameParts = name.split("/"); - const unscopedName = nameParts[nameParts.length - 1]; - const packagePath = join("packages", unscopedName); - // This will throw if the package name isn't also the path, which is desirable. - const { default: packageJson } = await import(join("..", packagePath, "package.json"), { assert: { type: "json" }}); - return { - packageJson, - path: packagePath, - }; - }); + const taggedPackages = taggedPackageNames.map(async name => { + const nameParts = name.split("/"); + const unscopedName = nameParts[nameParts.length - 1]; + const packagePath = join("packages", unscopedName); + const manifestPath = join(monorepoRootDir, packagePath, "package.json"); + // This will throw if the package name isn't also the path, which is desirable. + const { default: packageJson } = await import(manifestPath, { with: { type: "json" } }); + return { + packageJson, + path: packagePath, + }; + }); const publishablePackagePaths = (await Promise.all(taggedPackages)) .filter(({ packageJson }) => !packageJson.private) diff --git a/scripts/submit-comment-with-artifact-links.mjs b/scripts/submit-comment-with-artifact-links.mjs index f3c2280f5c..e1acc895f2 100644 --- a/scripts/submit-comment-with-artifact-links.mjs +++ b/scripts/submit-comment-with-artifact-links.mjs @@ -17,7 +17,7 @@ import { Octokit } from "octokit"; /** * @type {Array<{path: string; url: string;}>} */ -const { default: artifacts } = await import("./artifacts.json", { assert: { type: "json" }}); +const { default: artifacts } = await import("./artifacts.json", { with: { type: "json" } }); if (artifacts.items === undefined) { throw new Error( diff --git a/yarn.lock b/yarn.lock index a848ac1994..da650762a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -756,6 +756,11 @@ __metadata: karma-webpack: "npm:^5.0.0" mocha: "npm:^10.2.0" webpack: "npm:^5.89.0" + peerDependencies: + "@blueprintjs/core": "workspace:^" + peerDependenciesMeta: + "@blueprintjs/core": + optional: true languageName: unknown linkType: soft @@ -868,7 +873,7 @@ __metadata: "@types/enzyme": "npm:~3.10.18" "@types/enzyme-adapter-react-16": "npm:~1.0.9" "@types/mocha": "npm:~10.0.6" - "@types/node": "npm:~20.10.7" + "@types/node": "npm:~20.11.5" "@types/react": "npm:~16.14.55" "@types/react-dom": "npm:~16.9.24" "@types/react-transition-group": "npm:~4.4.10" @@ -2971,12 +2976,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>=10.0.0, @types/node@npm:~20.10.7": - version: 20.10.7 - resolution: "@types/node@npm:20.10.7" +"@types/node@npm:*, @types/node@npm:>=10.0.0, @types/node@npm:~20.11.5": + version: 20.11.5 + resolution: "@types/node@npm:20.11.5" dependencies: undici-types: "npm:~5.26.4" - checksum: d626cea1b7da4784ee7b335dcc54e64adba9725dab7ca51a690167de502ef89fec07b05ad8e25845d188d7ad7f72c192ec92964d456321ed5b9452113bf9351f + checksum: 6d18cec852f5cfbed3ec42b5c01c026e7a3f9da540d6e3d6738d4cee9979fb308cf27b6df7ba40a6553e7bc82e678f0ef53ba6e6ad52e5b86bd97b7783c2a42c languageName: node linkType: hard