From 291839f53b7bed451e0d99de637f2d8168e972f8 Mon Sep 17 00:00:00 2001 From: Floyd Kim Date: Thu, 3 Sep 2026 14:05:55 +0900 Subject: [PATCH 1/5] feat: load TypeScript config files with tsx instead of ts-node tsx compiles the TypeScript config file and the project files it imports, and resolves tsconfig `paths` aliases from the tsconfig.json nearest to the working directory. It ships as a regular dependency, so a project needs no setup for a `.ts` config file. Compared with ts-node: hooks listed in the tsconfig `ts-node.require` field no longer run, aliases defined only in babel.config.js (babel-plugin-module-resolver) are not resolved, and type errors in the config file no longer stop the CLI. --- cli/package.json | 9 +- cli/utils/fsUtils.ts | 19 +- package-lock.json | 531 ++++++++++++++++++++++++++++++++++++++++--- package.json | 1 + 4 files changed, 513 insertions(+), 47 deletions(-) diff --git a/cli/package.json b/cli/package.json index 60ada8202..eca1fa6a0 100644 --- a/cli/package.json +++ b/cli/package.json @@ -14,18 +14,11 @@ "commander": "^12.1.0", "semver": "^7.3.5", "shelljs": "^0.10.0", + "tsx": "^4.23.13", "xcode": "^3.0.1", "yazl": "^3.3.1", "yauzl": "^3.2.0" }, - "peerDependencies": { - "ts-node": ">=10" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - }, "engines": { "node": ">=18" }, diff --git a/cli/utils/fsUtils.ts b/cli/utils/fsUtils.ts index e31d1e96a..c919aa6ad 100644 --- a/cli/utils/fsUtils.ts +++ b/cli/utils/fsUtils.ts @@ -1,10 +1,9 @@ import fs from "fs"; import path from "path"; import { createRequire } from "module"; +import { require as tsxRequire } from "tsx/cjs/api"; import type { CliConfigInterface } from "../../typings/react-native-code-push.d.ts"; -const nodeRequire = createRequire(import.meta.url); - /** * allows to require a config file with .ts extension */ @@ -12,19 +11,21 @@ function requireConfig(filePath: string): CliConfigInterface { const ext = path.extname(filePath); if (ext === '.ts') { - try { - nodeRequire('ts-node/register'); - } catch { - console.error('ts-node not found. Please install ts-node as a devDependency.'); - process.exit(1); - } + // tsx compiles the file and the project files it imports, resolving tsconfig `paths` aliases + // from the tsconfig.json nearest to the working directory, which is the project root when the CLI runs. + return unwrapDefaultExport(tsxRequire(filePath, filePath)); } else if (ext === '.js') { // do nothing } else { throw new Error(`Unsupported file extension: ${ext}`); } - return nodeRequire(filePath) as CliConfigInterface; + return unwrapDefaultExport(createRequire(filePath)(filePath)); +} + +// `export default` compiles to `exports.default`; `module.exports =` is returned as is. +function unwrapDefaultExport(loaded: { default?: unknown }): CliConfigInterface { + return (loaded.default ?? loaded) as CliConfigInterface; } export function findAndReadConfigFile(startDir: string, configFileName: string): CliConfigInterface { diff --git a/package-lock.json b/package-lock.json index 7984363e3..8f03f7948 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "hoist-non-react-statics": "^3.3.2", "semver": "^7.3.5", "shelljs": "^0.10.0", + "tsx": "^4.23.13", "xcode": "^3.0.1", "yauzl": "^3.2.0", "yazl": "^3.3.1" @@ -66,6 +67,7 @@ "commander": "^12.1.0", "semver": "^7.3.5", "shelljs": "^0.10.0", + "tsx": "^4.23.13", "xcode": "^3.0.1", "yauzl": "^3.2.0", "yazl": "^3.3.1" @@ -77,14 +79,6 @@ }, "engines": { "node": ">=18" - }, - "peerDependencies": { - "ts-node": ">=10" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } } }, "code-push-plugin-testing-framework": { @@ -1791,7 +1785,7 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -1802,13 +1796,429 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "dev": true, @@ -2403,7 +2813,7 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2422,7 +2832,7 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -2651,22 +3061,22 @@ }, "node_modules/@tsconfig/node10": { "version": "1.0.11", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@types/babel__core": { @@ -2816,7 +3226,7 @@ "version": "18.19.129", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.129.tgz", "integrity": "sha512-hrmi5jWt2w60ayox3iIXwpMEnfUvOLJCRtrOPbHtH15nTjvO7uhnelvrdAs0dO0/zl5DZ3ZbahiaXEVb54ca/A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -3164,7 +3574,7 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3183,7 +3593,7 @@ }, "node_modules/acorn-walk": { "version": "8.3.2", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -3270,7 +3680,7 @@ }, "node_modules/arg": { "version": "4.1.3", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/argparse": { @@ -4113,7 +4523,7 @@ }, "node_modules/create-require": { "version": "1.1.1", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { @@ -4509,6 +4919,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, "node_modules/escalade": { "version": "3.2.0", "dev": true, @@ -5162,8 +5613,10 @@ "license": "ISC" }, "node_modules/fsevents": { - "version": "2.3.2", - "dev": true, + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ @@ -6841,7 +7294,7 @@ }, "node_modules/make-error": { "version": "1.3.6", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/makeerror": { @@ -8949,7 +9402,7 @@ }, "node_modules/ts-node": { "version": "10.9.2", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -8991,12 +9444,30 @@ }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", - "devOptional": true, + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, + "node_modules/tsx": { + "version": "4.23.13", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz", + "integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/type-detect": { "version": "4.0.8", "dev": true, @@ -9101,7 +9572,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "devOptional": true, + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9150,7 +9621,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -9253,7 +9724,7 @@ }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/v8-to-istanbul": { @@ -9571,7 +10042,7 @@ }, "node_modules/yn": { "version": "3.1.1", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" diff --git a/package.json b/package.json index 8d577c3c1..c79e0f80e 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "hoist-non-react-statics": "^3.3.2", "semver": "^7.3.5", "shelljs": "^0.10.0", + "tsx": "^4.23.13", "xcode": "^3.0.1", "yauzl": "^3.2.0", "yazl": "^3.3.1" From de24a069763251472e0b4cac5428b01f9c69db0b Mon Sep 17 00:00:00 2001 From: Floyd Kim Date: Thu, 3 Sep 2026 14:05:55 +0900 Subject: [PATCH 2/5] ci: load a TypeScript config through the compiled CLI --- .github/workflows/unit-test.yml | 3 +++ .../ts-config-project/code-push.config.ts | 14 ++++++++++++++ cli/__fixtures__/ts-config-project/helpers/host.ts | 5 +++++ cli/__fixtures__/ts-config-project/package.json | 4 ++++ cli/__fixtures__/ts-config-project/tsconfig.json | 10 ++++++++++ cli/tsconfig.json | 3 ++- 6 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 cli/__fixtures__/ts-config-project/code-push.config.ts create mode 100644 cli/__fixtures__/ts-config-project/helpers/host.ts create mode 100644 cli/__fixtures__/ts-config-project/package.json create mode 100644 cli/__fixtures__/ts-config-project/tsconfig.json diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 9f9e9e671..6fb6a136f 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -35,3 +35,6 @@ jobs: run: | npm run build:cli node bin/code-push.js build-patch-tools --print-hash > /dev/null + # Loads a TypeScript config file that uses `export default` and a tsconfig `paths` alias, + # from its project directory the way a user runs the CLI. + (cd cli/__fixtures__/ts-config-project && node ../../../bin/code-push.js show-history -b 1.0.0 -p ios | grep -q '"packageHash": "fixture"') diff --git a/cli/__fixtures__/ts-config-project/code-push.config.ts b/cli/__fixtures__/ts-config-project/code-push.config.ts new file mode 100644 index 000000000..85f5d1c9a --- /dev/null +++ b/cli/__fixtures__/ts-config-project/code-push.config.ts @@ -0,0 +1,14 @@ +// Loaded by the CI smoke test through the compiled CLI: a TypeScript config that uses +// `export default` and a tsconfig `paths` alias, the two things the loader must handle. +import type { CliConfigInterface, ReleaseHistoryInterface } from "@bravemobile/react-native-code-push"; +import { downloadUrlFor } from "@helpers/host"; + +const config: CliConfigInterface = { + bundleUploader: async (source) => ({ downloadUrl: downloadUrlFor(source) }), + getReleaseHistory: async (targetBinaryVersion): Promise => ({ + [targetBinaryVersion]: { enabled: true, mandatory: false, downloadUrl: downloadUrlFor("fixture.zip"), packageHash: "fixture" }, + }), + setReleaseHistory: async () => {}, +}; + +export default config; diff --git a/cli/__fixtures__/ts-config-project/helpers/host.ts b/cli/__fixtures__/ts-config-project/helpers/host.ts new file mode 100644 index 000000000..70f959dec --- /dev/null +++ b/cli/__fixtures__/ts-config-project/helpers/host.ts @@ -0,0 +1,5 @@ +const CDN_HOST = "https://cdn.example.com"; + +export function downloadUrlFor(fileName: string): string { + return `${CDN_HOST}/${fileName}`; +} diff --git a/cli/__fixtures__/ts-config-project/package.json b/cli/__fixtures__/ts-config-project/package.json new file mode 100644 index 000000000..daeb8a2cb --- /dev/null +++ b/cli/__fixtures__/ts-config-project/package.json @@ -0,0 +1,4 @@ +{ + "name": "ts-config-project", + "private": true +} diff --git a/cli/__fixtures__/ts-config-project/tsconfig.json b/cli/__fixtures__/ts-config-project/tsconfig.json new file mode 100644 index 000000000..473bd53d4 --- /dev/null +++ b/cli/__fixtures__/ts-config-project/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "baseUrl": ".", + "paths": { + "@helpers/*": ["helpers/*"] + } + } +} diff --git a/cli/tsconfig.json b/cli/tsconfig.json index 706bbd6ee..bfc6958c8 100644 --- a/cli/tsconfig.json +++ b/cli/tsconfig.json @@ -16,6 +16,7 @@ }, "include": ["./**/*.ts"], "exclude": [ - "dist" + "dist", + "**/__fixtures__" ] } From 946c74a81fc6b04511cc2c0f5e01f2674e7fb4a4 Mon Sep 17 00:00:00 2001 From: Floyd Kim Date: Thu, 3 Sep 2026 14:05:55 +0900 Subject: [PATCH 3/5] docs: drop the ts-node setup for TypeScript config files --- README.md | 21 --------------------- cli/README.ko.md | 1 - cli/README.md | 1 - 3 files changed, 23 deletions(-) diff --git a/README.md b/README.md index f3104a6da..bc9db07d3 100644 --- a/README.md +++ b/README.md @@ -394,27 +394,6 @@ module.exports = Config; - Modifying an existing release history with the `update-history` command. -**(2) For `code-push.config.ts` (TypeScript) to work properly, you may need to update your `tsconfig.json`.** - -```diff - { - "extends": "@react-native/typescript-config/tsconfig.json", - // ... - "include": [ - // ... -+ "code-push.config.ts" - ], -+ "ts-node": { -+ "compilerOptions": { -+ "module": "CommonJS", -+ "types": ["node"] -+ } -+ } - } - -``` - - ### 6. Diff Updates (Optional) In place of the full archive, a release can offer a binary patch computed against the JS diff --git a/cli/README.ko.md b/cli/README.ko.md index bd101412e..a59aa7dba 100644 --- a/cli/README.ko.md +++ b/cli/README.ko.md @@ -6,7 +6,6 @@ - **Node.js** >= 18 - React Native 프로젝트에서 **Hermes** 엔진 활성화 -- **ts-node** (선택 사항, 설정 파일이 `.ts`인 경우 필요) ## 빠른 시작 diff --git a/cli/README.md b/cli/README.md index b938d0e68..a422adff3 100644 --- a/cli/README.md +++ b/cli/README.md @@ -6,7 +6,6 @@ CLI for [`@bravemobile/react-native-code-push`](../README.md). Bundles, releases - **Node.js** >= 18 - **Hermes** engine enabled in your React Native project -- **ts-node** (optional — only needed if your config file is `.ts`) ## Quick Start From f926fc82a9971533749dc91a49e1a5d9aa95744a Mon Sep 17 00:00:00 2001 From: Floyd Kim Date: Sun, 6 Sep 2026 21:24:41 +0900 Subject: [PATCH 4/5] feat: keep loading TypeScript configs with ts-node, and make tsx optional Projects that already set up ts-node keep working without a change, and tsx moves from a regular dependency to an optional peer dependency so a project adopts it when it is ready. The loader tries tsx first and falls back to ts-node, which leaves existing ts-node projects untouched while letting a migrating project switch by installing tsx alone. When neither is installed, the CLI points at tsx. Both are resolved from the project the config file lives in rather than from the CLI install. ts-node is no longer maintained, so the README marks support for it as deprecated without committing to a removal version. --- README.md | 34 ++++++++++++++++++++++ cli/README.ko.md | 1 + cli/README.md | 1 + cli/package.json | 13 ++++++++- cli/utils/fsUtils.ts | 39 ++++++++++++++++++++++---- package-lock.json | 67 +++++++++++++++++++++++++++++--------------- package.json | 12 ++++++-- 7 files changed, 136 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index bc9db07d3..432116b1b 100644 --- a/README.md +++ b/README.md @@ -394,6 +394,40 @@ module.exports = Config; - Modifying an existing release history with the `update-history` command. +**(2) A `code-push.config.ts` (TypeScript) file needs a loader installed.** + +Install `tsx`, which requires no further setup: + +```bash +npm install --save-dev tsx +``` + +`ts-node` also keeps working, and is used when `tsx` is not installed. Note that `ts-node` is no +longer maintained, so support for it is **deprecated and will be removed in a future major +version** — please migrate to `tsx`. Until then, `ts-node` needs the following `tsconfig.json` +setup: + +```diff + { + "extends": "@react-native/typescript-config/tsconfig.json", + // ... + "include": [ + // ... ++ "code-push.config.ts" + ], ++ "ts-node": { ++ "compilerOptions": { ++ "module": "CommonJS", ++ "types": ["node"] ++ } ++ } + } + +``` + +A `code-push.config.js` (JavaScript) file needs neither. + + ### 6. Diff Updates (Optional) In place of the full archive, a release can offer a binary patch computed against the JS diff --git a/cli/README.ko.md b/cli/README.ko.md index a59aa7dba..79245fa23 100644 --- a/cli/README.ko.md +++ b/cli/README.ko.md @@ -6,6 +6,7 @@ - **Node.js** >= 18 - React Native 프로젝트에서 **Hermes** 엔진 활성화 +- **tsx** 또는 **ts-node** (선택 사항, 설정 파일이 `.ts`인 경우에만 필요하며 `tsx`를 권장합니다) ## 빠른 시작 diff --git a/cli/README.md b/cli/README.md index a422adff3..76e6e0fca 100644 --- a/cli/README.md +++ b/cli/README.md @@ -6,6 +6,7 @@ CLI for [`@bravemobile/react-native-code-push`](../README.md). Bundles, releases - **Node.js** >= 18 - **Hermes** engine enabled in your React Native project +- **tsx** or **ts-node** (optional — only needed if your config file is `.ts`; `tsx` recommended) ## Quick Start diff --git a/cli/package.json b/cli/package.json index eca1fa6a0..1b7f91793 100644 --- a/cli/package.json +++ b/cli/package.json @@ -14,11 +14,22 @@ "commander": "^12.1.0", "semver": "^7.3.5", "shelljs": "^0.10.0", - "tsx": "^4.23.13", "xcode": "^3.0.1", "yazl": "^3.3.1", "yauzl": "^3.2.0" }, + "peerDependencies": { + "ts-node": ">=10", + "tsx": ">=4" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + }, + "tsx": { + "optional": true + } + }, "engines": { "node": ">=18" }, diff --git a/cli/utils/fsUtils.ts b/cli/utils/fsUtils.ts index c919aa6ad..2216f8f57 100644 --- a/cli/utils/fsUtils.ts +++ b/cli/utils/fsUtils.ts @@ -1,7 +1,6 @@ import fs from "fs"; import path from "path"; import { createRequire } from "module"; -import { require as tsxRequire } from "tsx/cjs/api"; import type { CliConfigInterface } from "../../typings/react-native-code-push.d.ts"; /** @@ -9,18 +8,48 @@ import type { CliConfigInterface } from "../../typings/react-native-code-push.d. */ function requireConfig(filePath: string): CliConfigInterface { const ext = path.extname(filePath); + // Resolve the loader from the project the config file lives in, not from the CLI install. + const projectRequire = createRequire(filePath); if (ext === '.ts') { - // tsx compiles the file and the project files it imports, resolving tsconfig `paths` aliases - // from the tsconfig.json nearest to the working directory, which is the project root when the CLI runs. - return unwrapDefaultExport(tsxRequire(filePath, filePath)); + return unwrapDefaultExport(requireTsConfig(projectRequire, filePath)); } else if (ext === '.js') { // do nothing } else { throw new Error(`Unsupported file extension: ${ext}`); } - return unwrapDefaultExport(createRequire(filePath)(filePath)); + return unwrapDefaultExport(projectRequire(filePath)); +} + +/** + * tsx is preferred: it needs no tsconfig setup and resolves tsconfig `paths` aliases on its own. + * ts-node keeps working for projects that already have it configured. + */ +function requireTsConfig(projectRequire: NodeRequire, filePath: string): { default?: unknown } { + if (canResolve(projectRequire, 'tsx/cjs/api')) { + const { require: tsxRequire } = projectRequire('tsx/cjs/api') as { + require: (id: string, fromFile: string) => { default?: unknown }; + }; + return tsxRequire(filePath, filePath); + } + + if (canResolve(projectRequire, 'ts-node/register')) { + projectRequire('ts-node/register'); + return projectRequire(filePath); + } + + console.error('A TypeScript config file needs a loader. Please install tsx as a devDependency (`npm i -D tsx`).'); + process.exit(1); +} + +function canResolve(projectRequire: NodeRequire, id: string): boolean { + try { + projectRequire.resolve(id); + return true; + } catch { + return false; + } } // `export default` compiles to `exports.default`; `module.exports =` is returned as is. diff --git a/package-lock.json b/package-lock.json index 8f03f7948..2d05c93ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,6 @@ "hoist-non-react-statics": "^3.3.2", "semver": "^7.3.5", "shelljs": "^0.10.0", - "tsx": "^4.23.13", "xcode": "^3.0.1", "yauzl": "^3.2.0", "yazl": "^3.3.1" @@ -44,6 +43,7 @@ "react": "19.2.3", "react-native": "0.84.1", "ts-node": "^10.9.2", + "tsx": "^4.23.13", "typescript": "5.0.4", "typescript-eslint": "^8.11.0" }, @@ -52,11 +52,19 @@ }, "peerDependencies": { "expo": ">=50.0.0", - "react-native": "*" + "react-native": "*", + "ts-node": ">=10", + "tsx": ">=4" }, "peerDependenciesMeta": { "expo": { "optional": true + }, + "ts-node": { + "optional": true + }, + "tsx": { + "optional": true } } }, @@ -67,7 +75,6 @@ "commander": "^12.1.0", "semver": "^7.3.5", "shelljs": "^0.10.0", - "tsx": "^4.23.13", "xcode": "^3.0.1", "yauzl": "^3.2.0", "yazl": "^3.3.1" @@ -79,6 +86,18 @@ }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "ts-node": ">=10", + "tsx": ">=4" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + }, + "tsx": { + "optional": true + } } }, "code-push-plugin-testing-framework": { @@ -1785,7 +1804,7 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -1796,7 +1815,7 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -2813,7 +2832,7 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2832,7 +2851,7 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -3061,22 +3080,22 @@ }, "node_modules/@tsconfig/node10": { "version": "1.0.11", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/babel__core": { @@ -3226,7 +3245,7 @@ "version": "18.19.129", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.129.tgz", "integrity": "sha512-hrmi5jWt2w60ayox3iIXwpMEnfUvOLJCRtrOPbHtH15nTjvO7uhnelvrdAs0dO0/zl5DZ3ZbahiaXEVb54ca/A==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -3574,7 +3593,7 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3593,7 +3612,7 @@ }, "node_modules/acorn-walk": { "version": "8.3.2", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -3680,7 +3699,7 @@ }, "node_modules/arg": { "version": "4.1.3", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/argparse": { @@ -4523,7 +4542,7 @@ }, "node_modules/create-require": { "version": "1.1.1", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/cross-spawn": { @@ -4923,6 +4942,7 @@ "version": "0.28.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "devOptional": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -7294,7 +7314,7 @@ }, "node_modules/make-error": { "version": "1.3.6", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/makeerror": { @@ -9402,7 +9422,7 @@ }, "node_modules/ts-node": { "version": "10.9.2", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -9444,7 +9464,7 @@ }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -9454,6 +9474,7 @@ "version": "4.23.13", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz", "integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==", + "devOptional": true, "license": "MIT", "dependencies": { "esbuild": "~0.28.0" @@ -9572,7 +9593,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9621,7 +9642,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -9724,7 +9745,7 @@ }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/v8-to-istanbul": { @@ -10042,7 +10063,7 @@ }, "node_modules/yn": { "version": "3.1.1", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6" diff --git a/package.json b/package.json index c79e0f80e..b2f8a2549 100644 --- a/package.json +++ b/package.json @@ -96,18 +96,25 @@ "hoist-non-react-statics": "^3.3.2", "semver": "^7.3.5", "shelljs": "^0.10.0", - "tsx": "^4.23.13", "xcode": "^3.0.1", "yauzl": "^3.2.0", "yazl": "^3.3.1" }, "peerDependencies": { "expo": ">=50.0.0", - "react-native": "*" + "react-native": "*", + "ts-node": ">=10", + "tsx": ">=4" }, "peerDependenciesMeta": { "expo": { "optional": true + }, + "ts-node": { + "optional": true + }, + "tsx": { + "optional": true } }, "devDependencies": { @@ -130,6 +137,7 @@ "react": "19.2.3", "react-native": "0.84.1", "ts-node": "^10.9.2", + "tsx": "^4.23.13", "typescript": "5.0.4", "typescript-eslint": "^8.11.0" }, From 43f34891122d88c3bc6277b66faaf83618311db0 Mon Sep 17 00:00:00 2001 From: Floyd Kim Date: Sun, 6 Sep 2026 22:44:42 +0900 Subject: [PATCH 5/5] feat(cli): warn when a config file is loaded with ts-node ts-node is no longer maintained, and support for it as a config loader will be removed in a future major version. Projects still on it now see the notice on every command that reads the config file. The warning goes to stderr, so piping a command's JSON output is unaffected. --- cli/utils/fsUtils.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cli/utils/fsUtils.ts b/cli/utils/fsUtils.ts index 2216f8f57..5a8b27671 100644 --- a/cli/utils/fsUtils.ts +++ b/cli/utils/fsUtils.ts @@ -35,6 +35,10 @@ function requireTsConfig(projectRequire: NodeRequire, filePath: string): { defau } if (canResolve(projectRequire, 'ts-node/register')) { + console.warn( + 'warn: Loading the config file with ts-node, which is no longer maintained. Support for it ' + + 'will be removed in a future major version - please install tsx instead (`npm i -D tsx`).', + ); projectRequire('ts-node/register'); return projectRequire(filePath); }