nx/e2e/js/src/js-executor-tsc.test.ts
LongYinan 981eb30a0f
feat(core): support compile to wasi target (#22870)
This pull request is trying to add wasm32-wasi target support for the
nx/native

To test the build, you can run the following commands:

- `rustup target add wasm32-wasip1-threads`
- `pnpm exec napi build --release --platform --package-json-path
packages/nx/package.json --manifest-path packages/nx/Cargo.toml --js
./native-bindings.js -o packages/nx/src/native --target
wasm32-wasip1-threads`

And the wasm file will be built at
packages/nx/src/native/nx.wasm32-wasi.wasm

Blocked by:

- Support @napi-rs/cli 3.0  Cammisuli/monodon#48
- https://github.com/napi-rs/napi-rs/issues/2009

The pseudo_terminal mod is excluded on the wasm32 targets, which is as
expected.

The watch mod is excluded because of the upstream `watchexec` deps
introduced by ignore-files don't support the wasi target at this moment
(but we can improve it).

## Related Issues
Fixes https://github.com/nrwl/nx/issues/21860
Fixes https://github.com/nrwl/nx/issues/23821

---------

Co-authored-by: FrozenPandaz <jasonjean1993@gmail.com>
2024-07-05 15:55:35 -04:00

290 lines
8.5 KiB
TypeScript

import {
checkFilesDoNotExist,
checkFilesExist,
cleanupProject,
createFile,
detectPackageManager,
getPackageManagerCommand,
newProject,
packageManagerLockFile,
readFile,
readJson,
rmDist,
runCLI,
runCLIAsync,
runCommand,
runCommandUntil,
tmpProjPath,
uniq,
updateFile,
updateJson,
waitUntil,
} from '../../utils';
describe('js:tsc executor', () => {
let scope;
beforeAll(() => (scope = newProject()));
afterAll(() => cleanupProject());
it('should create libs with js executors (--compiler=tsc)', async () => {
const lib = uniq('lib');
runCLI(`generate @nx/js:lib ${lib} --bundler=tsc --no-interactive`);
const libPackageJson = readJson(`libs/${lib}/package.json`);
expect(libPackageJson.scripts).toBeUndefined();
expect(runCLI(`build ${lib}`)).toContain('Done compiling TypeScript files');
checkFilesExist(
`dist/libs/${lib}/README.md`,
`dist/libs/${lib}/package.json`,
`dist/libs/${lib}/src/index.js`,
`dist/libs/${lib}/src/lib/${lib}.js`,
`dist/libs/${lib}/src/index.d.ts`,
`dist/libs/${lib}/src/lib/${lib}.d.ts`
);
runCLI(`build ${lib} --generateLockfile=true`);
checkFilesExist(
`dist/libs/${lib}/package.json`,
`dist/libs/${lib}/${
packageManagerLockFile[detectPackageManager(tmpProjPath())]
}`
);
updateJson(`libs/${lib}/project.json`, (json) => {
json.targets.build.options.assets.push({
input: `libs/${lib}/docs`,
glob: '**/*.md',
output: 'docs',
});
return json;
});
const libBuildProcess = await runCommandUntil(
`build ${lib} --watch`,
(output) => output.includes(`Watching for file changes`),
{
env: {
NX_DAEMON: 'true',
},
}
);
updateFile(`libs/${lib}/README.md`, `Hello, World!`);
updateJson(`libs/${lib}/package.json`, (json) => {
json.version = '999.9.9';
return json;
});
updateFile(`libs/${lib}/docs/a/b/nested.md`, 'Nested File');
await expect(
waitUntil(
() => readFile(`dist/libs/${lib}/README.md`).includes(`Hello, World!`),
{
timeout: 20_000,
ms: 500,
}
)
).resolves.not.toThrow();
await expect(
waitUntil(
() =>
readFile(`dist/libs/${lib}/docs/a/b/nested.md`).includes(
`Nested File`
),
{
timeout: 20_000,
ms: 500,
}
)
).resolves.not.toThrow();
await expect(
waitUntil(
() =>
readFile(`dist/libs/${lib}/package.json`).includes(
`"version": "999.9.9"`
),
{
timeout: 20_000,
ms: 500,
}
)
).resolves.not.toThrow();
libBuildProcess.kill();
const parentLib = uniq('parentlib');
runCLI(`generate @nx/js:lib ${parentLib} --bundler=tsc --no-interactive`);
const parentLibPackageJson = readJson(`libs/${parentLib}/package.json`);
expect(parentLibPackageJson.scripts).toBeUndefined();
expect((await runCLIAsync(`test ${parentLib}`)).combinedOutput).toContain(
'Ran all test suites'
);
expect(runCLI(`build ${parentLib}`)).toContain(
'Done compiling TypeScript files'
);
checkFilesExist(
`dist/libs/${parentLib}/package.json`,
`dist/libs/${parentLib}/src/index.js`,
`dist/libs/${parentLib}/src/lib/${parentLib}.js`,
`dist/libs/${parentLib}/src/index.d.ts`,
`dist/libs/${parentLib}/src/lib/${parentLib}.d.ts`
);
const tsconfig = readJson(`tsconfig.base.json`);
expect(tsconfig.compilerOptions.paths).toEqual({
[`@${scope}/${lib}`]: [`libs/${lib}/src/index.ts`],
[`@${scope}/${parentLib}`]: [`libs/${parentLib}/src/index.ts`],
});
updateFile(`libs/${parentLib}/src/index.ts`, () => {
return `
import { ${lib} } from '@${scope}/${lib}'
export * from './lib/${parentLib}';
`;
});
const output = runCLI(`build ${parentLib}`);
expect(output).toContain('1 task it depends on');
expect(output).toContain('Done compiling TypeScript files');
updateJson(`libs/${lib}/tsconfig.json`, (json) => {
json.compilerOptions = { ...json.compilerOptions, importHelpers: true };
return json;
});
updateJson(`libs/${lib}/package.json`, (json) => {
// Delete automatically generated helper dependency to test legacy behavior.
delete json.dependencies.tslib;
return json;
});
// check batch build
rmDist();
let batchBuildOutput = runCLI(`build ${parentLib} --skip-nx-cache`, {
env: { NX_BATCH_MODE: 'true' },
});
expect(batchBuildOutput).toContain(`Running 2 tasks with @nx/js:tsc`);
expect(batchBuildOutput).toContain(
`Compiling TypeScript files for project "${lib}"...`
);
expect(batchBuildOutput).toContain(
`Done compiling TypeScript files for project "${lib}".`
);
expect(batchBuildOutput).toContain(
`Compiling TypeScript files for project "${parentLib}"...`
);
expect(batchBuildOutput).toContain(
`Done compiling TypeScript files for project "${parentLib}".`
);
expect(batchBuildOutput).toContain(
`Successfully ran target build for project ${parentLib} and 1 task it depends on`
);
batchBuildOutput = runCLI(`build ${parentLib} --skip-nx-cache --batch`);
expect(batchBuildOutput).toContain(`Running 2 tasks with @nx/js:tsc`);
checkFilesExist(
// parent
`dist/libs/${parentLib}/package.json`,
`dist/libs/${parentLib}/README.md`,
`dist/libs/${parentLib}/tsconfig.tsbuildinfo`,
`dist/libs/${parentLib}/src/index.js`,
`dist/libs/${parentLib}/src/index.d.ts`,
`dist/libs/${parentLib}/src/lib/${parentLib}.js`,
`dist/libs/${parentLib}/src/lib/${parentLib}.d.ts`,
// child
`dist/libs/${lib}/package.json`,
`dist/libs/${lib}/README.md`,
`dist/libs/${lib}/tsconfig.tsbuildinfo`,
`dist/libs/${lib}/src/index.js`,
`dist/libs/${lib}/src/index.d.ts`,
`dist/libs/${lib}/src/lib/${lib}.js`,
`dist/libs/${lib}/src/lib/${lib}.d.ts`
);
// run a second time skipping the nx cache and with the outputs present
const secondBatchBuildOutput = runCLI(
`build ${parentLib} --skip-nx-cache`,
{ env: { NX_BATCH_MODE: 'true' } }
);
expect(secondBatchBuildOutput).toContain(
`Successfully ran target build for project ${parentLib} and 1 task it depends on`
);
}, 240_000);
it('should not create a `.babelrc` file when creating libs with js executors (--compiler=tsc)', () => {
const lib = uniq('lib');
runCLI(
`generate @nx/js:lib ${lib} --compiler=tsc --includeBabelRc=false --no-interactive`
);
checkFilesDoNotExist(`libs/${lib}/.babelrc`);
});
it('should allow wildcard ts path alias', async () => {
const base = uniq('base');
runCLI(`generate @nx/js:lib ${base} --bundler=tsc --no-interactive`);
const lib = uniq('lib');
runCLI(`generate @nx/js:lib ${lib} --bundler=tsc --no-interactive`);
updateFile(`libs/${base}/src/index.ts`, () => {
return `
import { ${lib} } from '@${scope}/${lib}'
export * from './lib/${base}';
${lib}();
`;
});
expect(runCLI(`build ${base}`)).toContain(
'Done compiling TypeScript files'
);
updateJson('tsconfig.base.json', (json) => {
json['compilerOptions']['paths'][`@${scope}/${lib}/*`] = [
`libs/${lib}/src/*`,
];
return json;
});
createFile(
`libs/${lib}/src/${lib}.ts`,
`
export function ${lib}Wildcard() {
return '${lib}-wildcard';
};
`
);
updateFile(`libs/${base}/src/index.ts`, () => {
return `
import { ${lib} } from '@${scope}/${lib}';
import { ${lib}Wildcard } from '@${scope}/${lib}/src/${lib}';
export * from './lib/${base}';
${lib}();
${lib}Wildcard();
`;
});
expect(runCLI(`build ${base}`)).toContain(
'Done compiling TypeScript files'
);
}, 240_000);
it('should update package.json with detected dependencies', async () => {
const pmc = getPackageManagerCommand();
const lib = uniq('lib');
runCLI(`generate @nx/js:lib ${lib} --bundler=tsc --no-interactive`);
// Add a dependency for this lib to check the built package.json
runCommand(`${pmc.addProd} react`);
runCommand(`${pmc.addDev} @types/react`);
updateFile(`libs/${lib}/src/index.ts`, (content) => {
return `
import 'react';
${content};
`;
});
}, 240_000);
});