Skip to content

Commit

Permalink
fix(angular): init also installs plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
jaysoo committed Sep 13, 2024
1 parent 036e179 commit 3cd2975
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 55 deletions.
22 changes: 21 additions & 1 deletion packages/angular/src/generators/init/init.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import {
addDependenciesToPackageJson,
createProjectGraphAsync,
ensurePackage,
formatFiles,
type GeneratorCallback,
logger,
readNxJson,
type GeneratorCallback,
type Tree,
} from '@nx/devkit';
import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
import { getInstalledPackageVersion, versions } from '../utils/version-utils';
import { createNodesV2 } from '../../plugins/plugin';
import { Schema } from './schema';

export async function angularInitGenerator(
Expand All @@ -17,6 +20,23 @@ export async function angularInitGenerator(
ignoreAngularCacheDirectory(tree);
const installTask = installAngularDevkitCoreIfMissing(tree, options);

// For Angular inference plugin, we only want it during import since our
// generators do not use `angular.json`, and `nx init` should split
// `angular.json` into multiple `project.json` files -- as this is preferred
// by most folks we've talked to.
options.addPlugin ??= process.env.NX_RUNNING_NX_IMPORT === 'true';

if (options.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
'@nx/angular/plugin',
createNodesV2,
{},
options.updatePackageScripts
);
}

if (!options.skipFormat) {
await formatFiles(tree);
}
Expand Down
3 changes: 3 additions & 0 deletions packages/angular/src/generators/init/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ export interface Schema {
skipInstall?: boolean;
skipPackageJson?: boolean;
keepExistingVersions?: boolean;
/* internal */
addPlugin?: boolean;
updatePackageScripts?: boolean;
}
30 changes: 15 additions & 15 deletions packages/angular/src/plugins/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe('@nx/angular/plugin', () => {
"targets": {
"build": {
"cache": true,
"command": "ng run my-app:build",
"command": "ng build",
"dependsOn": [
"^build",
],
Expand Down Expand Up @@ -131,7 +131,7 @@ describe('@nx/angular/plugin', () => {
],
},
"serve": {
"command": "ng run my-app:serve",
"command": "ng serve",
"configurations": {
"production": {
"command": "ng run my-app:serve:production",
Expand All @@ -157,7 +157,7 @@ describe('@nx/angular/plugin', () => {
},
"test": {
"cache": true,
"command": "ng run my-app:test",
"command": "ng test",
"inputs": [
"default",
"^production",
Expand Down Expand Up @@ -197,7 +197,7 @@ describe('@nx/angular/plugin', () => {
"targets": {
"build": {
"cache": true,
"command": "ng run my-lib:build",
"command": "ng build",
"dependsOn": [
"^build",
],
Expand Down Expand Up @@ -233,7 +233,7 @@ describe('@nx/angular/plugin', () => {
},
"test": {
"cache": true,
"command": "ng run my-lib:test",
"command": "ng test",
"inputs": [
"default",
"^production",
Expand Down Expand Up @@ -394,7 +394,7 @@ describe('@nx/angular/plugin', () => {
"targets": {
"build": {
"cache": true,
"command": "ng run org1-app1:build",
"command": "ng build",
"dependsOn": [
"^build",
],
Expand Down Expand Up @@ -429,7 +429,7 @@ describe('@nx/angular/plugin', () => {
],
},
"serve": {
"command": "ng run org1-app1:serve",
"command": "ng serve",
"configurations": {
"production": {
"command": "ng run org1-app1:serve:production",
Expand All @@ -455,7 +455,7 @@ describe('@nx/angular/plugin', () => {
},
"test": {
"cache": true,
"command": "ng run org1-app1:test",
"command": "ng test",
"inputs": [
"default",
"^production",
Expand Down Expand Up @@ -495,7 +495,7 @@ describe('@nx/angular/plugin', () => {
"targets": {
"build": {
"cache": true,
"command": "ng run org1-lib1:build",
"command": "ng build",
"dependsOn": [
"^build",
],
Expand Down Expand Up @@ -531,7 +531,7 @@ describe('@nx/angular/plugin', () => {
},
"test": {
"cache": true,
"command": "ng run org1-lib1:test",
"command": "ng test",
"inputs": [
"default",
"^production",
Expand Down Expand Up @@ -578,7 +578,7 @@ describe('@nx/angular/plugin', () => {
"targets": {
"build": {
"cache": true,
"command": "ng run org2-app1:build",
"command": "ng build",
"dependsOn": [
"^build",
],
Expand Down Expand Up @@ -613,7 +613,7 @@ describe('@nx/angular/plugin', () => {
],
},
"serve": {
"command": "ng run org2-app1:serve",
"command": "ng serve",
"configurations": {
"production": {
"command": "ng run org2-app1:serve:production",
Expand All @@ -639,7 +639,7 @@ describe('@nx/angular/plugin', () => {
},
"test": {
"cache": true,
"command": "ng run org2-app1:test",
"command": "ng test",
"inputs": [
"default",
"^production",
Expand Down Expand Up @@ -679,7 +679,7 @@ describe('@nx/angular/plugin', () => {
"targets": {
"build": {
"cache": true,
"command": "ng run org2-lib1:build",
"command": "ng build",
"dependsOn": [
"^build",
],
Expand Down Expand Up @@ -715,7 +715,7 @@ describe('@nx/angular/plugin', () => {
},
"test": {
"cache": true,
"command": "ng run org2-lib1:test",
"command": "ng test",
"inputs": [
"default",
"^production",
Expand Down
13 changes: 12 additions & 1 deletion packages/angular/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,18 @@ async function buildAngularProjects(
const externalDependencies = ['@angular/cli'];

targets[targetName] = {
command: `ng run ${projectName}:${targetName}`,
command:
// For targets that are also Angular CLI commands, infer the simplified form.
// Otherwise, use `ng run` to support non-command targets so that they will run.
targetName === 'build' ||
targetName === 'deploy' ||
targetName === 'extract-i18n' ||
targetName === 'e2e' ||
targetName === 'lint' ||
targetName === 'serve' ||
targetName === 'test'
? `ng ${targetName}`
: `ng run ${projectName}:${targetName}`,
options: { cwd: angularWorkspaceRoot },
metadata: {
technologies: ['angular'],
Expand Down
89 changes: 56 additions & 33 deletions packages/devkit/src/utils/add-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,21 +104,64 @@ async function _addPluginInternal<PluginOptions>(

let pluginOptions: PluginOptions;
let projConfigs: ConfigurationResult;
const combinations = generateCombinations(options);
optionsLoop: for (const _pluginOptions of combinations) {
pluginOptions = _pluginOptions as PluginOptions;

nxJson.plugins ??= [];
if (
nxJson.plugins.some((p) =>
typeof p === 'string'
? p === pluginName
: p.plugin === pluginName && !p.include
)
) {
// Plugin has already been added
return;
if (Object.keys(options).length > 0) {
const combinations = generateCombinations(options);
optionsLoop: for (const _pluginOptions of combinations) {
pluginOptions = _pluginOptions as PluginOptions;

nxJson.plugins ??= [];
if (
nxJson.plugins.some((p) =>
typeof p === 'string'
? p === pluginName
: p.plugin === pluginName && !p.include
)
) {
// Plugin has already been added
return;
}
global.NX_GRAPH_CREATION = true;
try {
projConfigs = await retrieveProjectConfigurations(
[pluginFactory(pluginOptions)],
tree.root,
nxJson
);
} catch (e) {
// Errors are okay for this because we're only running 1 plugin
if (e instanceof ProjectConfigurationsError) {
projConfigs = e.partialProjectConfigurationsResult;
} else {
throw e;
}
}
global.NX_GRAPH_CREATION = false;

for (const projConfig of Object.values(projConfigs.projects)) {
const node = graphNodes.find(
(node) => node.data.root === projConfig.root
);

if (!node) {
continue;
}

for (const targetName in projConfig.targets) {
if (node.data.targets[targetName]) {
// Conflicting Target Name, check the next one
pluginOptions = null;
continue optionsLoop;
}
}
}

break;
}
} else {
// If the plugin does not take in options, we add the plugin with empty options.
nxJson.plugins ??= [];
pluginOptions = {} as unknown as PluginOptions;
global.NX_GRAPH_CREATION = true;
try {
projConfigs = await retrieveProjectConfigurations(
Expand All @@ -135,26 +178,6 @@ async function _addPluginInternal<PluginOptions>(
}
}
global.NX_GRAPH_CREATION = false;

for (const projConfig of Object.values(projConfigs.projects)) {
const node = graphNodes.find(
(node) => node.data.root === projConfig.root
);

if (!node) {
continue;
}

for (const targetName in projConfig.targets) {
if (node.data.targets[targetName]) {
// Conflicting Target Name, check the next one
pluginOptions = null;
continue optionsLoop;
}
}
}

break;
}

if (!pluginOptions) {
Expand Down
12 changes: 10 additions & 2 deletions packages/nx/src/command-line/import/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,15 @@ export interface ImportOptions {
}

export async function importHandler(options: ImportOptions) {
process.env.NX_RUNNING_NX_IMPORT = 'true';
let { sourceRemoteUrl, ref, source, destination } = options;
const destinationGitClient = new GitRepository(process.cwd());

if (await destinationGitClient.hasUncommittedChanges()) {
throw new Error(
`You have uncommitted changes in the destination repository. Commit or revert the changes and try again.`
);
}

output.log({
title:
Expand Down Expand Up @@ -174,7 +182,6 @@ export async function importHandler(options: ImportOptions) {
const absSource = join(sourceRepoPath, source);
const absDestination = join(process.cwd(), destination);

const destinationGitClient = new GitRepository(process.cwd());
await assertDestinationEmpty(destinationGitClient, absDestination);

const tempImportBranch = getTempImportBranch(ref);
Expand Down Expand Up @@ -245,7 +252,8 @@ export async function importHandler(options: ImportOptions) {

const { plugins, updatePackageScripts } = await detectPlugins(
nxJson,
options.interactive
options.interactive,
true
);

if (packageManager !== sourcePackageManager) {
Expand Down
13 changes: 10 additions & 3 deletions packages/nx/src/command-line/init/init-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export async function initHandler(options: InitArgs): Promise<void> {
});
}

const npmPackageToPluginMap: Record<string, string> = {
const npmPackageToPluginMap: Record<string, `@nx/${string}`> = {
// Generic JS tools
eslint: '@nx/eslint',
storybook: '@nx/storybook',
Expand All @@ -181,7 +181,8 @@ const npmPackageToPluginMap: Record<string, string> = {

export async function detectPlugins(
nxJson: NxJsonConfiguration,
interactive: boolean
interactive: boolean,
includeAngularCli?: boolean
): Promise<{
plugins: string[];
updatePackageScripts: boolean;
Expand Down Expand Up @@ -214,7 +215,13 @@ export async function detectPlugins(
...packageJson.devDependencies,
};

for (const [dep, plugin] of Object.entries(npmPackageToPluginMap)) {
const _npmPackageToPluginMap = {
...npmPackageToPluginMap,
};
if (includeAngularCli) {
_npmPackageToPluginMap['@angular/cli'] = '@nx/angular';
}
for (const [dep, plugin] of Object.entries(_npmPackageToPluginMap)) {
if (deps[dep]) {
detectedPlugins.add(plugin);
}
Expand Down
5 changes: 5 additions & 0 deletions packages/nx/src/utils/git-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export class GitRepository {
.trim();
}

async hasUncommittedChanges() {
const data = await this.execAsync(`git status --porcelain`);
return data.trim() !== '';
}

async addFetchRemote(remoteName: string, branch: string) {
return await this.execAsync(
`git config --add remote.${remoteName}.fetch "+refs/heads/${branch}:refs/remotes/${remoteName}/${branch}"`
Expand Down

0 comments on commit 3cd2975

Please sign in to comment.