@@ -44,8 +44,10 @@ import {
4444} from '../generators/utils/project-configuration' ;
4545import {
4646 createProjectGraphAsync ,
47+ readCachedProjectGraph ,
4748 readProjectsConfigurationFromProjectGraph ,
4849} from '../project-graph/project-graph' ;
50+ import type { ProjectGraph } from '../config/project-graph' ;
4951import { readJsonFile } from '../utils/fileutils' ;
5052import { getNxRequirePaths } from '../utils/installation-directory' ;
5153import { parseJson } from '../utils/json' ;
@@ -76,6 +78,14 @@ import {
7678} from '../config/schema-utils' ;
7779import { resolveNxTokensInOptions } from '../project-graph/utils/project-configuration-utils' ;
7880
81+ function getProjectGraph ( ) : Promise < ProjectGraph > {
82+ try {
83+ return Promise . resolve ( readCachedProjectGraph ( ) ) ;
84+ } catch {
85+ return createProjectGraphAsync ( ) ;
86+ }
87+ }
88+
7989export async function createBuilderContext (
8090 builderInfo : {
8191 builderName : string ;
@@ -85,7 +95,10 @@ export async function createBuilderContext(
8595 context : ExecutorContext
8696) {
8797 require ( './compat' ) ;
88- const fsHost = new NxScopedHostForBuilders ( context . root ) ;
98+ const fsHost = new NxScopedHostForBuilders (
99+ context . root ,
100+ context . projectGraph
101+ ) ;
89102 // the top level import is not patched because it is imported before the
90103 // patching happens so we require it here to use the patched version below
91104 const { workspaces } = require ( '@angular-devkit/core' ) ;
@@ -213,12 +226,13 @@ export async function scheduleTarget(
213226 runOptions : any ;
214227 projects : Record < string , ProjectConfiguration > ;
215228 } ,
216- verbose : boolean
229+ verbose : boolean ,
230+ projectGraph : ProjectGraph
217231) : Promise < Observable < import ( '@angular-devkit/architect' ) . BuilderOutput > > {
218232 const { Architect } = require ( '@angular-devkit/architect' ) ;
219233
220234 const logger = getLogger ( verbose ) ;
221- const fsHost = new NxScopedHostForBuilders ( root ) ;
235+ const fsHost = new NxScopedHostForBuilders ( root , projectGraph ) ;
222236 const { workspace } = await workspaces . readWorkspace (
223237 'angular.json' ,
224238 workspaces . createWorkspaceHost ( fsHost )
@@ -456,7 +470,10 @@ async function runSchematic(
456470type AngularProjectConfiguration = ProjectConfiguration & { prefix ?: string } ;
457471
458472export class NxScopedHost extends virtualFs . ScopedHost < any > {
459- constructor ( private root : string ) {
473+ constructor (
474+ private root : string ,
475+ protected _projectGraph ?: ProjectGraph
476+ ) {
460477 super ( new NodeJsSyncHost ( ) , normalize ( root ) ) ;
461478 }
462479
@@ -466,7 +483,10 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
466483 isAngularPluginInstalled ( )
467484 ) {
468485 return this . readMergedWorkspaceConfiguration ( ) . pipe (
469- map ( ( r ) => stringToArrayBuffer ( JSON . stringify ( toOldFormat ( r ) ) ) )
486+ // structuredClone to avoid toOldFormat mutating shared graph objects
487+ map ( ( r ) =>
488+ stringToArrayBuffer ( JSON . stringify ( toOldFormat ( structuredClone ( r ) ) ) )
489+ )
470490 ) ;
471491 } else {
472492 return super . read ( path ) ;
@@ -475,7 +495,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
475495
476496 protected readMergedWorkspaceConfiguration ( ) {
477497 return zip (
478- from ( createProjectGraphAsync ( ) ) ,
498+ this . _projectGraph ? of ( this . _projectGraph ) : from ( getProjectGraph ( ) ) ,
479499 this . readExistingAngularJson ( ) ,
480500 this . readJson < NxJsonConfiguration > ( 'nx.json' )
481501 ) . pipe (
@@ -704,9 +724,13 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
704724 * the project graph to access the expanded targets.
705725 */
706726export class NxScopedHostForBuilders extends NxScopedHost {
727+ constructor ( root : string , projectGraph : ProjectGraph ) {
728+ super ( root , projectGraph ) ;
729+ }
730+
707731 protected readMergedWorkspaceConfiguration ( ) {
708732 return zip (
709- from ( createProjectGraphAsync ( ) ) ,
733+ of ( this . _projectGraph ) ,
710734 this . readExistingAngularJson ( ) ,
711735 this . readJson < NxJsonConfiguration > ( 'nx.json' )
712736 ) . pipe (
@@ -754,9 +778,10 @@ export function arrayBufferToString(buffer: any) {
754778export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost {
755779 constructor (
756780 root : string ,
757- private readonly host : Tree
781+ private readonly host : Tree ,
782+ projectGraph : ProjectGraph
758783 ) {
759- super ( root ) ;
784+ super ( root , projectGraph ) ;
760785 }
761786
762787 read ( path : Path ) : Observable < FileBuffer > {
@@ -867,7 +892,8 @@ export async function generate(
867892 root : string ,
868893 opts : GenerateOptions ,
869894 projects : Record < string , ProjectConfiguration > ,
870- verbose : boolean
895+ verbose : boolean ,
896+ projectGraph : ProjectGraph
871897) {
872898 const logger = getLogger ( verbose ) ;
873899 const fsHost = new NxScopeHostUsedForWrappedSchematics (
@@ -876,7 +902,8 @@ export async function generate(
876902 root ,
877903 verbose ,
878904 `ng-cli generator: ${ opts . collectionName } :${ opts . generatorName } `
879- )
905+ ) ,
906+ projectGraph
880907 ) ;
881908 const workflow = createWorkflow ( fsHost , root , opts , projects ) ;
882909 const collection = getCollection ( workflow , opts . collectionName ) ;
@@ -961,7 +988,8 @@ export async function runMigration(
961988 packageName : string ,
962989 migrationName : string ,
963990 projects : Record < string , ProjectConfiguration > ,
964- isVerbose : boolean
991+ isVerbose : boolean ,
992+ projectGraph : ProjectGraph
965993) {
966994 const logger = getLogger ( isVerbose ) ;
967995 const fsHost = new NxScopeHostUsedForWrappedSchematics (
@@ -970,7 +998,8 @@ export async function runMigration(
970998 root ,
971999 isVerbose ,
9721000 `ng-cli migration: ${ packageName } :${ migrationName } `
973- )
1001+ ) ,
1002+ projectGraph
9741003 ) ;
9751004 const workflow = createWorkflow ( fsHost , root , { } , projects ) ;
9761005 const collection = resolveMigrationsCollection ( packageName ) ;
@@ -1084,7 +1113,7 @@ export function wrapAngularDevkitSchematic(
10841113 host : Tree ,
10851114 generatorOptions : { [ k : string ] : any }
10861115 ) : Promise < GeneratorCallback > => {
1087- const graph = await createProjectGraphAsync ( ) ;
1116+ const graph = await getProjectGraph ( ) ;
10881117 const { projects } = readProjectsConfigurationFromProjectGraph ( graph ) ;
10891118
10901119 if (
@@ -1124,7 +1153,11 @@ export function wrapAngularDevkitSchematic(
11241153 }
11251154 } ;
11261155
1127- const fsHost = new NxScopeHostUsedForWrappedSchematics ( host . root , host ) ;
1156+ const fsHost = new NxScopeHostUsedForWrappedSchematics (
1157+ host . root ,
1158+ host ,
1159+ graph
1160+ ) ;
11281161
11291162 const logger = getLogger ( generatorOptions . verbose ) ;
11301163 const options = {
0 commit comments