feat(@angular-devkit/architect): support accessing project metadata

This commit is contained in:
Charles Lyding 2019-09-18 10:38:46 -04:00 committed by vikerman
parent ab5b1909d6
commit 0d104c0aba
8 changed files with 66 additions and 0 deletions

View File

@ -15,6 +15,8 @@ export interface BuilderContext {
workspaceRoot: string; workspaceRoot: string;
addTeardown(teardown: () => (Promise<void> | void)): void; addTeardown(teardown: () => (Promise<void> | void)): void;
getBuilderNameForTarget(target: Target): Promise<string>; getBuilderNameForTarget(target: Target): Promise<string>;
getProjectMetadata(target: Target): Promise<json.JsonObject>;
getProjectMetadata(projectName: string): Promise<json.JsonObject>;
getTargetOptions(target: Target): Promise<json.JsonObject>; getTargetOptions(target: Target): Promise<json.JsonObject>;
reportProgress(current: number, total?: number, status?: string): void; reportProgress(current: number, total?: number, status?: string): void;
reportRunning(): void; reportRunning(): void;

View File

@ -8,6 +8,7 @@ export declare class TestingArchitectHost implements ArchitectHost {
getBuilderNameForTarget(target: Target): Promise<string | null>; getBuilderNameForTarget(target: Target): Promise<string | null>;
getCurrentDirectory(): Promise<string>; getCurrentDirectory(): Promise<string>;
getOptionsForTarget(target: Target): Promise<json.JsonObject | null>; getOptionsForTarget(target: Target): Promise<json.JsonObject | null>;
getProjectMetadata(target: Target | string): Promise<json.JsonObject | null>;
getWorkspaceRoot(): Promise<string>; getWorkspaceRoot(): Promise<string>;
loadBuilder(info: BuilderInfo): Promise<Builder | null>; loadBuilder(info: BuilderInfo): Promise<Builder | null>;
resolveBuilder(builderName: string): Promise<BuilderInfo | null>; resolveBuilder(builderName: string): Promise<BuilderInfo | null>;

View File

@ -113,6 +113,29 @@ export class WorkspaceNodeModulesArchitectHost implements ArchitectHost<NodeModu
}; };
} }
async getProjectMetadata(target: Target | string): Promise<json.JsonObject | null> {
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<Builder> { async loadBuilder(info: NodeModulesBuilderInfo): Promise<Builder> {
const builder = (await import(info.import)).default; const builder = (await import(info.import)).default;
if (builder[BuilderSymbol]) { if (builder[BuilderSymbol]) {

View File

@ -197,6 +197,9 @@ export interface BuilderContext {
*/ */
getTargetOptions(target: Target): Promise<json.JsonObject>; getTargetOptions(target: Target): Promise<json.JsonObject>;
getProjectMetadata(projectName: string): Promise<json.JsonObject>;
getProjectMetadata(target: Target): Promise<json.JsonObject>;
/** /**
* Resolves and return a builder name. The exact format of the name is up to the host, * 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 * so it should not be parsed to gather information (it's free form). This string can be

View File

@ -277,6 +277,30 @@ function _getTargetOptionsFactory(host: ArchitectHost) {
); );
} }
function _getProjectMetadataFactory(host: ArchitectHost) {
return experimental.jobs.createJobHandler<Target, json.JsonValue, json.JsonObject>(
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) { function _getBuilderNameForTargetFactory(host: ArchitectHost) {
return experimental.jobs.createJobHandler<Target, never, string>(async target => { return experimental.jobs.createJobHandler<Target, never, string>(async target => {
const builderName = await host.getBuilderNameForTarget(target); const builderName = await host.getBuilderNameForTarget(target);
@ -342,6 +366,7 @@ export class Architect {
privateArchitectJobRegistry.register(_getTargetOptionsFactory(_host)); privateArchitectJobRegistry.register(_getTargetOptionsFactory(_host));
privateArchitectJobRegistry.register(_getBuilderNameForTargetFactory(_host)); privateArchitectJobRegistry.register(_getBuilderNameForTargetFactory(_host));
privateArchitectJobRegistry.register(_validateOptionsFactory(_host, registry)); privateArchitectJobRegistry.register(_validateOptionsFactory(_host, registry));
privateArchitectJobRegistry.register(_getProjectMetadataFactory(_host));
const jobRegistry = new experimental.jobs.FallbackRegistry([ const jobRegistry = new experimental.jobs.FallbackRegistry([
new ArchitectTargetJobRegistry(_host, registry, this._jobCache, this._infoCache), new ArchitectTargetJobRegistry(_host, registry, this._jobCache, this._infoCache),

View File

@ -25,6 +25,7 @@ import { Builder, BuilderSymbol, BuilderVersionSymbol } from './internal';
import { scheduleByName, scheduleByTarget } from './schedule-by-name'; import { scheduleByName, scheduleByTarget } from './schedule-by-name';
// tslint:disable-next-line: no-big-function
export function createBuilder< export function createBuilder<
OptT extends json.JsonObject, OptT extends json.JsonObject,
OutT extends BuilderOutput = BuilderOutput, OutT extends BuilderOutput = BuilderOutput,
@ -144,6 +145,10 @@ export function createBuilder<
return scheduler.schedule<Target, json.JsonValue, json.JsonObject>( return scheduler.schedule<Target, json.JsonValue, json.JsonObject>(
'..getTargetOptions', target).output.toPromise(); '..getTargetOptions', target).output.toPromise();
}, },
async getProjectMetadata(target: Target | string) {
return scheduler.schedule<Target | string, json.JsonValue, json.JsonObject>(
'..getProjectMetadata', target).output.toPromise();
},
async getBuilderNameForTarget(target: Target) { async getBuilderNameForTarget(target: Target) {
return scheduler.schedule<Target, json.JsonValue, string>( return scheduler.schedule<Target, json.JsonValue, string>(
'..getBuilderNameForTarget', '..getBuilderNameForTarget',

View File

@ -78,4 +78,7 @@ export interface ArchitectHost<BuilderInfoT extends BuilderInfo = BuilderInfo> {
getWorkspaceRoot(): Promise<string>; getWorkspaceRoot(): Promise<string>;
getOptionsForTarget(target: Target): Promise<json.JsonObject | null>; getOptionsForTarget(target: Target): Promise<json.JsonObject | null>;
getProjectMetadata(projectName: string): Promise<json.JsonObject | null>;
getProjectMetadata(target: Target): Promise<json.JsonObject | null>;
} }

View File

@ -104,6 +104,10 @@ export class TestingArchitectHost implements ArchitectHost {
return maybeTarget.options; return maybeTarget.options;
} }
async getProjectMetadata(target: Target | string): Promise<json.JsonObject | null> {
return this._backendHost && this._backendHost.getProjectMetadata(target as string);
}
async loadBuilder(info: BuilderInfo): Promise<Builder | null> { async loadBuilder(info: BuilderInfo): Promise<Builder | null> {
return this._builderImportMap.get(info.builderName) return this._builderImportMap.get(info.builderName)
|| (this._backendHost && this._backendHost.loadBuilder(info)); || (this._backendHost && this._backendHost.loadBuilder(info));