fix(nx-plugin): local plugin execution should work with ts-node (#15066)
This commit is contained in:
parent
7d80f25833
commit
6ff04d5a9b
@ -15,7 +15,11 @@ import {
|
||||
readFile,
|
||||
removeFile,
|
||||
cleanupProject,
|
||||
runCommand,
|
||||
getPackageManagerCommand,
|
||||
updateJson,
|
||||
} from '@nrwl/e2e/utils';
|
||||
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||
|
||||
import { ASYNC_GENERATOR_EXECUTOR_CONTENTS } from './nx-plugin.fixtures';
|
||||
|
||||
@ -360,6 +364,30 @@ describe('Nx Plugin', () => {
|
||||
expect(() => checkFilesExist(`libs/${generatedProject}`)).not.toThrow();
|
||||
expect(() => runCLI(`execute ${generatedProject}`)).not.toThrow();
|
||||
});
|
||||
|
||||
it('should work with ts-node only', async () => {
|
||||
const oldPackageJson: PackageJson = readJson('package.json');
|
||||
updateJson<PackageJson>('package.json', (j) => {
|
||||
delete j.dependencies['@swc-node/register'];
|
||||
delete j.devDependencies['@swc-node/register'];
|
||||
return j;
|
||||
});
|
||||
runCommand(getPackageManagerCommand().install);
|
||||
|
||||
const generator = uniq('generator');
|
||||
|
||||
expect(() => {
|
||||
runCLI(
|
||||
`generate @nrwl/nx-plugin:generator ${generator} --project=${plugin}`
|
||||
);
|
||||
|
||||
runCLI(
|
||||
`generate @${npmScope}/${plugin}:${generator} --name ${uniq('test')}`
|
||||
);
|
||||
}).not.toThrow();
|
||||
updateFile('package.json', JSON.stringify(oldPackageJson, null, 2));
|
||||
runCommand(getPackageManagerCommand().install);
|
||||
});
|
||||
});
|
||||
|
||||
describe('--directory', () => {
|
||||
|
||||
20
packages/nx/src/utils/register.spec.ts
Normal file
20
packages/nx/src/utils/register.spec.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { ModuleKind, ScriptTarget } from 'typescript';
|
||||
import { getTsNodeCompilerOptions } from './register';
|
||||
|
||||
describe('getTsNodeCompilerOptions', () => {
|
||||
it('should replace enum value with enum key for module', () => {
|
||||
expect(
|
||||
getTsNodeCompilerOptions({
|
||||
module: ModuleKind.CommonJS,
|
||||
}).module
|
||||
).toEqual('CommonJS');
|
||||
});
|
||||
|
||||
it('should replace enum value with enum key for target', () => {
|
||||
expect(
|
||||
getTsNodeCompilerOptions({
|
||||
target: ScriptTarget.ES2020,
|
||||
}).target
|
||||
).toEqual('ES2020');
|
||||
});
|
||||
});
|
||||
@ -4,6 +4,7 @@ import { logger, NX_PREFIX, stripIndent } from './logger';
|
||||
|
||||
const swcNodeInstalled = packageIsInstalled('@swc-node/register');
|
||||
const tsNodeInstalled = packageIsInstalled('ts-node/register');
|
||||
let ts: typeof import('typescript');
|
||||
|
||||
/**
|
||||
* Optionally, if swc-node and tsconfig-paths are available in the current workspace, apply the require
|
||||
@ -63,7 +64,7 @@ export function registerTranspiler(
|
||||
registerTranspiler = () => {
|
||||
const service = register({
|
||||
transpileOnly: true,
|
||||
compilerOptions,
|
||||
compilerOptions: getTsNodeCompilerOptions(compilerOptions),
|
||||
});
|
||||
// Don't warn if a faster transpiler is enabled
|
||||
if (!service.options.transpiler && !service.options.swc) {
|
||||
@ -121,8 +122,10 @@ function readCompilerOptions(tsConfigPath): CompilerOptions {
|
||||
}
|
||||
|
||||
function readCompilerOptionsWithTypescript(tsConfigPath) {
|
||||
const { readConfigFile, parseJsonConfigFileContent, sys } =
|
||||
require('typescript') as typeof import('typescript');
|
||||
if (!ts) {
|
||||
ts = require('typescript');
|
||||
}
|
||||
const { readConfigFile, parseJsonConfigFileContent, sys } = ts;
|
||||
const jsonContent = readConfigFile(tsConfigPath, sys.readFile);
|
||||
const { options } = parseJsonConfigFileContent(
|
||||
jsonContent,
|
||||
@ -164,3 +167,44 @@ function packageIsInstalled(m: string) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ts-node requires string values for enum based typescript options.
|
||||
* `register`'s signature just types the field as `object`, so we
|
||||
* unfortunately do not get any kind of type safety on this.
|
||||
*/
|
||||
export function getTsNodeCompilerOptions(compilerOptions: CompilerOptions) {
|
||||
if (!ts) {
|
||||
ts = require('typescript');
|
||||
}
|
||||
|
||||
const flagMap: Partial<
|
||||
Record<keyof RemoveIndex<CompilerOptions>, keyof typeof ts>
|
||||
> = {
|
||||
module: 'ModuleKind',
|
||||
target: 'ScriptTarget',
|
||||
moduleDetection: 'ModuleDetectionKind',
|
||||
newLine: 'NewLineKind',
|
||||
moduleResolution: 'ModuleResolutionKind',
|
||||
importsNotUsedAsValues: 'ImportsNotUsedAsValues',
|
||||
};
|
||||
|
||||
const result = { ...compilerOptions };
|
||||
|
||||
for (const flag in flagMap) {
|
||||
if (compilerOptions[flag]) {
|
||||
result[flag] = ts[flagMap[flag]][compilerOptions[flag]];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Index keys allow empty objects, where as "real" keys
|
||||
* require a value. Thus, this filters out index keys
|
||||
* See: https://stackoverflow.com/a/68261113/3662471
|
||||
*/
|
||||
type RemoveIndex<T> = {
|
||||
[K in keyof T as {} extends Record<K, 1> ? never : K]: T[K];
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user