diff --git a/packages/angular/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.spec.ts b/packages/angular/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.spec.ts index c505cddf4c..ccedbedbf4 100644 --- a/packages/angular/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.spec.ts +++ b/packages/angular/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.spec.ts @@ -1,6 +1,17 @@ +import { + ProjectConfiguration, + ProjectGraph, + Tree, + addProjectConfiguration, +} from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; 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'; import { @@ -18,19 +29,22 @@ describe('extractStandaloneConfigFromBootstrap', () => { it('should extract the config correctly from a standard main.ts file', async () => { // ARRANGE const tree = createTreeWithEmptyWorkspace(); - addProjectConfiguration(tree, 'app1', { - name: 'app1', - root: 'apps/app1', - sourceRoot: 'apps/app1/src', - projectType: 'application', - targets: { - build: { - options: { - main: 'apps/app1/src/main.ts', + addProject( + tree, + 'app1', + { + name: 'app1', + root: 'apps/app1', + sourceRoot: 'apps/app1/src', + projectType: 'application', + targets: { + build: { + options: { main: 'apps/app1/src/main.ts' }, }, }, }, - }); + ['npm:@angular/core'] + ); 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 () => { // ARRANGE const tree = createTreeWithEmptyWorkspace(); - addProjectConfiguration(tree, 'app1', { - name: 'app1', - root: 'apps/app1', - sourceRoot: 'apps/app1/src', - projectType: 'application', - targets: { - build: { - options: { - main: 'apps/app1/src/main.ts', + addProject( + tree, + 'app1', + { + name: 'app1', + root: 'apps/app1', + sourceRoot: 'apps/app1/src', + projectType: 'application', + 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/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); +} diff --git a/packages/angular/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.ts b/packages/angular/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.ts index ea0031415c..339bf85bd6 100644 --- a/packages/angular/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.ts +++ b/packages/angular/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.ts @@ -1,8 +1,9 @@ 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 { dirname, relative, resolve } from 'path'; import type { Identifier, Node, SourceFile, StringLiteral } from 'typescript'; +import { getProjectsFilteredByDependencies } from '../utils/projects'; let tsModule: typeof import('typescript'); let tsquery: typeof import('@phenomnomnominal/tsquery').tsquery; @@ -163,14 +164,16 @@ export default async function extractStandaloneConfig(tree: Tree) { tsquery = require('@phenomnomnominal/tsquery').tsquery; } - const projects = getProjects(tree); + const projects = await getProjectsFilteredByDependencies(tree, [ + 'npm:@angular/core', + ]); const BOOTSTRAP_APPLICATION_CALL_SELECTOR = 'CallExpression:has(Identifier[name=bootstrapApplication])'; const BOOTSTRAP_APPLICATION_CALL_CONFIG_SELECTOR = 'CallExpression:has(Identifier[name=bootstrapApplication]) > ObjectLiteralExpression'; - for (const [, project] of projects.entries()) { + for (const { project } of projects) { if (project.projectType !== 'application') { continue; } diff --git a/packages/angular/src/migrations/utils/projects.ts b/packages/angular/src/migrations/utils/projects.ts index 977c9399ec..8012c8465e 100644 --- a/packages/angular/src/migrations/utils/projects.ts +++ b/packages/angular/src/migrations/utils/projects.ts @@ -17,11 +17,10 @@ export async function getProjectsFilteredByDependencies( const projectGraph = await createProjectGraphAsync(); return Object.entries(projectGraph.dependencies) - .filter(([node, dep]) => - dep.some( - ({ target }) => - !projectGraph.externalNodes?.[node] && dependencies.includes(target) - ) + .filter( + ([node, deps]) => + !projectGraph.externalNodes?.[node] && + deps.some(({ target }) => dependencies.includes(target)) ) .map(([projectName]) => ({ project: readProjectConfiguration(tree, projectName),