Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): misc encapuslated mode fixes #15075

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions e2e/nx-misc/src/encapsulated.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
checkFilesExist,
cleanupProject,
getPublishedVersion,
uniq,
} from '@nrwl/e2e/utils';

describe('encapsulated nx', () => {
Expand Down Expand Up @@ -69,6 +70,18 @@ describe('encapsulated nx', () => {
new RegExp(`nx.*:.*${getPublishedVersion()}`)
);
});

it('should work with basic generators', () => {
updateJson<NxJsonConfiguration>('nx.json', (j) => {
j.installation.plugins ??= {};
j.installation.plugins['@nrwl/workspace'] = getPublishedVersion();
return j;
});
expect(() =>
runEncapsulatedNx(`g npm-package ${uniq('pkg')}`)
).not.toThrow();
expect(() => checkFilesExist());
});
});

function assertNoRootPackages() {
Expand Down
7 changes: 2 additions & 5 deletions packages/nx/src/command-line/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { getLocalWorkspacePlugins } from '../utils/plugins/local-plugins';
import { printHelp } from '../utils/print-help';
import { workspaceRoot } from '../utils/workspace-root';
import { NxJsonConfiguration } from '../config/nx-json';
import { findInstalledPlugins } from '../utils/plugins/installed-plugins';

export interface GenerateOptions {
collectionName: string;
Expand Down Expand Up @@ -50,14 +51,10 @@ async function promptForCollection(
interactive: boolean,
projectsConfiguration: ProjectsConfigurations
): Promise<string> {
const packageJson = readJsonFile(`${workspaceRoot}/package.json`);
const localPlugins = getLocalWorkspacePlugins(projectsConfiguration);

const installedCollections = Array.from(
new Set([
...Object.keys(packageJson.dependencies || {}),
...Object.keys(packageJson.devDependencies || {}),
])
new Set(findInstalledPlugins().map((x) => x.name))
);

const choicesMap = new Set<string>();
Expand Down
6 changes: 5 additions & 1 deletion packages/nx/src/command-line/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { directoryExists, readJsonFile } from '../utils/fileutils';
import { PackageJson } from '../utils/package-json';
import * as parser from 'yargs-parser';
import { generateEncapsulatedNxSetup } from '../nx-init/encapsulated/add-nx-scripts';
import { prerelease } from 'semver';

export async function initHandler() {
const args = process.argv.slice(2).join(' ');
Expand All @@ -16,7 +17,10 @@ export async function initHandler() {
},
}) as any as { encapsulated: boolean };

const version = process.env.NX_VERSION ?? 'latest';
const version =
process.env.NX_VERSION ?? prerelease(require('../../package.json').version)
? 'next'
: 'latest';
if (process.env.NX_VERSION) {
console.log(`Using version ${process.env.NX_VERSION}`);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/nx/src/command-line/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { output } from '../utils/output';
import {
fetchCommunityPlugins,
fetchCorePlugins,
getInstalledPluginsFromPackageJson,
getInstalledPluginsAndCapabilities,
listCommunityPlugins,
listCorePlugins,
listInstalledPlugins,
Expand Down Expand Up @@ -49,7 +49,7 @@ export async function listHandler(args: ListArgs): Promise<void> {
const localPlugins = getLocalWorkspacePlugins(
readProjectsConfigurationFromProjectGraph(projectGraph)
);
const installedPlugins = getInstalledPluginsFromPackageJson(
const installedPlugins = getInstalledPluginsAndCapabilities(
workspaceRoot,
corePlugins,
communityPlugins
Expand Down
12 changes: 6 additions & 6 deletions packages/nx/src/command-line/report.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('report', () => {
);
const plugins = findInstalledCommunityPlugins();
expect(plugins).toEqual([
expect.objectContaining({ package: 'plugin-two', version: '2.0.0' }),
expect.objectContaining({ name: 'plugin-two', version: '2.0.0' }),
]);
});

Expand Down Expand Up @@ -112,8 +112,8 @@ describe('report', () => {
);
const plugins = findInstalledCommunityPlugins();
expect(plugins).toEqual([
expect.objectContaining({ package: 'plugin-one', version: '1.0.0' }),
expect.objectContaining({ package: 'plugin-two', version: '2.0.0' }),
expect.objectContaining({ name: 'plugin-one', version: '1.0.0' }),
expect.objectContaining({ name: 'plugin-two', version: '2.0.0' }),
]);
});

Expand Down Expand Up @@ -152,8 +152,8 @@ describe('report', () => {
const plugins = findInstalledCommunityPlugins();
expect(plugins).toEqual(
expect.arrayContaining([
expect.objectContaining({ package: 'plugin-one', version: '1.0.0' }),
expect.objectContaining({ package: 'plugin-two', version: '2.0.0' }),
expect.objectContaining({ name: 'plugin-one', version: '1.0.0' }),
expect.objectContaining({ name: 'plugin-two', version: '2.0.0' }),
])
);
});
Expand Down Expand Up @@ -189,7 +189,7 @@ describe('report', () => {
},
})
);
const plugins = findInstalledCommunityPlugins().map((x) => x.package);
const plugins = findInstalledCommunityPlugins().map((x) => x.name);
expect(plugins).not.toContain('other-package');
});
});
Expand Down
81 changes: 13 additions & 68 deletions packages/nx/src/command-line/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from '../project-graph/project-graph';
import { gt, valid } from 'semver';
import { NxJsonConfiguration } from '../config/nx-json';
import { findInstalledPlugins } from '../utils/plugins/installed-plugins';

const nxPackageJson = readJsonFile<typeof import('../../package.json')>(
join(__dirname, '../../package.json')
Expand Down Expand Up @@ -79,11 +80,11 @@ export async function reportHandler() {

if (communityPlugins.length) {
bodyLines.push(LINE_SEPARATOR);
padding = Math.max(...communityPlugins.map((x) => x.package.length)) + 1;
padding = Math.max(...communityPlugins.map((x) => x.name.length)) + 1;
bodyLines.push('Community plugins:');
communityPlugins.forEach((p) => {
bodyLines.push(
`${chalk.green(p.package.padEnd(padding))}: ${chalk.bold(p.version)}`
`${chalk.green(p.name.padEnd(padding))}: ${chalk.bold(p.version)}`
);
});
}
Expand Down Expand Up @@ -129,9 +130,7 @@ export interface ReportData {
pm: PackageManager;
pmVersion: string;
localPlugins: string[];
communityPlugins: (PackageJson & {
package: string;
})[];
communityPlugins: PackageJson[];
packageVersionsWeCareAbout: {
package: string;
version: string;
Expand Down Expand Up @@ -249,47 +248,15 @@ export function findMisalignedPackagesForPackage(
: undefined;
}

export function findInstalledCommunityPlugins(): (PackageJson & {
package: string;
})[] {
const packageJsonDeps = getDependenciesFromPackageJson();
const nxJsonDeps = getDependenciesFromNxJson();
const deps = packageJsonDeps.concat(nxJsonDeps);
return deps.reduce(
(arr: any[], nextDep: string): { project: string; version: string }[] => {
if (
patternsWeIgnoreInCommunityReport.some((pattern) =>
typeof pattern === 'string'
? pattern === nextDep
: pattern.test(nextDep)
)
) {
return arr;
}
try {
const depPackageJson: Partial<PackageJson> =
readPackageJson(nextDep) || {};
if (
[
'ng-update',
'nx-migrations',
'schematics',
'generators',
'builders',
'executors',
].some((field) => field in depPackageJson)
) {
arr.push({ package: nextDep, ...depPackageJson });
return arr;
} else {
return arr;
}
} catch {
console.warn(`Error parsing packageJson for ${nextDep}`);
return arr;
}
},
[]
export function findInstalledCommunityPlugins(): PackageJson[] {
const installedPlugins = findInstalledPlugins();
return installedPlugins.filter(
(dep) =>
!patternsWeIgnoreInCommunityReport.some((pattern) =>
typeof pattern === 'string'
? pattern === dep.name
: pattern.test(dep.name)
)
);
}
export function findInstalledPackagesWeCareAbout() {
Expand All @@ -301,25 +268,3 @@ export function findInstalledPackagesWeCareAbout() {
return acc;
}, [] as { package: string; version: string }[]);
}

function getDependenciesFromPackageJson(
packageJsonPath = 'package.json'
): string[] {
try {
const { dependencies, devDependencies } = readJsonFile(
join(workspaceRoot, packageJsonPath)
);
return Object.keys({ ...dependencies, ...devDependencies });
} catch {}
return [];
}

function getDependenciesFromNxJson(): string[] {
const { installation } = readJsonFile<NxJsonConfiguration>(
join(workspaceRoot, 'nx.json')
);
if (!installation) {
return [];
}
return ['nx', ...Object.keys(installation.plugins || {})];
}
32 changes: 14 additions & 18 deletions packages/nx/src/nx-init/encapsulated/add-nx-scripts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { execSync } from 'child_process';
import { readFileSync, constants as FsConstants } from 'fs';
import { stripIndent } from 'nx/src/utils/logger';
import * as path from 'path';
import { valid } from 'semver';
import { NxJsonConfiguration } from '../../config/nx-json';
Expand All @@ -20,22 +19,18 @@ const NODE_MISSING_ERR =
const NPM_MISSING_ERR =
'Nx requires npm to be available. To install NodeJS and NPM, see: https://nodejs.org/en/download/ .';

const BATCH_SCRIPT_CONTENTS = stripIndent(
`set path_to_root=%~dp0
WHERE node >nul 2>nul
IF %ERRORLEVEL% NEQ 0 (ECHO ${NODE_MISSING_ERR}; EXIT 1)
WHERE npm >nul 2>nul
IF %ERRORLEVEL% NEQ 0 (ECHO ${NPM_MISSING_ERR}; EXIT 1)
node ${path.win32.join('%path_to_root%', nxWrapperPath(path.win32))} %*`
);
const BATCH_SCRIPT_CONTENTS = `set path_to_root=%~dp0
WHERE node >nul 2>nul
IF %ERRORLEVEL% NEQ 0 (ECHO ${NODE_MISSING_ERR}; EXIT 1)
WHERE npm >nul 2>nul
IF %ERRORLEVEL% NEQ 0 (ECHO ${NPM_MISSING_ERR}; EXIT 1)
node ${path.win32.join('%path_to_root%', nxWrapperPath(path.win32))} %*`;

const SHELL_SCRIPT_CONTENTS = stripIndent(
`#!/bin/bash
command -v node >/dev/null 2>&1 || { echo >&2 "${NODE_MISSING_ERR}"; exit 1; }
command -v npm >/dev/null 2>&1 || { echo >&2 "${NPM_MISSING_ERR}"; exit 1; }
path_to_root=$(dirname $BASH_SOURCE)
node ${path.posix.join('$path_to_root', nxWrapperPath(path.posix))} $@`
);
const SHELL_SCRIPT_CONTENTS = `#!/bin/bash
command -v node >/dev/null 2>&1 || { echo >&2 "${NODE_MISSING_ERR}"; exit 1; }
command -v npm >/dev/null 2>&1 || { echo >&2 "${NPM_MISSING_ERR}"; exit 1; }
path_to_root=$(dirname $BASH_SOURCE)
node ${path.posix.join('$path_to_root', nxWrapperPath(path.posix))} $@`;

export function generateEncapsulatedNxSetup(version?: string) {
const host = new FsTree(process.cwd(), false);
Expand Down Expand Up @@ -81,9 +76,10 @@ export function updateGitIgnore(host: Tree) {
}

function getNodeScriptContents() {
// Read nxw.js, but remove any empty comments or comments that start with `INTERNAL: `
// Read nxw.js, but remove any empty comments or comments that start with `//#: `
// This removes the sourceMapUrl since it is invalid, as well as any internal comments.
return readFileSync(path.join(__dirname, 'nxw.js'), 'utf-8').replace(
/(\/\/ INTERNAL: .*)|(\/\/\w*)$/gm,
/(\/\/# .*)|(\/\/\w*)$/gm,
''
);
}
29 changes: 14 additions & 15 deletions packages/nx/src/nx-init/encapsulated/nxw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// that your local installation matches nx.json.
// See: https://nx.dev/more-concepts/encapsulated-nx-and-the-wrapper for more info.
//
// INTERNAL: The contents of this file are executed before packages are installed.
// INTERNAL: As such, we should not import anything from nx, other @nrwl packages,
// INTERNAL: or any other npm packages. Only import node builtins.
//# The contents of this file are executed before packages are installed.
//# As such, we should not import anything from nx, other @nrwl packages,
//# or any other npm packages. Only import node builtins.

const fs: typeof import('fs') = require('fs');
const path: typeof import('path') = require('path');
Expand All @@ -19,24 +19,23 @@ function matchesCurrentNxInstall(
nxJsonInstallation: NxJsonConfiguration['installation']
) {
try {
const currentInstallation: PackageJson = JSON.parse(
fs.readFileSync(installationPath, 'utf-8')
);
const currentInstallation: PackageJson = require(installationPath);
if (
currentInstallation.dependencies['nx'] !== nxJsonInstallation.version ||
JSON.parse(
fs.readFileSync(
path.join(installationPath, 'node_modules', 'nx', 'package.json'),
'utf-8'
)
).version !== nxJsonInstallation.version
currentInstallation.devDependencies['nx'] !==
nxJsonInstallation.version ||
require(path.join(
path.dirname(installationPath),
'node_modules',
'nx',
'package.json'
)).version !== nxJsonInstallation.version
) {
return false;
}
for (const [plugin, desiredVersion] of Object.entries(
nxJsonInstallation.plugins || {}
)) {
if (currentInstallation.dependencies[plugin] !== desiredVersion) {
if (currentInstallation.devDependencies[plugin] !== desiredVersion) {
return false;
}
}
Expand All @@ -58,7 +57,7 @@ function ensureUpToDateInstallation() {
let nxJson: NxJsonConfiguration;

try {
nxJson = JSON.parse(fs.readFileSync(nxJsonPath, 'utf-8'));
nxJson = require(nxJsonPath);
} catch {
console.error(
'[NX]: nx.json is required when running in encapsulated mode. Run `npx nx init --encapsulated` to restore it.'
Expand Down
2 changes: 1 addition & 1 deletion packages/nx/src/utils/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export {
} from './community-plugins';
export { fetchCorePlugins, listCorePlugins } from './core-plugins';
export {
getInstalledPluginsFromPackageJson,
getInstalledPluginsAndCapabilities,
listInstalledPlugins,
} from './installed-plugins';
export {
Expand Down
Loading