diff --git a/etc/api/angular_devkit/architect/src/index.d.ts b/etc/api/angular_devkit/architect/src/index.d.ts index 1d7e5cb3e9..c25da032ea 100644 --- a/etc/api/angular_devkit/architect/src/index.d.ts +++ b/etc/api/angular_devkit/architect/src/index.d.ts @@ -15,6 +15,8 @@ export interface BuilderContext { workspaceRoot: string; addTeardown(teardown: () => (Promise | void)): void; getBuilderNameForTarget(target: Target): Promise; + getProjectMetadata(target: Target): Promise; + getProjectMetadata(projectName: string): Promise; getTargetOptions(target: Target): Promise; reportProgress(current: number, total?: number, status?: string): void; reportRunning(): void; diff --git a/etc/api/angular_devkit/architect/testing/index.d.ts b/etc/api/angular_devkit/architect/testing/index.d.ts index ccd2f03ff0..c531a3dfb5 100644 --- a/etc/api/angular_devkit/architect/testing/index.d.ts +++ b/etc/api/angular_devkit/architect/testing/index.d.ts @@ -8,6 +8,7 @@ export declare class TestingArchitectHost implements ArchitectHost { getBuilderNameForTarget(target: Target): Promise; getCurrentDirectory(): Promise; getOptionsForTarget(target: Target): Promise; + getProjectMetadata(target: Target | string): Promise; getWorkspaceRoot(): Promise; loadBuilder(info: BuilderInfo): Promise; resolveBuilder(builderName: string): Promise; diff --git a/packages/angular_devkit/architect/node/node-modules-architect-host.ts b/packages/angular_devkit/architect/node/node-modules-architect-host.ts index e19051e7b1..c78cd74064 100644 --- a/packages/angular_devkit/architect/node/node-modules-architect-host.ts +++ b/packages/angular_devkit/architect/node/node-modules-architect-host.ts @@ -113,6 +113,29 @@ export class WorkspaceNodeModulesArchitectHost implements ArchitectHost { + const projectName = typeof target === 'string' ? target : target.project; + + // NOTE: Remove conditional when deprecated support for experimental workspace API is removed. + if ('getProject' in this._workspace) { + return this._workspace.getProject(projectName) as unknown as json.JsonObject; + } else { + const projectDefinition = this._workspace.projects.get(projectName); + if (!projectDefinition) { + throw new Error('Project does not exist.'); + } + + const metadata = { + root: projectDefinition.root, + sourceRoot: projectDefinition.sourceRoot, + prefix: projectDefinition.prefix, + ...projectDefinition.extensions, + } as unknown as json.JsonObject; + + return metadata; + } + } + async loadBuilder(info: NodeModulesBuilderInfo): Promise { const builder = (await import(info.import)).default; if (builder[BuilderSymbol]) { diff --git a/packages/angular_devkit/architect/src/api.ts b/packages/angular_devkit/architect/src/api.ts index 35f7e4fd92..57cd289bbc 100644 --- a/packages/angular_devkit/architect/src/api.ts +++ b/packages/angular_devkit/architect/src/api.ts @@ -197,6 +197,9 @@ export interface BuilderContext { */ getTargetOptions(target: Target): Promise; + getProjectMetadata(projectName: string): Promise; + getProjectMetadata(target: Target): Promise; + /** * Resolves and return a builder name. The exact format of the name is up to the host, * so it should not be parsed to gather information (it's free form). This string can be diff --git a/packages/angular_devkit/architect/src/architect.ts b/packages/angular_devkit/architect/src/architect.ts index 62350f8fc0..7e8c18fd0d 100644 --- a/packages/angular_devkit/architect/src/architect.ts +++ b/packages/angular_devkit/architect/src/architect.ts @@ -277,6 +277,30 @@ function _getTargetOptionsFactory(host: ArchitectHost) { ); } +function _getProjectMetadataFactory(host: ArchitectHost) { + return experimental.jobs.createJobHandler( + target => { + return host.getProjectMetadata(target).then(options => { + if (options === null) { + throw new Error(`Invalid target: ${JSON.stringify(target)}.`); + } + + return options; + }); + }, + { + name: '..getProjectMetadata', + output: { type: 'object' }, + argument: { + oneOf: [ + { type: 'string' }, + inputSchema.properties.target, + ], + }, + }, + ); +} + function _getBuilderNameForTargetFactory(host: ArchitectHost) { return experimental.jobs.createJobHandler(async target => { const builderName = await host.getBuilderNameForTarget(target); @@ -342,6 +366,7 @@ export class Architect { privateArchitectJobRegistry.register(_getTargetOptionsFactory(_host)); privateArchitectJobRegistry.register(_getBuilderNameForTargetFactory(_host)); privateArchitectJobRegistry.register(_validateOptionsFactory(_host, registry)); + privateArchitectJobRegistry.register(_getProjectMetadataFactory(_host)); const jobRegistry = new experimental.jobs.FallbackRegistry([ new ArchitectTargetJobRegistry(_host, registry, this._jobCache, this._infoCache), diff --git a/packages/angular_devkit/architect/src/create-builder.ts b/packages/angular_devkit/architect/src/create-builder.ts index 9b03efd8b8..62b0ff2489 100644 --- a/packages/angular_devkit/architect/src/create-builder.ts +++ b/packages/angular_devkit/architect/src/create-builder.ts @@ -25,6 +25,7 @@ import { Builder, BuilderSymbol, BuilderVersionSymbol } from './internal'; import { scheduleByName, scheduleByTarget } from './schedule-by-name'; +// tslint:disable-next-line: no-big-function export function createBuilder< OptT extends json.JsonObject, OutT extends BuilderOutput = BuilderOutput, @@ -144,6 +145,10 @@ export function createBuilder< return scheduler.schedule( '..getTargetOptions', target).output.toPromise(); }, + async getProjectMetadata(target: Target | string) { + return scheduler.schedule( + '..getProjectMetadata', target).output.toPromise(); + }, async getBuilderNameForTarget(target: Target) { return scheduler.schedule( '..getBuilderNameForTarget', diff --git a/packages/angular_devkit/architect/src/internal.ts b/packages/angular_devkit/architect/src/internal.ts index 0ccf439926..deaf250471 100644 --- a/packages/angular_devkit/architect/src/internal.ts +++ b/packages/angular_devkit/architect/src/internal.ts @@ -78,4 +78,7 @@ export interface ArchitectHost { getWorkspaceRoot(): Promise; getOptionsForTarget(target: Target): Promise; + + getProjectMetadata(projectName: string): Promise; + getProjectMetadata(target: Target): Promise; } diff --git a/packages/angular_devkit/architect/testing/testing-architect-host.ts b/packages/angular_devkit/architect/testing/testing-architect-host.ts index 0599979241..c7d901f390 100644 --- a/packages/angular_devkit/architect/testing/testing-architect-host.ts +++ b/packages/angular_devkit/architect/testing/testing-architect-host.ts @@ -104,6 +104,10 @@ export class TestingArchitectHost implements ArchitectHost { return maybeTarget.options; } + async getProjectMetadata(target: Target | string): Promise { + return this._backendHost && this._backendHost.getProjectMetadata(target as string); + } + async loadBuilder(info: BuilderInfo): Promise { return this._builderImportMap.get(info.builderName) || (this._backendHost && this._backendHost.loadBuilder(info));