fix(angular): process only angular projects in migration (#17833)

This commit is contained in:
Leosvel Pérez Espinosa 2023-06-28 16:19:49 +01:00 committed by GitHub
parent 5e51bf4041
commit 20d45bbdf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 110 additions and 29 deletions

View File

@ -1,6 +1,17 @@
import {
ProjectConfiguration,
ProjectGraph,
Tree,
addProjectConfiguration,
} from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import extractStandaloneConfig from './extract-standalone-config-from-bootstrap'; import extractStandaloneConfig from './extract-standalone-config-from-bootstrap';
import { addProjectConfiguration } from '@nx/devkit';
let projectGraph: ProjectGraph;
jest.mock('@nx/devkit', () => ({
...jest.requireActual('@nx/devkit'),
createProjectGraphAsync: () => Promise.resolve(projectGraph),
}));
const TEST_MAIN_FILE = `import { bootstrapApplication } from '@angular/platform-browser'; const TEST_MAIN_FILE = `import { bootstrapApplication } from '@angular/platform-browser';
import { import {
@ -18,19 +29,22 @@ describe('extractStandaloneConfigFromBootstrap', () => {
it('should extract the config correctly from a standard main.ts file', async () => { it('should extract the config correctly from a standard main.ts file', async () => {
// ARRANGE // ARRANGE
const tree = createTreeWithEmptyWorkspace(); const tree = createTreeWithEmptyWorkspace();
addProjectConfiguration(tree, 'app1', { addProject(
name: 'app1', tree,
root: 'apps/app1', 'app1',
sourceRoot: 'apps/app1/src', {
projectType: 'application', name: 'app1',
targets: { root: 'apps/app1',
build: { sourceRoot: 'apps/app1/src',
options: { projectType: 'application',
main: 'apps/app1/src/main.ts', targets: {
build: {
options: { main: 'apps/app1/src/main.ts' },
}, },
}, },
}, },
}); ['npm:@angular/core']
);
tree.write('apps/app1/src/main.ts', TEST_MAIN_FILE); tree.write('apps/app1/src/main.ts', TEST_MAIN_FILE);
@ -68,19 +82,22 @@ describe('extractStandaloneConfigFromBootstrap', () => {
it('should extract the config correctly when the main.ts imports bootstrap from bootstrap.ts file', async () => { it('should extract the config correctly when the main.ts imports bootstrap from bootstrap.ts file', async () => {
// ARRANGE // ARRANGE
const tree = createTreeWithEmptyWorkspace(); const tree = createTreeWithEmptyWorkspace();
addProjectConfiguration(tree, 'app1', { addProject(
name: 'app1', tree,
root: 'apps/app1', 'app1',
sourceRoot: 'apps/app1/src', {
projectType: 'application', name: 'app1',
targets: { root: 'apps/app1',
build: { sourceRoot: 'apps/app1/src',
options: { projectType: 'application',
main: 'apps/app1/src/main.ts', targets: {
build: {
options: { main: 'apps/app1/src/main.ts' },
}, },
}, },
}, },
}); ['npm:@angular/core']
);
tree.write('apps/app1/src/main.ts', `import('./bootstrap');`); tree.write('apps/app1/src/main.ts', `import('./bootstrap');`);
tree.write('apps/app1/src/bootstrap.ts', TEST_MAIN_FILE); tree.write('apps/app1/src/bootstrap.ts', TEST_MAIN_FILE);
@ -120,4 +137,66 @@ describe('extractStandaloneConfigFromBootstrap', () => {
" "
`); `);
}); });
it('should not throw with non-angular projects', async () => {
// ARRANGE
const tree = createTreeWithEmptyWorkspace();
addProject(
tree,
'app1',
{
name: 'app1',
projectType: 'application',
root: 'apps/app1',
sourceRoot: 'apps/app1',
targets: {
build: {
executor: '@nx-go/nx-go:build',
options: { main: 'apps/app1' },
},
},
},
[]
);
tree.write(
'apps/app1/main.go',
`package main
import "fmt"
func Hello(name string) string {
result := "Hello " + name
return result
}
func main() {
fmt.Println(Hello("app1"))
}`
);
// ACT && ASSERT
await expect(extractStandaloneConfig(tree)).resolves.not.toThrow();
});
}); });
function addProject(
tree: Tree,
projectName: string,
config: ProjectConfiguration,
dependencies: string[]
): void {
projectGraph = {
dependencies: {
[projectName]: dependencies.map((d) => ({
source: projectName,
target: d,
type: 'static',
})),
},
nodes: {
[projectName]: { data: config, name: projectName, type: 'app' },
},
};
addProjectConfiguration(tree, projectName, config);
}

View File

@ -1,8 +1,9 @@
import type { ProjectConfiguration, Tree } from '@nx/devkit'; import type { ProjectConfiguration, Tree } from '@nx/devkit';
import { formatFiles, getProjects, joinPathFragments } from '@nx/devkit'; import { formatFiles, joinPathFragments } from '@nx/devkit';
import { ensureTypescript } from '@nx/js/src/utils/typescript/ensure-typescript'; import { ensureTypescript } from '@nx/js/src/utils/typescript/ensure-typescript';
import { dirname, relative, resolve } from 'path'; import { dirname, relative, resolve } from 'path';
import type { Identifier, Node, SourceFile, StringLiteral } from 'typescript'; import type { Identifier, Node, SourceFile, StringLiteral } from 'typescript';
import { getProjectsFilteredByDependencies } from '../utils/projects';
let tsModule: typeof import('typescript'); let tsModule: typeof import('typescript');
let tsquery: typeof import('@phenomnomnominal/tsquery').tsquery; let tsquery: typeof import('@phenomnomnominal/tsquery').tsquery;
@ -163,14 +164,16 @@ export default async function extractStandaloneConfig(tree: Tree) {
tsquery = require('@phenomnomnominal/tsquery').tsquery; tsquery = require('@phenomnomnominal/tsquery').tsquery;
} }
const projects = getProjects(tree); const projects = await getProjectsFilteredByDependencies(tree, [
'npm:@angular/core',
]);
const BOOTSTRAP_APPLICATION_CALL_SELECTOR = const BOOTSTRAP_APPLICATION_CALL_SELECTOR =
'CallExpression:has(Identifier[name=bootstrapApplication])'; 'CallExpression:has(Identifier[name=bootstrapApplication])';
const BOOTSTRAP_APPLICATION_CALL_CONFIG_SELECTOR = const BOOTSTRAP_APPLICATION_CALL_CONFIG_SELECTOR =
'CallExpression:has(Identifier[name=bootstrapApplication]) > ObjectLiteralExpression'; 'CallExpression:has(Identifier[name=bootstrapApplication]) > ObjectLiteralExpression';
for (const [, project] of projects.entries()) { for (const { project } of projects) {
if (project.projectType !== 'application') { if (project.projectType !== 'application') {
continue; continue;
} }

View File

@ -17,11 +17,10 @@ export async function getProjectsFilteredByDependencies(
const projectGraph = await createProjectGraphAsync(); const projectGraph = await createProjectGraphAsync();
return Object.entries(projectGraph.dependencies) return Object.entries(projectGraph.dependencies)
.filter(([node, dep]) => .filter(
dep.some( ([node, deps]) =>
({ target }) => !projectGraph.externalNodes?.[node] &&
!projectGraph.externalNodes?.[node] && dependencies.includes(target) deps.some(({ target }) => dependencies.includes(target))
)
) )
.map(([projectName]) => ({ .map(([projectName]) => ({
project: readProjectConfiguration(tree, projectName), project: readProjectConfiguration(tree, projectName),