diff --git a/e2e/js/src/js-swc.test.ts b/e2e/js/src/js-swc.test.ts index aa3b98f1a64e5c..2e737d63fe991f 100644 --- a/e2e/js/src/js-swc.test.ts +++ b/e2e/js/src/js-swc.test.ts @@ -1,3 +1,5 @@ +import { execSync } from 'child_process'; +import { writeFileSync } from 'fs-extra'; import { checkFilesDoNotExist, checkFilesExist, @@ -21,7 +23,9 @@ describe('js e2e', () => { scope = newProject(); }); - afterEach(() => cleanupProject()); + afterEach(() => { + cleanupProject(); + }); it('should create libs with js executors (--compiler=swc)', async () => { const lib = uniq('lib'); @@ -116,4 +120,50 @@ describe('js e2e', () => { 'peerDependencies.@swc/helpers' ); }, 240_000); + + it.only('should handle swcrc path mappings', async () => { + const lib = uniq('lib'); + runCLI(`generate @nrwl/js:lib ${lib} --compiler=swc --no-interactive`); + + // add a dummy x.ts file for path mappings + updateFile( + `libs/${lib}/src/x.ts`, + ` +export function x() { + console.log('x'); +} + ` + ); + + // update .swcrc to use path mappings + updateJson(`libs/${lib}/.swcrc`, (json) => { + json.jsc.paths = { + 'src/*': ['src/*'], + }; + return json; + }); + + // update lib.ts to use x + updateFile(`libs/${lib}/src/lib/${lib}.ts`, () => { + return ` +// @ts-ignore +import { x } from 'src/x'; + +export function myLib() { + console.log(x()); +} + +myLib(); + `; + }); + + // now run build + runCLI(`build ${lib}`); + + // invoke the lib with node + const result = execSync(`node dist/libs/${lib}/src/lib/${lib}.js`, { + cwd: tmpProjPath(), + }).toString(); + expect(result).toContain('x'); + }, 240_000); }); diff --git a/packages/js/src/executors/swc/swc.impl.ts b/packages/js/src/executors/swc/swc.impl.ts index 499623d0a7457f..76a6d65fa4b535 100644 --- a/packages/js/src/executors/swc/swc.impl.ts +++ b/packages/js/src/executors/swc/swc.impl.ts @@ -1,4 +1,4 @@ -import { ExecutorContext } from '@nrwl/devkit'; +import { ExecutorContext, readJsonFile, writeJsonFile } from '@nrwl/devkit'; import { assetGlobsToFiles, FileInputOutput, @@ -24,6 +24,7 @@ import { import { compileSwc, compileSwcWatch } from '../../utils/swc/compile-swc'; import { getSwcrcPath } from '../../utils/swc/get-swcrc-path'; import { generateTmpSwcrc } from '../../utils/swc/inline'; +import type { Options } from '@swc/core'; export function normalizeOptions( options: SwcExecutorOptions, @@ -68,7 +69,21 @@ export function normalizeOptions( // default to current directory if projectRootParts is []. // Eg: when a project is at the root level, outside of layout dir const swcCwd = projectRootParts.join('/') || '.'; - const swcrcPath = getSwcrcPath(options, contextRoot, projectRoot); + let swcrcPath = getSwcrcPath(options, contextRoot, projectRoot); + + try { + const swcrcContent = readJsonFile(swcrcPath) as Options; + // if we have path mappings setup but baseUrl isn't specified, then we're proceeding with the following logic + if ( + swcrcContent.jsc && + swcrcContent.jsc.paths && + !swcrcContent.jsc.baseUrl + ) { + swcrcContent.jsc.baseUrl = `./${projectDir}`; + swcrcPath = getSwcrcPath(options, contextRoot, projectRoot, true); + writeJsonFile(swcrcPath, swcrcContent); + } + } catch (e) {} const swcCliOptions = { srcPath: projectDir, @@ -190,7 +205,7 @@ export async function* swcExecutor( } function removeTmpSwcrc(swcrcPath: string) { - if (swcrcPath.startsWith('tmp/')) { + if (swcrcPath.includes('tmp/') && swcrcPath.includes('.generated.swcrc')) { removeSync(dirname(swcrcPath)); } } diff --git a/packages/js/src/utils/swc/get-swcrc-path.ts b/packages/js/src/utils/swc/get-swcrc-path.ts index cc4acdbb1b9c45..43cd059d32cde8 100644 --- a/packages/js/src/utils/swc/get-swcrc-path.ts +++ b/packages/js/src/utils/swc/get-swcrc-path.ts @@ -4,9 +4,14 @@ import { SwcExecutorOptions } from '../schema'; export function getSwcrcPath( options: SwcExecutorOptions, contextRoot: string, - projectRoot: string + projectRoot: string, + temp = false ) { - return options.swcrc - ? join(contextRoot, options.swcrc) - : join(contextRoot, projectRoot, '.swcrc'); + let swcrcPath = options.swcrc ?? join(projectRoot, '.swcrc'); + + if (temp) { + swcrcPath = join('tmp', swcrcPath.replace('.swcrc', '.generated.swcrc')); + } + + return join(contextRoot, swcrcPath); }