Skip to content

Commit

Permalink
fix(js): js:node executor resolves main.js and build options correctly (
Browse files Browse the repository at this point in the history
#17884)

Co-authored-by: Katerina Skroumpelou <[email protected]>
  • Loading branch information
skrtheboss and mandarini authored Jul 5, 2023
1 parent 6d7ce43 commit 47d23c8
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 34 deletions.
119 changes: 119 additions & 0 deletions e2e/js/src/js-node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,123 @@ describe('js:node error handling', () => {
expect(output).toContain('Hello from my library!');
expect(output).toContain('This is an error');
}, 240_000);

it('should execute library compiled with rollup', () => {
const rollupLib = uniq('rolluplib');

runCLI(
`generate @nx/js:lib ${rollupLib} --bundler=rollup --no-interactive`
);

updateFile(`libs/${rollupLib}/src/index.ts`, () => {
return `
console.log('Hello from my library!');
`;
});

updateProjectConfig(rollupLib, (config) => {
config.targets['run-node'] = {
executor: '@nx/js:node',
options: {
buildTarget: `${rollupLib}:build`,
watch: false,
},
};
return config;
});

const output = runCLI(`run ${rollupLib}:run-node`);
expect(output).toContain('Hello from my library!');
}, 240_000);

it('should execute library compiled with tsc', () => {
const tscLib = uniq('tsclib');

runCLI(`generate @nx/js:lib ${tscLib} --bundler=tsc --no-interactive`);

updateFile(`libs/${tscLib}/src/index.ts`, () => {
return `
console.log('Hello from my tsc library!');
`;
});

updateProjectConfig(tscLib, (config) => {
config.targets['run-node'] = {
executor: '@nx/js:node',
options: {
buildTarget: `${tscLib}:build`,
watch: false,
},
};
return config;
});

const output = runCLI(`run ${tscLib}:run-node`);
expect(output).toContain('Hello from my tsc library!');
}, 240_000);

it('should execute library compiled with swc', () => {
const swcLib = uniq('swclib');

runCLI(`generate @nx/js:lib ${swcLib} --bundler=swc --no-interactive`);

updateFile(`libs/${swcLib}/src/index.ts`, () => {
return `
console.log('Hello from my swc library!');
`;
});

updateProjectConfig(swcLib, (config) => {
config.targets['run-node'] = {
executor: '@nx/js:node',
options: {
buildTarget: `${swcLib}:build`,
watch: false,
},
};
return config;
});

const output = runCLI(`run ${swcLib}:run-node`);
expect(output).toContain('Hello from my swc library!');
}, 240_000);

it('should execute webpack app', () => {
const webpackProject = uniq('webpackproject');

runCLI(
`generate @nx/node:application ${webpackProject} --bundler=webpack --no-interactive`
);

updateFile(`apps/${webpackProject}/src/main.ts`, () => {
return `
console.log('Hello from my webpack app!');
`;
});

updateProjectConfig(webpackProject, (config) => {
config.targets['run-node'] = {
executor: '@nx/js:node',
options: {
buildTarget: `${webpackProject}:build`,
watch: false,
},
};
config.targets.build = {
...config.targets.build,
configurations: {
development: {
outputPath: 'dist/packages/api-dev',
},
production: {
outputPath: 'dist/packages/api-prod',
},
},
};
return config;
});

const output = runCLI(`run ${webpackProject}:run-node`);
expect(output).toContain('Hello from my webpack app!');
}, 240_000);
});
70 changes: 48 additions & 22 deletions packages/js/src/executors/node/node.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@ import {
joinPathFragments,
logger,
parseTargetString,
ProjectGraphProjectNode,
readTargetOptions,
runExecutor,
} from '@nx/devkit';
import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable';
import { daemonClient } from 'nx/src/daemon/client/client';
import { randomUUID } from 'crypto';
import * as path from 'path';
import { join } from 'path';

import { InspectType, NodeExecutorOptions } from './schema';
import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable';
import { calculateProjectDependencies } from '../../utils/buildable-libs-utils';
import { killTree } from './lib/kill-tree';
import { fileExists } from 'nx/src/utils/fileutils';
import { getMainFileDirRelativeToProjectRoot } from '../../utils/get-main-file-dir';

interface ActiveTask {
id: string;
Expand Down Expand Up @@ -46,20 +49,22 @@ export async function* nodeExecutor(
context.projectGraph
);

let buildOptions: Record<string, any>;
if (project.data.targets[buildTarget.target]) {
buildOptions = {
...project.data.targets[buildTarget.target]?.options,
...options.buildTargetOptions,
};
} else {
if (!project.data.targets[buildTarget.target]) {
throw new Error(
`Cannot find build target ${chalk.bold(
options.buildTarget
)} for project ${chalk.bold(context.projectName)}`
);
}

const buildTargetExecutor =
project.data.targets[buildTarget.target]?.executor;

const buildOptions: Record<string, any> = {
...readTargetOptions(buildTarget, context),
...options.buildTargetOptions,
};

if (options.waitUntilTargets && options.waitUntilTargets.length > 0) {
const results = await runWaitUntilTargets(options, context);
for (const [i, result] of results.entries()) {
Expand All @@ -73,21 +78,13 @@ export async function* nodeExecutor(

// Re-map buildable workspace projects to their output directory.
const mappings = calculateResolveMappings(context, options);
let outputFileName =
buildOptions.outputFileName || `${path.parse(buildOptions.main).name}.js`;

if (!buildOptions.outputFileName) {
const matches = buildOptions.main.match(/^(?!.*src)(.*)\/([^/]*)$/); //ignore strings that contain src and split paths into [folders before main, main.ts]
if (matches) {
const [mainFolder, mainFileName] = matches.slice(1);
outputFileName = path.join(
mainFolder,
`${path.parse(mainFileName).name}.js`
);
}
}
const fileToRun = getFileToRun(
context,
project,
buildOptions,
buildTargetExecutor
);

const fileToRun = join(context.root, buildOptions.outputPath, outputFileName);
const tasks: ActiveTask[] = [];
let currentTask: ActiveTask = null;

Expand Down Expand Up @@ -318,6 +315,35 @@ function runWaitUntilTargets(
);
}

function getFileToRun(
context: ExecutorContext,
project: ProjectGraphProjectNode,
buildOptions: Record<string, any>,
buildTargetExecutor: string
): string {
let outputFileName = buildOptions.outputFileName;

if (!outputFileName) {
const fileName = `${path.parse(buildOptions.main).name}.js`;
if (
buildTargetExecutor === '@nx/js:tsc' ||
buildTargetExecutor === '@nx/js:swc'
) {
outputFileName = path.join(
getMainFileDirRelativeToProjectRoot(
buildOptions.main,
project.data.root
),
fileName
);
} else {
outputFileName = fileName;
}
}

return join(context.root, buildOptions.outputPath, outputFileName);
}

function fileToRunCorrectPath(fileToRun: string): string {
if (!fileExists(fileToRun)) {
const cjsFile = fileToRun.replace(/\.js$/, '.cjs');
Expand Down
3 changes: 1 addition & 2 deletions packages/js/src/executors/swc/swc.impl.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ExecutorContext, readJsonFile, writeJsonFile } from '@nx/devkit';
import { ExecutorContext } from '@nx/devkit';
import { assetGlobsToFiles, FileInputOutput } from '../../utils/assets/assets';
import { removeSync } from 'fs-extra';
import { dirname, join, relative, resolve } from 'path';
Expand All @@ -21,7 +21,6 @@ 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,
Expand Down
11 changes: 11 additions & 0 deletions packages/js/src/utils/get-main-file-dir.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { dirname, relative } from 'path';
import { normalizePath } from 'nx/src/utils/path';

export function getMainFileDirRelativeToProjectRoot(
main: string,
projectRoot: string
): string {
const mainFileDir = dirname(main);
const relativeDir = normalizePath(relative(projectRoot, mainFileDir));
return relativeDir === '' ? `./` : `./${relativeDir}/`;
}
12 changes: 2 additions & 10 deletions packages/js/src/utils/package-json/update-package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,22 @@ import {
ExecutorContext,
getOutputsForTargetAndConfiguration,
joinPathFragments,
normalizePath,
ProjectFileMap,
ProjectGraphProjectNode,
readJsonFile,
workspaceRoot,
writeJsonFile,
} from '@nx/devkit';
import { DependentBuildableProjectNode } from '../buildable-libs-utils';
import { basename, dirname, join, parse, relative } from 'path';
import { basename, join, parse } from 'path';
import { writeFileSync } from 'fs-extra';
import { isNpmProject } from 'nx/src/project-graph/operators';
import { fileExists } from 'nx/src/utils/fileutils';
import type { PackageJson } from 'nx/src/utils/package-json';
import { existsSync } from 'fs';
import { readProjectFileMapCache } from 'nx/src/project-graph/nx-deps-cache';

function getMainFileDirRelativeToProjectRoot(
main: string,
projectRoot: string
): string {
const mainFileDir = dirname(main);
const relativeDir = normalizePath(relative(projectRoot, mainFileDir));
return relativeDir === '' ? `./` : `./${relativeDir}/`;
}
import { getMainFileDirRelativeToProjectRoot } from '../get-main-file-dir';

export type SupportedFormat = 'cjs' | 'esm';

Expand Down

1 comment on commit 47d23c8

@vercel
Copy link

@vercel vercel bot commented on 47d23c8 Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-git-master-nrwl.vercel.app
nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx.dev

Please sign in to comment.