Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.

Commit 54d5d56

Browse files
committed
feat(@angular-devkit/core): add workspace getProjectByPath
1 parent 49e9285 commit 54d5d56

File tree

2 files changed

+56
-1
lines changed

2 files changed

+56
-1
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ import {
1212
JsonObject,
1313
JsonParseMode,
1414
Path,
15+
isAbsolute,
1516
join,
1617
normalize,
1718
parseJson,
19+
relative,
20+
resolve,
1821
schema,
1922
virtualFs,
2023
} from '..';
@@ -143,6 +146,38 @@ export class Workspace {
143146
return null;
144147
}
145148

149+
getProjectByPath(path: Path): string | null {
150+
this._assertLoaded();
151+
152+
const projectNames = this.listProjectNames();
153+
if (projectNames.length === 1) {
154+
return projectNames[0];
155+
}
156+
157+
const isInside = (base: Path, potential: Path): boolean => {
158+
const absoluteBase = resolve(this.root, base);
159+
const absolutePotential = resolve(this.root, potential);
160+
const relativePotential = relative(absoluteBase, absolutePotential);
161+
if (!relativePotential.startsWith('..') && !isAbsolute(relativePotential)) {
162+
return true;
163+
}
164+
165+
return false;
166+
};
167+
168+
const projects = this.listProjectNames()
169+
.map(name => [this.getProject(name).root, name] as [Path, string])
170+
.filter(tuple => isInside(tuple[0], path))
171+
// Sort tuples by depth, with the deeper ones first.
172+
.sort((a, b) => isInside(a[0], b[0]) ? 1 : 0);
173+
174+
if (projects[0]) {
175+
return projects[0][1];
176+
}
177+
178+
return null;
179+
}
180+
146181
getCli() {
147182
return this._getTool('cli');
148183
}

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,34 @@ describe('Workspace', () => {
202202
).subscribe(undefined, done.fail, done);
203203
});
204204

205-
it('gets default project when there is a single one', (done) => {
205+
it('gets default project returns null when there is none', (done) => {
206206
const customWorkspaceJson = { ...workspaceJson, defaultProject: undefined, projects: {} };
207207
const workspace = new Workspace(root, host);
208208
workspace.loadWorkspaceFromJson(customWorkspaceJson).pipe(
209209
tap((ws) => expect(ws.getDefaultProject()).toEqual(null)),
210210
).subscribe(undefined, done.fail, done);
211211
});
212212

213+
it('gets project by path', (done) => {
214+
const workspace = new Workspace(root, host);
215+
workspace.loadWorkspaceFromJson(workspaceJson).pipe(
216+
tap((ws) => expect(ws.getProjectByPath(ws.root)).toEqual('app')),
217+
).subscribe(undefined, done.fail, done);
218+
});
219+
220+
it('gets closest project by path', (done) => {
221+
const app = workspaceJson.projects['app'];
222+
const anotherAppRoot = join(normalize(app.root), 'folder');
223+
const customWorkspaceJson = { ...workspaceJson, projects: {
224+
'app': app,
225+
'another-app': { ...app, root: anotherAppRoot},
226+
} };
227+
const workspace = new Workspace(root, host);
228+
workspace.loadWorkspaceFromJson(customWorkspaceJson).pipe(
229+
tap((ws) => expect(ws.getProjectByPath(anotherAppRoot)).toEqual('another-app')),
230+
).subscribe(undefined, done.fail, done);
231+
});
232+
213233
it('gets workspace cli', (done) => {
214234
const workspace = new Workspace(root, host);
215235
workspace.loadWorkspaceFromJson(workspaceJson).pipe(

0 commit comments

Comments
 (0)