@nx/devkit
Advanced tools
@@ -11,5 +11,9 @@ "use strict"; | ||
| const { JsxEmit, ScriptTarget, transpile, ModuleKind } = (0, package_json_1.ensurePackage)('typescript', versions_1.typescriptVersion); | ||
| // Match `.ts`, `.mts`, `.cts`, `.tsx`. The optional `[cm]` keeps native | ||
| // ESM (`.mts`) and CommonJS (`.cts`) TypeScript extensions in the rename | ||
| // path so `--js` generators that emit `.mts`/`.cts` templates get | ||
| // converted instead of silently left as TypeScript on disk. | ||
| const tsExtRegex = /\.([cm]?ts|tsx)$/; | ||
| for (const c of tree.listChanges()) { | ||
| if ((c.path.endsWith('.ts') || c.path.endsWith('tsx')) && | ||
| c.type === 'CREATE') { | ||
| if (tsExtRegex.test(c.path) && c.type === 'CREATE') { | ||
| tree.write(c.path, transpile(c.content.toString('utf-8'), { | ||
@@ -21,3 +25,4 @@ allowJs: true, | ||
| })); | ||
| tree.rename(c.path, c.path.replace(/\.ts$/, options?.extension ?? '.js')); | ||
| const targetExt = options?.extension ?? '.js'; | ||
| tree.rename(c.path, c.path.replace(/\.([cm]?ts)$/, targetExt)); | ||
| if (options?.useJsx) { | ||
@@ -27,3 +32,3 @@ tree.rename(c.path, c.path.replace(/\.tsx$/, '.jsx')); | ||
| else { | ||
| tree.rename(c.path, c.path.replace(/\.tsx$/, options?.extension ?? '.js')); | ||
| tree.rename(c.path, c.path.replace(/\.tsx$/, targetExt)); | ||
| } | ||
@@ -30,0 +35,0 @@ } |
@@ -30,4 +30,10 @@ "use strict"; | ||
| const tsConfigPath = getTypeScriptConfigPath(path, tsconfigFileNames); | ||
| if (tsConfigPath) { | ||
| const unregisterTsProject = (0, devkit_internals_1.registerTsProject)(tsConfigPath); | ||
| if (!tsConfigPath) { | ||
| return await loadModuleByExtension(path, extension); | ||
| } | ||
| // loadTsFile was added in nx@23. @nx/devkit's peer range supports older | ||
| // nx majors, so fall back to the legacy registerTsProject + require path | ||
| // when loadTsFile isn't available on the host nx. | ||
| if (typeof devkit_internals_1.loadTsFile !== 'function') { | ||
| const cleanup = (0, devkit_internals_1.registerTsProject)(tsConfigPath); | ||
| try { | ||
@@ -37,6 +43,55 @@ return await loadModuleByExtension(path, extension); | ||
| finally { | ||
| unregisterTsProject(); | ||
| cleanup(); | ||
| } | ||
| } | ||
| return await loadModuleByExtension(path, extension); | ||
| // Both .ts and .mts go through loadTsFile first. Node 22.12+ supports | ||
| // require() of synchronous ESM by default, and loadTsFile's lazy fallback | ||
| // covers swc/ts-node + tsconfig-paths registration when needed (swc-node | ||
| // hooks .cts/.mts/.ts via Module._extensions). Async-only ESM modules | ||
| // (top-level await) throw ERR_REQUIRE_ASYNC_MODULE and fall through to | ||
| // dynamic import(). ERR_REQUIRE_ESM is the legacy code for the same case | ||
| // - kept for older Node lines. | ||
| try { | ||
| return (0, devkit_internals_1.loadTsFile)(path, tsConfigPath); | ||
| } | ||
| catch (e) { | ||
| if (e?.code !== 'ERR_REQUIRE_ESM' && | ||
| e?.code !== 'ERR_REQUIRE_ASYNC_MODULE') { | ||
| throw e; | ||
| } | ||
| // The module must be loaded via dynamic import(). Register | ||
| // tsconfig-paths first so workspace alias imports resolve, then try a | ||
| // native dynamic import. Node 22.18+ LTS strips TS types on the ESM | ||
| // path natively, so pure-ESM TLA configs load without any swc/ts-node | ||
| // ESM loader. Only escalate to forceRegisterEsmLoader (which throws | ||
| // when neither @swc-node/register nor ts-node is installed) if the | ||
| // native attempt hits unsupported TS syntax. | ||
| const cleanup = (0, devkit_internals_1.registerTsProject)(tsConfigPath); | ||
| try { | ||
| return await loadESM(path); | ||
| } | ||
| catch (esmErr) { | ||
| if (esmErr?.code !== 'ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX' || | ||
| typeof devkit_internals_1.forceRegisterEsmLoader !== 'function') { | ||
| throw esmErr; | ||
| } | ||
| // Module.register is global and one-shot per process. After this | ||
| // runs, every subsequent ESM import in the process is routed | ||
| // through the registered loader, forfeiting Node's native TS | ||
| // stripping for the dynamic-import path. If neither swc-node nor | ||
| // ts-node is installed, forceRegisterEsmLoader throws - surface the | ||
| // original ESM error in that case so the user sees the real | ||
| // problem, not a misleading "loader missing" message. | ||
| try { | ||
| (0, devkit_internals_1.forceRegisterEsmLoader)(); | ||
| } | ||
| catch { | ||
| throw esmErr; | ||
| } | ||
| return await loadESM(path); | ||
| } | ||
| finally { | ||
| cleanup(); | ||
| } | ||
| } | ||
| } | ||
@@ -43,0 +98,0 @@ function getTypeScriptConfigPath(path, tsconfigFileNames) { |
+2
-2
| { | ||
| "name": "@nx/devkit", | ||
| "version": "23.0.0-canary.20260515-4f14067", | ||
| "version": "23.0.0-canary.20260519-6e6edab", | ||
| "private": false, | ||
@@ -63,3 +63,3 @@ "type": "commonjs", | ||
| "jest": "30.3.0", | ||
| "nx": "23.0.0-canary.20260515-4f14067" | ||
| "nx": "23.0.0-canary.20260519-6e6edab" | ||
| }, | ||
@@ -66,0 +66,0 @@ "peerDependencies": { |
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 8 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 8 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
301704
1%6973
0.87%42
2.44%