diff --git a/e2e/js/src/js-swc.test.ts b/e2e/js/src/js-swc.test.ts index b6ebb923d7..4918bd18ad 100644 --- a/e2e/js/src/js-swc.test.ts +++ b/e2e/js/src/js-swc.test.ts @@ -103,7 +103,7 @@ describe('js e2e', () => { const swcHelpersFromDist = readJson(`dist/libs/${lib}/package.json`) .peerDependencies['@swc/helpers']; - expect(satisfies(swcHelpersFromDist, swcHelpersFromRoot)).toBeTruthy(); + expect(swcHelpersFromDist).toEqual(swcHelpersFromRoot); updateJson(`libs/${lib}/.lib.swcrc`, (json) => { json.jsc.externalHelpers = false; diff --git a/e2e/js/src/js-tsc.test.ts b/e2e/js/src/js-tsc.test.ts index d35194024d..7831fed7ff 100644 --- a/e2e/js/src/js-tsc.test.ts +++ b/e2e/js/src/js-tsc.test.ts @@ -144,11 +144,8 @@ describe('js e2e', () => { const rootPackageJson = readJson(`package.json`); expect( - satisfies( - readJson(`dist/libs/${lib}/package.json`).peerDependencies.tslib, - rootPackageJson.dependencies.tslib - ) - ).toBeTruthy(); + readJson(`dist/libs/${lib}/package.json`).peerDependencies.tslib + ).toEqual(rootPackageJson.dependencies.tslib); updateJson(`libs/${lib}/tsconfig.json`, (json) => { json.compilerOptions = { ...json.compilerOptions, importHelpers: false }; diff --git a/e2e/node/src/node.test.ts b/e2e/node/src/node.test.ts index eb2ab9dede..9c7fbec893 100644 --- a/e2e/node/src/node.test.ts +++ b/e2e/node/src/node.test.ts @@ -11,6 +11,7 @@ import { packageInstall, promisifiedTreeKill, readFile, + readJson, runCLI, runCLIAsync, runCommandUntil, @@ -22,7 +23,6 @@ import { import { exec, execSync } from 'child_process'; import * as http from 'http'; import { getLockFileName } from 'nx/src/lock-file/lock-file'; -import { satisfies } from 'semver'; function getData(port, path = '/api'): Promise { return new Promise((resolve) => { @@ -246,6 +246,7 @@ describe('Build Node apps', () => { detectPackageManager(tmpProjPath()) )}` ); + const rootPackageJson = JSON.parse(readFile(`package.json`)); const packageJson = JSON.parse( readFile(`dist/apps/${nestapp}/package.json`) ); @@ -256,17 +257,22 @@ describe('Build Node apps', () => { version: '0.0.1', }) ); - expect( - satisfies(packageJson.dependencies['@nestjs/common'], '^9.0.0') - ).toBeTruthy(); - expect( - satisfies(packageJson.dependencies['@nestjs/core'], '^9.0.0') - ).toBeTruthy(); - expect( - satisfies(packageJson.dependencies['reflect-metadata'], '^0.1.13') - ).toBeTruthy(); - expect(satisfies(packageJson.dependencies['rxjs'], '^7.0.0')).toBeTruthy(); - expect(satisfies(packageJson.dependencies['tslib'], '^2.3.0')).toBeTruthy(); + + expect(packageJson.dependencies['@nestjs/common']).toEqual( + rootPackageJson.dependencies['@nestjs/common'] + ); + expect(packageJson.dependencies['@nestjs/core']).toEqual( + rootPackageJson.dependencies['@nestjs/core'] + ); + expect(packageJson.dependencies['reflect-metadata']).toEqual( + rootPackageJson.dependencies['reflect-metadata'] + ); + expect(packageJson.dependencies['rxjs']).toEqual( + rootPackageJson.dependencies['rxjs'] + ); + expect(packageJson.dependencies['tslib']).toEqual( + rootPackageJson.dependencies['tslib'] + ); const nodeapp = uniq('nodeapp'); runCLI(`generate @nrwl/node:app ${nodeapp} --bundler=webpack`); diff --git a/packages/nx/src/plugins/js/index.ts b/packages/nx/src/plugins/js/index.ts new file mode 100644 index 0000000000..eef503c009 --- /dev/null +++ b/packages/nx/src/plugins/js/index.ts @@ -0,0 +1,11 @@ +import { ProjectGraphProcessor } from '../../config/project-graph'; +import { ProjectGraphBuilder } from '../../project-graph/project-graph-builder'; +import { buildNpmPackageNodes } from './project-graph/build-nodes/build-npm-package-nodes'; + +export const processProjectGraph: ProjectGraphProcessor = (graph) => { + const builder = new ProjectGraphBuilder(graph); + + buildNpmPackageNodes(builder); + + return builder.getUpdatedProjectGraph(); +}; diff --git a/packages/nx/src/project-graph/build-nodes/npm-packages.ts b/packages/nx/src/plugins/js/project-graph/build-nodes/build-npm-package-nodes.ts similarity index 68% rename from packages/nx/src/project-graph/build-nodes/npm-packages.ts rename to packages/nx/src/plugins/js/project-graph/build-nodes/build-npm-package-nodes.ts index a0a50b1a25..2aeefe65d8 100644 --- a/packages/nx/src/project-graph/build-nodes/npm-packages.ts +++ b/packages/nx/src/plugins/js/project-graph/build-nodes/build-npm-package-nodes.ts @@ -1,7 +1,7 @@ +import { ProjectGraphBuilder } from '../../../../project-graph/project-graph-builder'; +import { readJsonFile } from '../../../../utils/fileutils'; import { join } from 'path'; -import { workspaceRoot } from '../../utils/workspace-root'; -import { readJsonFile } from '../../utils/fileutils'; -import { ProjectGraphBuilder } from '../project-graph-builder'; +import { workspaceRoot } from '../../../../utils/workspace-root'; export function buildNpmPackageNodes(builder: ProjectGraphBuilder) { const packageJson = readJsonFile(join(workspaceRoot, 'package.json')); diff --git a/packages/nx/src/project-graph/build-nodes/index.ts b/packages/nx/src/project-graph/build-nodes/index.ts index faff1905e7..b2e837b933 100644 --- a/packages/nx/src/project-graph/build-nodes/index.ts +++ b/packages/nx/src/project-graph/build-nodes/index.ts @@ -1,2 +1 @@ export * from './workspace-projects'; -export * from './npm-packages'; diff --git a/packages/nx/src/project-graph/build-project-graph.ts b/packages/nx/src/project-graph/build-project-graph.ts index 41e1acad20..ccf7f3dd75 100644 --- a/packages/nx/src/project-graph/build-project-graph.ts +++ b/packages/nx/src/project-graph/build-project-graph.ts @@ -12,10 +12,7 @@ import { writeCache, } from './nx-deps-cache'; import { buildImplicitProjectDependencies } from './build-dependencies'; -import { - buildNpmPackageNodes, - buildWorkspaceProjectNodes, -} from './build-nodes'; +import { buildWorkspaceProjectNodes } from './build-nodes'; import * as os from 'os'; import { buildExplicitTypescriptAndPackageJsonDependencies } from './build-dependencies/build-explicit-typescript-and-package-json-dependencies'; import { loadNxPlugins } from '../utils/nx-plugin'; @@ -175,13 +172,16 @@ async function buildProjectGraphUsingContext( performance.mark('build project graph:start'); const builder = new ProjectGraphBuilder(partialGraph); + builder.setVersion(projectGraphVersion); buildWorkspaceProjectNodes(ctx, builder, nxJson); - if (!partialGraph) { - buildNpmPackageNodes(builder); - } + const initProjectGraph = builder.getUpdatedProjectGraph(); + + const r = await updateProjectGraphWithPlugins(ctx, initProjectGraph); + + const updatedBuilder = new ProjectGraphBuilder(r); for (const proj of Object.keys(cachedFileData)) { - for (const f of builder.graph.nodes[proj].data.files) { + for (const f of updatedBuilder.graph.nodes[proj].data.files) { const cached = cachedFileData[proj][f.file]; if (cached && cached.deps) { f.deps = [...cached.deps]; @@ -192,14 +192,12 @@ async function buildProjectGraphUsingContext( await buildExplicitDependencies( jsPluginConfig(nxJson, packageJsonDeps), ctx, - builder + updatedBuilder ); - buildImplicitProjectDependencies(ctx, builder); - builder.setVersion(projectGraphVersion); - const initProjectGraph = builder.getUpdatedProjectGraph(); + buildImplicitProjectDependencies(ctx, updatedBuilder); - const r = await updateProjectGraphWithPlugins(ctx, initProjectGraph); + const finalGraph = updatedBuilder.getUpdatedProjectGraph(); performance.mark('build project graph:end'); performance.measure( @@ -208,7 +206,7 @@ async function buildProjectGraphUsingContext( 'build project graph:end' ); - return r; + return finalGraph; } function jsPluginConfig( diff --git a/packages/nx/src/utils/nx-plugin.ts b/packages/nx/src/utils/nx-plugin.ts index 33732753f2..523c66da70 100644 --- a/packages/nx/src/utils/nx-plugin.ts +++ b/packages/nx/src/utils/nx-plugin.ts @@ -47,49 +47,63 @@ export interface NxPlugin { // Allows loadNxPlugins to be called multiple times w/o // executing resolution mulitple times. let nxPluginCache: NxPlugin[] = null; + +function loadNxPlugin(moduleName: string, paths: string[], root: string) { + let pluginPath: string; + try { + pluginPath = require.resolve(moduleName, { + paths, + }); + } catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + const plugin = resolveLocalNxPlugin(moduleName, root); + if (plugin) { + const main = readPluginMainFromProjectConfiguration( + plugin.projectConfig + ); + pluginPath = main ? path.join(root, main) : plugin.path; + } else { + logger.error(`Plugin listed in \`nx.json\` not found: ${moduleName}`); + throw e; + } + } else { + throw e; + } + } + const packageJsonPath = path.join(pluginPath, 'package.json'); + const { name } = + !['.ts', '.js'].some((x) => x === path.extname(pluginPath)) && // Not trying to point to a ts or js file + existsSync(packageJsonPath) // plugin has a package.json + ? readJsonFile(packageJsonPath) // read name from package.json + : { name: path.basename(pluginPath) }; // use the name of the file we point to + const plugin = require(pluginPath) as NxPlugin; + plugin.name = name; + + return plugin; +} + export function loadNxPlugins( plugins?: string[], paths = [workspaceRoot], root = workspaceRoot ): NxPlugin[] { - return plugins?.length - ? nxPluginCache || - (nxPluginCache = plugins.map((moduleName) => { - let pluginPath: string; - try { - pluginPath = require.resolve(moduleName, { - paths, - }); - } catch (e) { - if (e.code === 'MODULE_NOT_FOUND') { - const plugin = resolveLocalNxPlugin(moduleName, root); - if (plugin) { - const main = readPluginMainFromProjectConfiguration( - plugin.projectConfig - ); - pluginPath = main ? path.join(root, main) : plugin.path; - } else { - logger.error( - `Plugin listed in \`nx.json\` not found: ${moduleName}` - ); - throw e; - } - } else { - throw e; - } - } - const packageJsonPath = path.join(pluginPath, 'package.json'); - const { name } = - !['.ts', '.js'].some((x) => x === path.extname(pluginPath)) && // Not trying to point to a ts or js file - existsSync(packageJsonPath) // plugin has a package.json - ? readJsonFile(packageJsonPath) // read name from package.json - : { name: path.basename(pluginPath) }; // use the name of the file we point to - const plugin = require(pluginPath) as NxPlugin; - plugin.name = name; + const result: NxPlugin[] = []; - return plugin; - })) - : []; + // TODO: This should be specified in nx.json + // Temporarily load js as if it were a plugin which is built into nx + // In the future, this will be optional and need to be specified in nx.json + const jsPlugin = require('../plugins/js'); + jsPlugin.name = 'index'; + result.push(jsPlugin as NxPlugin); + + plugins ??= []; + if (!nxPluginCache) { + nxPluginCache = plugins.map((moduleName) => + loadNxPlugin(moduleName, paths, root) + ); + } + + return result.concat(nxPluginCache); } export function mergePluginTargetsWithNxTargets(