diff --git a/packages/nx/src/adapter/ngcli-adapter.ts b/packages/nx/src/adapter/ngcli-adapter.ts index 0b113d2a2ae99..0c3c976ca847a 100644 --- a/packages/nx/src/adapter/ngcli-adapter.ts +++ b/packages/nx/src/adapter/ngcli-adapter.ts @@ -12,10 +12,10 @@ import { import { createConsoleLogger, NodeJsSyncHost } from '@angular-devkit/core/node'; import { FileBuffer } from '@angular-devkit/core/src/virtual-fs/host/interface'; +// Importing @angular-devkit/architect here will cause issues importing this file without @angular-devkit/architect installed /* eslint-disable no-restricted-imports */ import type { Architect } from '@angular-devkit/architect'; -import { WorkspaceNodeModulesArchitectHost } from '@angular-devkit/architect/node'; -import { NodeModulesBuilderInfo } from '@angular-devkit/architect/node/node-modules-architect-host'; +import type { NodeModulesBuilderInfo } from '@angular-devkit/architect/node/node-modules-architect-host'; import * as chalk from 'chalk'; import { Stats } from 'fs'; @@ -52,123 +52,6 @@ import { } from '../config/misc-interfaces'; import { readPluginPackageJson } from '../utils/nx-plugin'; -class WrappedWorkspaceNodeModulesArchitectHost extends WorkspaceNodeModulesArchitectHost { - private workspaces = new Workspaces(this.root); - - constructor(private workspace, private root) { - super(workspace, root); - } - async resolveBuilder(builderStr: string): Promise { - const [packageName, builderName] = builderStr.split(':'); - - const { executorsFilePath, executorConfig } = this.readExecutorsJson( - packageName, - builderName - ); - const builderInfo = this.readExecutor(packageName, builderName); - return { - name: builderStr, - builderName, - description: - readJsonFile(executorsFilePath).builders[builderName] - .description, - optionSchema: builderInfo.schema, - import: this.workspaces['resolveImplementation'].bind(this.workspaces)( - executorConfig.implementation, - dirname(executorsFilePath) - ), - }; - } - - private readExecutorsJson(nodeModule: string, builder: string) { - const { json: packageJson, path: packageJsonPath } = readPluginPackageJson( - nodeModule, - this.workspaces['resolvePaths'].bind(this.workspaces)() - ); - const executorsFile = packageJson.executors ?? packageJson.builders; - - if (!executorsFile) { - throw new Error( - `The "${nodeModule}" package does not support Nx executors or Angular Devkit Builders.` - ); - } - - const executorsFilePath = require.resolve( - join(dirname(packageJsonPath), executorsFile) - ); - const executorsJson = readJsonFile(executorsFilePath); - const executorConfig: { - implementation: string; - batchImplementation?: string; - schema: string; - hasher?: string; - } = executorsJson.builders?.[builder]; - if (!executorConfig) { - throw new Error( - `Cannot find builder '${builder}' in ${executorsFilePath}.` - ); - } - return { executorsFilePath, executorConfig, isNgCompat: true }; - } - - private readExecutor( - nodeModule: string, - executor: string - ): ExecutorConfig & { isNgCompat: boolean } { - try { - const { executorsFilePath, executorConfig, isNgCompat } = - this.readExecutorsJson(nodeModule, executor); - const executorsDir = dirname(executorsFilePath); - const schemaPath = this.workspaces['resolveSchema'].bind(this.workspaces)( - executorConfig.schema, - executorsDir - ); - const schema = normalizeExecutorSchema(readJsonFile(schemaPath)); - - const implementationFactory = this.getImplementationFactory( - executorConfig.implementation, - executorsDir - ); - - const batchImplementationFactory = executorConfig.batchImplementation - ? this.getImplementationFactory( - executorConfig.batchImplementation, - executorsDir - ) - : null; - - const hasherFactory = executorConfig.hasher - ? this.getImplementationFactory( - executorConfig.hasher, - executorsDir - ) - : null; - - return { - schema, - implementationFactory, - batchImplementationFactory, - hasherFactory, - isNgCompat, - }; - } catch (e) { - throw new Error( - `Unable to resolve ${nodeModule}:${executor}.\n${e.message}` - ); - } - } - - private getImplementationFactory( - implementation: string, - executorsDir: string - ): () => T { - return this.workspaces['getImplementationFactory'].bind(this.workspaces)( - implementation, - executorsDir - ); - } -} - export async function scheduleTarget( root: string, opts: { @@ -194,6 +77,127 @@ export async function scheduleTarget( // This happens when context.scheduleTarget is used to run a target using nx:run-commands return []; }); + + const AngularWorkspaceNodeModulesArchitectHost = + require('@angular-devkit/architect/node').WorkspaceNodeModulesArchitectHost; + + class WrappedWorkspaceNodeModulesArchitectHost extends AngularWorkspaceNodeModulesArchitectHost { + private workspaces = new Workspaces(this.root); + + constructor(private workspace, private root) { + super(workspace, root); + } + async resolveBuilder(builderStr: string): Promise { + const [packageName, builderName] = builderStr.split(':'); + + const { executorsFilePath, executorConfig } = this.readExecutorsJson( + packageName, + builderName + ); + const builderInfo = this.readExecutor(packageName, builderName); + return { + name: builderStr, + builderName, + description: + readJsonFile(executorsFilePath).builders[builderName] + .description, + optionSchema: builderInfo.schema, + import: this.workspaces['resolveImplementation'].bind(this.workspaces)( + executorConfig.implementation, + dirname(executorsFilePath) + ), + }; + } + + private readExecutorsJson(nodeModule: string, builder: string) { + const { json: packageJson, path: packageJsonPath } = + readPluginPackageJson( + nodeModule, + this.workspaces['resolvePaths'].bind(this.workspaces)() + ); + const executorsFile = packageJson.executors ?? packageJson.builders; + + if (!executorsFile) { + throw new Error( + `The "${nodeModule}" package does not support Nx executors or Angular Devkit Builders.` + ); + } + + const executorsFilePath = require.resolve( + join(dirname(packageJsonPath), executorsFile) + ); + const executorsJson = readJsonFile(executorsFilePath); + const executorConfig: { + implementation: string; + batchImplementation?: string; + schema: string; + hasher?: string; + } = executorsJson.builders?.[builder]; + if (!executorConfig) { + throw new Error( + `Cannot find builder '${builder}' in ${executorsFilePath}.` + ); + } + return { executorsFilePath, executorConfig, isNgCompat: true }; + } + + private readExecutor( + nodeModule: string, + executor: string + ): ExecutorConfig & { isNgCompat: boolean } { + try { + const { executorsFilePath, executorConfig, isNgCompat } = + this.readExecutorsJson(nodeModule, executor); + const executorsDir = dirname(executorsFilePath); + const schemaPath = this.workspaces['resolveSchema'].bind( + this.workspaces + )(executorConfig.schema, executorsDir); + const schema = normalizeExecutorSchema(readJsonFile(schemaPath)); + + const implementationFactory = this.getImplementationFactory( + executorConfig.implementation, + executorsDir + ); + + const batchImplementationFactory = executorConfig.batchImplementation + ? this.getImplementationFactory( + executorConfig.batchImplementation, + executorsDir + ) + : null; + + const hasherFactory = executorConfig.hasher + ? this.getImplementationFactory( + executorConfig.hasher, + executorsDir + ) + : null; + + return { + schema, + implementationFactory, + batchImplementationFactory, + hasherFactory, + isNgCompat, + }; + } catch (e) { + throw new Error( + `Unable to resolve ${nodeModule}:${executor}.\n${e.message}` + ); + } + } + + private getImplementationFactory( + implementation: string, + executorsDir: string + ): () => T { + return this.workspaces['getImplementationFactory'].bind(this.workspaces)( + implementation, + executorsDir + ); + } + } + const architectHost = new WrappedWorkspaceNodeModulesArchitectHost( workspace, root