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,
|
readFile,
|
||||||
removeFile,
|
removeFile,
|
||||||
cleanupProject,
|
cleanupProject,
|
||||||
|
runCommand,
|
||||||
|
getPackageManagerCommand,
|
||||||
|
updateJson,
|
||||||
} from '@nrwl/e2e/utils';
|
} from '@nrwl/e2e/utils';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
import { ASYNC_GENERATOR_EXECUTOR_CONTENTS } from './nx-plugin.fixtures';
|
import { ASYNC_GENERATOR_EXECUTOR_CONTENTS } from './nx-plugin.fixtures';
|
||||||
|
|
||||||
@ -360,6 +364,30 @@ describe('Nx Plugin', () => {
|
|||||||
expect(() => checkFilesExist(`libs/${generatedProject}`)).not.toThrow();
|
expect(() => checkFilesExist(`libs/${generatedProject}`)).not.toThrow();
|
||||||
expect(() => runCLI(`execute ${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', () => {
|
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 swcNodeInstalled = packageIsInstalled('@swc-node/register');
|
||||||
const tsNodeInstalled = packageIsInstalled('ts-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
|
* Optionally, if swc-node and tsconfig-paths are available in the current workspace, apply the require
|
||||||
@ -63,7 +64,7 @@ export function registerTranspiler(
|
|||||||
registerTranspiler = () => {
|
registerTranspiler = () => {
|
||||||
const service = register({
|
const service = register({
|
||||||
transpileOnly: true,
|
transpileOnly: true,
|
||||||
compilerOptions,
|
compilerOptions: getTsNodeCompilerOptions(compilerOptions),
|
||||||
});
|
});
|
||||||
// Don't warn if a faster transpiler is enabled
|
// Don't warn if a faster transpiler is enabled
|
||||||
if (!service.options.transpiler && !service.options.swc) {
|
if (!service.options.transpiler && !service.options.swc) {
|
||||||
@ -121,8 +122,10 @@ function readCompilerOptions(tsConfigPath): CompilerOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function readCompilerOptionsWithTypescript(tsConfigPath) {
|
function readCompilerOptionsWithTypescript(tsConfigPath) {
|
||||||
const { readConfigFile, parseJsonConfigFileContent, sys } =
|
if (!ts) {
|
||||||
require('typescript') as typeof import('typescript');
|
ts = require('typescript');
|
||||||
|
}
|
||||||
|
const { readConfigFile, parseJsonConfigFileContent, sys } = ts;
|
||||||
const jsonContent = readConfigFile(tsConfigPath, sys.readFile);
|
const jsonContent = readConfigFile(tsConfigPath, sys.readFile);
|
||||||
const { options } = parseJsonConfigFileContent(
|
const { options } = parseJsonConfigFileContent(
|
||||||
jsonContent,
|
jsonContent,
|
||||||
@ -164,3 +167,44 @@ function packageIsInstalled(m: string) {
|
|||||||
return false;
|
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