Skip to content

Commit 041907d

Browse files
committed
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.
1 parent 02943ea commit 041907d

File tree

2 files changed

+77
-8
lines changed

2 files changed

+77
-8
lines changed

etc/api/angular_devkit/core/src/_golden-api.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,7 @@ export declare class Workspace {
10041004
readonly newProjectRoot: string | undefined;
10051005
readonly root: Path;
10061006
readonly version: number;
1007-
constructor(_root: Path, _host: virtualFs.Host<{}>);
1007+
constructor(_root: Path, _host: virtualFs.Host<{}>, registry?: schema.CoreSchemaRegistry);
10081008
getCli(): WorkspaceTool;
10091009
getDefaultProjectName(): string | null;
10101010
getProject(projectName: string): WorkspaceProject;
@@ -1018,6 +1018,13 @@ export declare class Workspace {
10181018
loadWorkspaceFromHost(workspacePath: Path): Observable<this>;
10191019
loadWorkspaceFromJson(json: {}): Observable<this>;
10201020
validateAgainstSchema<T = {}>(contentJson: {}, schemaJson: JsonObject): Observable<T>;
1021+
protected static _workspaceFileNames: string[];
1022+
static findWorkspaceFile(host: virtualFs.Host<{}>, path: Path): Promise<Path | null>;
1023+
static fromPath(host: virtualFs.Host<{}>, path: Path, registry: schema.CoreSchemaRegistry): Promise<Workspace>;
1024+
}
1025+
1026+
export declare class WorkspaceFileNotFoundException extends BaseException {
1027+
constructor(path: Path);
10211028
}
10221029

10231030
export declare class WorkspaceNotYetLoadedException extends BaseException {

packages/angular_devkit/core/src/workspace/workspace.ts

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import { existsSync } from 'fs';
10+
import * as path from 'path';
911
import { Observable, of, throwError } from 'rxjs';
10-
import { concatMap, map, tap } from 'rxjs/operators';
12+
import { concatMap, first, map, tap } from 'rxjs/operators';
1113
import { BaseException } from '../exception';
1214
import {
1315
JsonObject,
@@ -17,16 +19,22 @@ import {
1719
} from '../json';
1820
import {
1921
Path,
22+
basename,
23+
dirname,
2024
isAbsolute,
2125
join,
2226
normalize,
23-
relative,
24-
resolve,
25-
virtualFs,
27+
relative, resolve, virtualFs,
2628
} from '../virtual-fs';
2729
import { WorkspaceProject, WorkspaceSchema, WorkspaceTool } from './workspace-schema';
2830

2931

32+
export class WorkspaceFileNotFoundException extends BaseException {
33+
constructor(path: Path) {
34+
super(`Workspace could not be found from path ${path}.`);
35+
}
36+
}
37+
3038
export class ProjectNotFoundException extends BaseException {
3139
constructor(name: string) {
3240
super(`Project '${name}' could not be found in workspace.`);
@@ -55,15 +63,69 @@ export class AmbiguousProjectPathException extends BaseException {
5563
}
5664
}
5765

66+
async function _findUp(host: virtualFs.Host, names: string[], from: Path): Promise<Path | null> {
67+
if (!Array.isArray(names)) {
68+
names = [names];
69+
}
70+
71+
do {
72+
for (const name of names) {
73+
const p = join(from, name);
74+
if (await host.exists(p)) {
75+
return p;
76+
}
77+
}
78+
79+
from = dirname(from);
80+
} while (from && from !== dirname(from));
81+
82+
return null;
83+
}
84+
5885
export class Workspace {
86+
protected static _workspaceFileNames = [
87+
'angular.json',
88+
'.angular.json',
89+
'workspace.json',
90+
'.workspace.json',
91+
];
92+
5993
private readonly _workspaceSchemaPath = normalize(require.resolve('./workspace-schema.json'));
6094
private _workspaceSchema: JsonObject;
6195
private _workspace: WorkspaceSchema;
6296
private _registry: schema.CoreSchemaRegistry;
6397

64-
constructor(private _root: Path, private _host: virtualFs.Host<{}>) {
65-
this._registry = new schema.CoreSchemaRegistry();
66-
this._registry.addPostTransform(schema.transforms.addUndefinedDefaults);
98+
constructor(
99+
private _root: Path,
100+
private _host: virtualFs.Host<{}>,
101+
registry?: schema.CoreSchemaRegistry,
102+
) {
103+
if (registry) {
104+
this._registry = registry;
105+
} else {
106+
this._registry = new schema.CoreSchemaRegistry();
107+
this._registry.addPostTransform(schema.transforms.addUndefinedDefaults);
108+
}
109+
}
110+
111+
static async findWorkspaceFile(host: virtualFs.Host<{}>, path: Path): Promise<Path | null> {
112+
return await _findUp(host, this._workspaceFileNames, path);
113+
}
114+
static async fromPath(
115+
host: virtualFs.Host<{}>,
116+
path: Path,
117+
registry: schema.CoreSchemaRegistry,
118+
): Promise<Workspace> {
119+
const maybePath = await this.findWorkspaceFile(host, path);
120+
121+
if (!maybePath) {
122+
throw new WorkspaceFileNotFoundException(path);
123+
}
124+
125+
return new Workspace(dirname(maybePath), host, registry)
126+
.loadWorkspaceFromHost(basename(maybePath))
127+
.pipe(first())
128+
.toPromise();
67129
}
68130

69131
loadWorkspaceFromJson(json: {}) {

0 commit comments

Comments
 (0)