feat(@angular-devkit/core): add factories for workspace

It makes it easier instead of always copy-pasting the same findUp code
to get the workspace file.
This commit is contained in:
Hans Larsen 2019-02-22 17:54:10 -08:00 committed by Hans
parent 02943eaf49
commit 041907d551
2 changed files with 77 additions and 8 deletions

View File

@ -1004,7 +1004,7 @@ export declare class Workspace {
readonly newProjectRoot: string | undefined;
readonly root: Path;
readonly version: number;
constructor(_root: Path, _host: virtualFs.Host<{}>);
constructor(_root: Path, _host: virtualFs.Host<{}>, registry?: schema.CoreSchemaRegistry);
getCli(): WorkspaceTool;
getDefaultProjectName(): string | null;
getProject(projectName: string): WorkspaceProject;
@ -1018,6 +1018,13 @@ export declare class Workspace {
loadWorkspaceFromHost(workspacePath: Path): Observable<this>;
loadWorkspaceFromJson(json: {}): Observable<this>;
validateAgainstSchema<T = {}>(contentJson: {}, schemaJson: JsonObject): Observable<T>;
protected static _workspaceFileNames: string[];
static findWorkspaceFile(host: virtualFs.Host<{}>, path: Path): Promise<Path | null>;
static fromPath(host: virtualFs.Host<{}>, path: Path, registry: schema.CoreSchemaRegistry): Promise<Workspace>;
}
export declare class WorkspaceFileNotFoundException extends BaseException {
constructor(path: Path);
}
export declare class WorkspaceNotYetLoadedException extends BaseException {

View File

@ -6,8 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
import { existsSync } from 'fs';
import * as path from 'path';
import { Observable, of, throwError } from 'rxjs';
import { concatMap, map, tap } from 'rxjs/operators';
import { concatMap, first, map, tap } from 'rxjs/operators';
import { BaseException } from '../exception';
import {
JsonObject,
@ -17,16 +19,22 @@ import {
} from '../json';
import {
Path,
basename,
dirname,
isAbsolute,
join,
normalize,
relative,
resolve,
virtualFs,
relative, resolve, virtualFs,
} from '../virtual-fs';
import { WorkspaceProject, WorkspaceSchema, WorkspaceTool } from './workspace-schema';
export class WorkspaceFileNotFoundException extends BaseException {
constructor(path: Path) {
super(`Workspace could not be found from path ${path}.`);
}
}
export class ProjectNotFoundException extends BaseException {
constructor(name: string) {
super(`Project '${name}' could not be found in workspace.`);
@ -55,15 +63,69 @@ export class AmbiguousProjectPathException extends BaseException {
}
}
async function _findUp(host: virtualFs.Host, names: string[], from: Path): Promise<Path | null> {
if (!Array.isArray(names)) {
names = [names];
}
do {
for (const name of names) {
const p = join(from, name);
if (await host.exists(p)) {
return p;
}
}
from = dirname(from);
} while (from && from !== dirname(from));
return null;
}
export class Workspace {
protected static _workspaceFileNames = [
'angular.json',
'.angular.json',
'workspace.json',
'.workspace.json',
];
private readonly _workspaceSchemaPath = normalize(require.resolve('./workspace-schema.json'));
private _workspaceSchema: JsonObject;
private _workspace: WorkspaceSchema;
private _registry: schema.CoreSchemaRegistry;
constructor(private _root: Path, private _host: virtualFs.Host<{}>) {
this._registry = new schema.CoreSchemaRegistry();
this._registry.addPostTransform(schema.transforms.addUndefinedDefaults);
constructor(
private _root: Path,
private _host: virtualFs.Host<{}>,
registry?: schema.CoreSchemaRegistry,
) {
if (registry) {
this._registry = registry;
} else {
this._registry = new schema.CoreSchemaRegistry();
this._registry.addPostTransform(schema.transforms.addUndefinedDefaults);
}
}
static async findWorkspaceFile(host: virtualFs.Host<{}>, path: Path): Promise<Path | null> {
return await _findUp(host, this._workspaceFileNames, path);
}
static async fromPath(
host: virtualFs.Host<{}>,
path: Path,
registry: schema.CoreSchemaRegistry,
): Promise<Workspace> {
const maybePath = await this.findWorkspaceFile(host, path);
if (!maybePath) {
throw new WorkspaceFileNotFoundException(path);
}
return new Workspace(dirname(maybePath), host, registry)
.loadWorkspaceFromHost(basename(maybePath))
.pipe(first())
.toPromise();
}
loadWorkspaceFromJson(json: {}) {