From c409f7c1c5708f3a4c90307e61b9479717a876b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Zori=C4=87?= Date: Wed, 13 Nov 2024 16:06:25 +0100 Subject: [PATCH] feat: update packages script [skip ci] --- package.json | 1 + .../package.json | 2 +- scripts/updateBabelPackages.js | 117 ------------------ scripts/updatePackages.js | 12 ++ scripts/updatePackagesLib/BasicPackages.ts | 84 +++++++++++++ .../LatestVersionPackages.ts | 55 ++++++++ .../updatePackagesLib/ResolutionPackages.ts | 66 ++++++++++ scripts/updatePackagesLib/UpPackages.ts | 25 ++++ scripts/updatePackagesLib/createPreset.ts | 12 ++ scripts/updatePackagesLib/getUserInput.ts | 102 +++++++++++++++ scripts/updatePackagesLib/index.js | 15 +++ scripts/updatePackagesLib/presets/awsSdk.ts | 9 ++ scripts/updatePackagesLib/presets/babel.ts | 9 ++ scripts/updatePackagesLib/presets/index.ts | 5 + scripts/updatePackagesLib/presets/react.ts | 9 ++ scripts/updatePackagesLib/types.ts | 15 +++ scripts/updatePackagesLib/updatePackages.ts | 70 +++++++++++ yarn.lock | 43 ++++++- 18 files changed, 531 insertions(+), 120 deletions(-) delete mode 100644 scripts/updateBabelPackages.js create mode 100644 scripts/updatePackages.js create mode 100644 scripts/updatePackagesLib/BasicPackages.ts create mode 100644 scripts/updatePackagesLib/LatestVersionPackages.ts create mode 100644 scripts/updatePackagesLib/ResolutionPackages.ts create mode 100644 scripts/updatePackagesLib/UpPackages.ts create mode 100644 scripts/updatePackagesLib/createPreset.ts create mode 100644 scripts/updatePackagesLib/getUserInput.ts create mode 100644 scripts/updatePackagesLib/index.js create mode 100644 scripts/updatePackagesLib/presets/awsSdk.ts create mode 100644 scripts/updatePackagesLib/presets/babel.ts create mode 100644 scripts/updatePackagesLib/presets/index.ts create mode 100644 scripts/updatePackagesLib/presets/react.ts create mode 100644 scripts/updatePackagesLib/types.ts create mode 100644 scripts/updatePackagesLib/updatePackages.ts diff --git a/package.json b/package.json index cc5f7c3be23..6eccc7a300f 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ "semver": "^7.5.4", "ts-expect": "^1.3.0", "ts-jest": "^29.1.2", + "ts-node": "^10.9.1", "typescript": "4.9.5", "typescript-transform-paths": "^3.4.6", "verdaccio": "^5.29.1", diff --git a/packages/cli-plugin-scaffold-admin-app-module/package.json b/packages/cli-plugin-scaffold-admin-app-module/package.json index 10a797b79b3..c9ad7d2a63b 100644 --- a/packages/cli-plugin-scaffold-admin-app-module/package.json +++ b/packages/cli-plugin-scaffold-admin-app-module/package.json @@ -28,7 +28,7 @@ "terminal-link": "^2.1.1" }, "devDependencies": { - "@types/inquirer": "8.2.10", + "@types/inquirer": "^8.2.10", "@types/ncp": "^2.0.4", "@types/pluralize": "^0.0.29", "@webiny/plugins": "0.0.0", diff --git a/scripts/updateBabelPackages.js b/scripts/updateBabelPackages.js deleted file mode 100644 index 53fedccc485..00000000000 --- a/scripts/updateBabelPackages.js +++ /dev/null @@ -1,117 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const semver = require("semver"); -const execa = require("execa"); -const loadJsonFile = require("load-json-file"); -const writeJsonFile = require("write-json-file"); -const { allWorkspaces } = require("../packages/project-utils/workspaces"); - -const types = ["dependencies", "devDependencies", "peerDependencies"]; -const findPackages = (collection, json, matching) => { - return types.reduce((packages, type) => { - const deps = json[type]; - if (!deps) { - return packages; - } - for (const pkg in deps) { - if (pkg.match(matching) === null) { - continue; - } else if (!packages[pkg]) { - packages[pkg] = { - version: semver.coerce(deps[pkg]), - latest: null - }; - continue; - } - const version = semver.coerce(deps[pkg]); - const existing = packages[pkg].version; - if (!semver.gt(existing.raw, version.raw)) { - continue; - } - packages[pkg] = { - version: version, - latest: null - }; - } - - return packages; - }, collection); -}; - -const updateBabelPackages = async () => { - const packages = allWorkspaces().map(pkg => { - return path.resolve(process.cwd(), pkg); - }); - - packages.push(path.resolve(process.cwd())); - - const babelPackages = packages.reduce((collection, pkg) => { - const target = path.resolve(pkg, "package.json"); - if (!fs.existsSync(target)) { - console.log(`File not found: ${target}`); - return collection; - } - const json = loadJsonFile.sync(target); - collection = findPackages(collection, json, /^@babel\//); - return collection; - }, {}); - - for (const pkg in babelPackages) { - try { - const result = await execa("npm", ["show", pkg, "version"]); - if (!result.stdout) { - continue; - } - const version = semver.coerce(result.stdout); - babelPackages[pkg].latest = version; - if (semver.gt(version.raw, babelPackages[pkg].version.raw) === false) { - continue; - } - babelPackages[pkg].updateToLatest = true; - } catch (ex) { - console.error(`Could not find "${pkg}" latest version on npm.`, ex); - } - } - - /** - * Is the babel package in root package.json devDependencies? - */ - const rootPackageJsonPath = path.resolve(process.cwd(), "package.json"); - const rootPackageJson = loadJsonFile.sync(rootPackageJsonPath); - const addedToResolutions = []; - for (const pkg in babelPackages) { - if (!rootPackageJson.resolutions[pkg]) { - rootPackageJson.resolutions[pkg] = `^${babelPackages[pkg].latest.raw}`; - addedToResolutions.push(pkg); - } - if (rootPackageJson.devDependencies[pkg]) { - continue; - } - rootPackageJson.devDependencies[pkg] = `^${babelPackages[pkg].latest.raw}`; - } - writeJsonFile.sync(rootPackageJsonPath, rootPackageJson); - await execa("yarn"); - - for (const pkg in babelPackages) { - const target = babelPackages[pkg]; - if (!target.updateToLatest) { - console.log(`"${pkg}" is already up-to-date (${target.version.raw}).`); - continue; - } - await execa("yarn", ["up", `${pkg}@^${target.latest.raw}`]); - console.log(`"${pkg}" updated from "${target.version.raw}" to ${target.latest.raw}.`); - } - /** - * Remove from resolutions. - */ - if (addedToResolutions.length === 0) { - return; - } - const rootPackageJsonUp = loadJsonFile.sync(rootPackageJsonPath); - for (const pkg of addedToResolutions) { - delete rootPackageJsonUp.resolutions[pkg]; - } - writeJsonFile.sync(rootPackageJsonPath, rootPackageJsonUp); -}; - -updateBabelPackages(); diff --git a/scripts/updatePackages.js b/scripts/updatePackages.js new file mode 100644 index 00000000000..de2e1021505 --- /dev/null +++ b/scripts/updatePackages.js @@ -0,0 +1,12 @@ +const { updatePackages, presets, getUserInput } = require("./updatePackagesLib/index"); + +(async () => { + const input = await getUserInput({ + presets + }); + if (!input) { + return; + } + + return updatePackages(input); +})(); diff --git a/scripts/updatePackagesLib/BasicPackages.ts b/scripts/updatePackagesLib/BasicPackages.ts new file mode 100644 index 00000000000..b1f39498c21 --- /dev/null +++ b/scripts/updatePackagesLib/BasicPackages.ts @@ -0,0 +1,84 @@ +import loadJsonFile from "load-json-file"; +import { IBasicPackage, IPackageJson } from "./types"; +import path from "path"; +import fs from "fs"; +import semver from "semver"; + +export interface IBasicPackageParams { + packages: string[]; + matching: RegExp; +} + +interface IFindPackagesParams { + collection: IBasicPackage[]; + json: IPackageJson; + matching: RegExp; +} + +const types = ["dependencies", "devDependencies", "peerDependencies"] as const; + +export class BasicPackages { + public readonly packages: IBasicPackage[]; + + private constructor(packages: IBasicPackage[]) { + this.packages = packages; + } + + public static async create(params: IBasicPackageParams): Promise { + const { packages, matching } = params; + const results = packages.reduce((collection, pkg) => { + const target = path.resolve(pkg, "package.json"); + if (!fs.existsSync(target)) { + console.log(`File not found: ${target}`); + return collection; + } + const json = loadJsonFile.sync(target); + return BasicPackages.findPackages({ + collection, + json, + matching + }); + }, []); + + return new BasicPackages(results); + } + + private static findPackages(params: IFindPackagesParams): IBasicPackage[] { + const { collection, json, matching } = params; + return types.reduce((packages, type) => { + const deps = json[type]; + if (!deps) { + return packages; + } + for (const name in deps) { + if (name.match(matching) === null) { + continue; + } + const existing = packages.find(p => p.name === name); + if (!existing) { + const version = semver.coerce(deps[name]); + if (!version) { + console.warn(`Could not coerce version "${deps[name]}" for ${name}`); + continue; + } + packages.push({ + name, + version + }); + + continue; + } + const version = semver.coerce(deps[name]); + if (!version) { + continue; + } + if (!semver.gt(existing.version, version)) { + continue; + } + existing.version = version; + } + + return packages; + }, Array.from(collection)); + } +} diff --git a/scripts/updatePackagesLib/LatestVersionPackages.ts b/scripts/updatePackagesLib/LatestVersionPackages.ts new file mode 100644 index 00000000000..f73e550e3a3 --- /dev/null +++ b/scripts/updatePackagesLib/LatestVersionPackages.ts @@ -0,0 +1,55 @@ +import execa from "execa"; +import semver from "semver"; +import { IBasicPackage, IVersionedPackage } from "./types"; + +export interface IGetUpdatableParams { + packages: IBasicPackage[]; +} + +export class LatestVersionPackages { + private readonly cache: WeakMap = new WeakMap(); + + public async getUpdatable(params: IGetUpdatableParams): Promise { + const cache = this.cache.get(params.packages); + if (cache) { + return cache; + } + + const results: IVersionedPackage[] = []; + + for (const localPackage of params.packages) { + try { + const result = await execa("npm", ["show", localPackage.name, "version"]); + if (!result.stdout) { + console.log(`Could not find "${localPackage.name}" latest version on npm.`); + continue; + } + const npmPackageVersion = semver.coerce(result.stdout); + if (!npmPackageVersion) { + console.log( + `Could not coerce "${localPackage.name}" latest version "${result.stdout}" from npm.` + ); + continue; + } + if (semver.gte(localPackage.version, npmPackageVersion)) { + continue; + } + + results.push({ + ...localPackage, + version: localPackage.version, + latestVersion: npmPackageVersion + }); + } catch (ex) { + console.error(`Could not find "${localPackage}" latest version on npm.`, ex); + } + } + + this.cache.set(params.packages, results); + return results; + } + + public static async create() { + return new LatestVersionPackages(); + } +} diff --git a/scripts/updatePackagesLib/ResolutionPackages.ts b/scripts/updatePackagesLib/ResolutionPackages.ts new file mode 100644 index 00000000000..2f17089ba5a --- /dev/null +++ b/scripts/updatePackagesLib/ResolutionPackages.ts @@ -0,0 +1,66 @@ +import { IPackageJson, IVersionedPackage } from "./types"; +import loadJsonFile from "load-json-file"; +import writeJsonFile from "write-json-file"; +import execa from "execa"; + +export interface IResolutionPackagesParams { + packages: IVersionedPackage[]; + path: string; + skip: boolean; +} + +export class ResolutionPackages { + private readonly skip: boolean; + private readonly packages: IVersionedPackage[]; + private readonly path: string; + private addedToResolutions: IVersionedPackage[] | undefined; + + private constructor(params: IResolutionPackagesParams) { + this.skip = params.skip; + this.path = params.path; + this.packages = params.packages; + } + + public static async create(params: IResolutionPackagesParams): Promise { + return new ResolutionPackages(params); + } + + public async addToPackageJson(): Promise { + if (this.skip) { + return; + } else if (this.addedToResolutions) { + throw new Error(`Cannot execute addToPackageJson() twice.`); + } + this.addedToResolutions = []; + const rootPackageJson = loadJsonFile.sync(this.path); + for (const pkg of this.packages) { + if (!rootPackageJson.resolutions[pkg.name]) { + rootPackageJson.resolutions[pkg.name] = `^${pkg.latestVersion.raw}`; + this.addedToResolutions.push(pkg); + } + if (!rootPackageJson.devDependencies) { + rootPackageJson.devDependencies = {}; + } + if (rootPackageJson.devDependencies[pkg.name]) { + continue; + } + rootPackageJson.devDependencies[pkg.name] = `^${pkg.latestVersion.raw}`; + } + writeJsonFile.sync(this.path, rootPackageJson); + await execa("yarn"); + } + + public async removeFromPackageJson(): Promise { + if (this.skip || !this.addedToResolutions?.length) { + return; + } + const rootPackageJsonUp = loadJsonFile.sync(this.path); + if (!rootPackageJsonUp.resolutions) { + return; + } + for (const pkg of this.packages) { + delete rootPackageJsonUp.resolutions[pkg.name]; + } + writeJsonFile.sync(this.path, rootPackageJsonUp); + } +} diff --git a/scripts/updatePackagesLib/UpPackages.ts b/scripts/updatePackagesLib/UpPackages.ts new file mode 100644 index 00000000000..471022d6eaf --- /dev/null +++ b/scripts/updatePackagesLib/UpPackages.ts @@ -0,0 +1,25 @@ +import { IVersionedPackage } from "./types"; +import execa from "execa"; + +export interface IUpPackagesParams { + packages: IVersionedPackage[]; +} + +export class UpPackages { + private readonly packages: IVersionedPackage[]; + + private constructor(params: IUpPackagesParams) { + this.packages = params.packages; + } + + public static async create(params: IUpPackagesParams): Promise { + return new UpPackages(params); + } + + public async process(): Promise { + for (const pkg of this.packages) { + await execa("yarn", ["up", `${pkg}@^${pkg.latestVersion.raw}`]); + console.log(`${pkg}: ${pkg.version.raw} -> ${pkg.latestVersion.raw}`); + } + } +} diff --git a/scripts/updatePackagesLib/createPreset.ts b/scripts/updatePackagesLib/createPreset.ts new file mode 100644 index 00000000000..31f645dda38 --- /dev/null +++ b/scripts/updatePackagesLib/createPreset.ts @@ -0,0 +1,12 @@ +export interface IPreset { + name: string; + matching: RegExp; + skipResolutions: boolean; +} +export interface ICreatePresetCb { + (): IPreset; +} + +export const createPreset = (cb: ICreatePresetCb) => { + return cb(); +}; diff --git a/scripts/updatePackagesLib/getUserInput.ts b/scripts/updatePackagesLib/getUserInput.ts new file mode 100644 index 00000000000..2862ee0c2bb --- /dev/null +++ b/scripts/updatePackagesLib/getUserInput.ts @@ -0,0 +1,102 @@ +import { IPreset } from "./createPreset"; +import inquirer from "inquirer"; + +export interface IGetUserInputParams { + presets: IPreset[]; +} + +export interface IUserInputParams { + dryRun: boolean; + skipResolutions: boolean; + matching: RegExp; +} + +export const getUserInput = async ({ + presets +}: IGetUserInputParams): Promise => { + const prompt = inquirer.createPromptModule(); + + const { dryRun } = await prompt({ + name: "dryRun", + type: "confirm", + default: true, + message: "First, is this a dry run?" + }); + + const { preset } = await prompt({ + name: "preset", + message: "Do you want to use a preset?", + default: null, + type: "list", + choices: [ + { name: "I will write my own custom matching", value: null }, + + ...presets.map(p => { + return { + name: p.name, + value: p.name + }; + }) + ] + }); + if (preset) { + const matching = presets.find(p => p.name === preset); + if (!matching) { + throw new Error(`Preset not found: ${preset}`); + } + return { + ...matching, + dryRun + }; + } + + const { matching } = await prompt({ + name: "matching", + type: "input", + message: "Enter a regex to match package names.", + validate(input: string) { + try { + if (!input || input.length < 3) { + return "Please enter a regex."; + } + new RegExp(input); + return true; + } catch (e) { + return `Invalid regex: ${input}`; + } + } + }); + + const { skipResolutions } = await prompt({ + name: "skipResolutions", + type: "list", + default: null, + message: "Skip adding packages to main package.json resolutions?", + choices: [ + { name: "No", value: false }, + { name: "Yes", value: true } + ] + }); + + const { confirm } = await prompt({ + name: "confirm", + default: false, + type: "list", + message: `Confirm settings: matching - ${matching}, dry run - ${ + dryRun ? "yes" : "no" + }, skip resolutions - ${skipResolutions ? "yes" : "no"})`, + choices: [ + { name: "Not correct, exit.", value: false }, + { name: "Correct, continue.", value: true } + ] + }); + if (!confirm) { + return null; + } + + return { + matching, + dryRun, + skipResolutions + }; +}; diff --git a/scripts/updatePackagesLib/index.js b/scripts/updatePackagesLib/index.js new file mode 100644 index 00000000000..0127eabe1f7 --- /dev/null +++ b/scripts/updatePackagesLib/index.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node +process.env.NODE_PATH = process.cwd(); +require("ts-node").register({ + dir: __dirname +}); + +const { presets } = require("./presets"); +const { updatePackages } = require("./updatePackages"); +const { getUserInput } = require("./getUserInput"); + +module.exports = { + updatePackages, + getUserInput, + presets +}; diff --git a/scripts/updatePackagesLib/presets/awsSdk.ts b/scripts/updatePackagesLib/presets/awsSdk.ts new file mode 100644 index 00000000000..3f8904a6a2d --- /dev/null +++ b/scripts/updatePackagesLib/presets/awsSdk.ts @@ -0,0 +1,9 @@ +import { createPreset } from "../createPreset"; + +export const awsSdk = createPreset(() => { + return { + name: "aws-sdk", + matching: /^@aws-sdk\//, + skipResolutions: true + }; +}); diff --git a/scripts/updatePackagesLib/presets/babel.ts b/scripts/updatePackagesLib/presets/babel.ts new file mode 100644 index 00000000000..5181c119a42 --- /dev/null +++ b/scripts/updatePackagesLib/presets/babel.ts @@ -0,0 +1,9 @@ +import { createPreset } from "../createPreset"; + +export const babel = createPreset(() => { + return { + name: "babel", + matching: /^@babel\//, + skipResolutions: false + }; +}); diff --git a/scripts/updatePackagesLib/presets/index.ts b/scripts/updatePackagesLib/presets/index.ts new file mode 100644 index 00000000000..d661cef61f4 --- /dev/null +++ b/scripts/updatePackagesLib/presets/index.ts @@ -0,0 +1,5 @@ +import { react } from "./react"; +import { babel } from "./babel"; +import { awsSdk } from "./awsSdk"; + +export const presets = [react, babel, awsSdk]; diff --git a/scripts/updatePackagesLib/presets/react.ts b/scripts/updatePackagesLib/presets/react.ts new file mode 100644 index 00000000000..600601d252d --- /dev/null +++ b/scripts/updatePackagesLib/presets/react.ts @@ -0,0 +1,9 @@ +import { createPreset } from "../createPreset"; + +export const react = createPreset(() => { + return { + name: "react", + matching: /^react$|^react-dom$|^@types\/react$|^@types\/react-dom$/, + skipResolutions: false + }; +}); diff --git a/scripts/updatePackagesLib/types.ts b/scripts/updatePackagesLib/types.ts new file mode 100644 index 00000000000..118501faed1 --- /dev/null +++ b/scripts/updatePackagesLib/types.ts @@ -0,0 +1,15 @@ +import { PackageJson as BasePackageJson } from "type-fest"; +import { SemVer } from "semver"; + +export interface IBasicPackage { + name: string; + version: SemVer; +} + +export interface IVersionedPackage extends IBasicPackage { + latestVersion: SemVer; +} + +export interface IPackageJson extends BasePackageJson { + resolutions: Record; +} diff --git a/scripts/updatePackagesLib/updatePackages.ts b/scripts/updatePackagesLib/updatePackages.ts new file mode 100644 index 00000000000..546488f6b5c --- /dev/null +++ b/scripts/updatePackagesLib/updatePackages.ts @@ -0,0 +1,70 @@ +import path from "path"; +import { allWorkspaces } from "../../packages/project-utils/workspaces"; +import { BasicPackages } from "./BasicPackages"; +import { LatestVersionPackages } from "./LatestVersionPackages"; +import { ResolutionPackages } from "./ResolutionPackages"; +import { UpPackages } from "./UpPackages"; + +const getAllPackages = (): string[] => { + const workspaces = allWorkspaces() as string[]; + const packages = workspaces.map(pkg => { + return path.resolve(process.cwd(), pkg); + }); + + packages.push(path.resolve(process.cwd())); + + return packages; +}; + +interface IUpdatePackagesParams { + dryRun: boolean; + skipResolutions: boolean; + matching: RegExp; +} + +export const updatePackages = async (params: IUpdatePackagesParams) => { + const { matching, skipResolutions, dryRun } = params; + /** + * Basic packages container with all packages that match the regex and their versions in the package.json files. + */ + const packages = await BasicPackages.create({ + packages: getAllPackages(), + matching + }); + /** + * Versioned packages container. + * All packages with latest versions + */ + const latestVersionPackages = await LatestVersionPackages.create(); + + const updatable = await latestVersionPackages.getUpdatable({ + packages: packages.packages + }); + if (updatable.length === 0) { + console.log("All packages are up-to-date. Exiting..."); + return; + } + if (dryRun !== false) { + console.log("Dry run mode enabled. Packages which will get updated:"); + for (const pkg of updatable) { + console.log(`${pkg.name}: ${pkg.version.raw} -> ${pkg.latestVersion.raw}`); + } + return; + } + + const resolutions = await ResolutionPackages.create({ + skip: skipResolutions, + path: path.resolve(process.cwd(), "package.json"), + packages: updatable + }); + + await resolutions.addToPackageJson(); + + const updatePackages = await UpPackages.create({ + packages: updatable + }); + + await updatePackages.process(); + + await resolutions.removeFromPackageJson(); +}; diff --git a/yarn.lock b/yarn.lock index 8da08f99a6e..b8ce65e37dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10622,7 +10622,7 @@ __metadata: languageName: node linkType: hard -"@types/inquirer@npm:8.2.10": +"@types/inquirer@npm:8.2.10, @types/inquirer@npm:^8.2.10": version: 8.2.10 resolution: "@types/inquirer@npm:8.2.10" dependencies: @@ -14899,7 +14899,7 @@ __metadata: version: 0.0.0-use.local resolution: "@webiny/cli-plugin-scaffold-admin-app-module@workspace:packages/cli-plugin-scaffold-admin-app-module" dependencies: - "@types/inquirer": 8.2.10 + "@types/inquirer": ^8.2.10 "@types/ncp": ^2.0.4 "@types/pluralize": ^0.0.29 "@webiny/cli": 0.0.0 @@ -34778,6 +34778,7 @@ __metadata: semver: ^7.5.4 ts-expect: ^1.3.0 ts-jest: ^29.1.2 + ts-node: ^10.9.1 typescript: 4.9.5 typescript-transform-paths: ^3.4.6 verdaccio: ^5.29.1 @@ -37223,6 +37224,44 @@ __metadata: languageName: node linkType: hard +"ts-node@npm:^10.9.1": + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" + dependencies: + "@cspotcode/source-map-support": ^0.8.0 + "@tsconfig/node10": ^1.0.7 + "@tsconfig/node12": ^1.0.7 + "@tsconfig/node14": ^1.0.0 + "@tsconfig/node16": ^1.0.2 + acorn: ^8.4.1 + acorn-walk: ^8.1.1 + arg: ^4.1.0 + create-require: ^1.1.0 + diff: ^4.0.1 + make-error: ^1.1.1 + v8-compile-cache-lib: ^3.0.1 + yn: 3.1.1 + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + bin: + ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: fde256c9073969e234526e2cfead42591b9a2aec5222bac154b0de2fa9e4ceb30efcd717ee8bc785a56f3a119bdd5aa27b333d9dbec94ed254bd26f8944c67ac + languageName: node + linkType: hard + "ts-toolbelt@npm:^9.6.0": version: 9.6.0 resolution: "ts-toolbelt@npm:9.6.0"