Skip to content

Commit ca3783a

Browse files
committed
feat: 🎸 edit project configuration
✅ Closes: 15
1 parent 7ec472b commit ca3783a

17 files changed

+313
-29
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import {
2+
extractValueObject,
3+
} from './extract-value-object';
4+
5+
describe('Extract value object', () => {
6+
const data = {
7+
name: 'value',
8+
nestedData: {
9+
name: 'nestedValue',
10+
level1: {
11+
level2: {
12+
level2Name: 'level2NameValue',
13+
level2Param: 'level2ParamValue',
14+
},
15+
},
16+
},
17+
};
18+
19+
it('should extract data from object', () => {
20+
expect(extractValueObject(data, 'nestedData.name')).toEqual({
21+
'nestedData.name': 'nestedValue',
22+
});
23+
expect(
24+
extractValueObject(data, 'nestedData.level1.level2.level2Name')
25+
).toEqual({ 'nestedData.level1.level2.level2Name': 'level2NameValue' });
26+
expect(extractValueObject(data, 'nestedData.level1')).toEqual({
27+
'nestedData.level1': {
28+
level2: {
29+
level2Name: 'level2NameValue',
30+
level2Param: 'level2ParamValue',
31+
},
32+
},
33+
});
34+
});
35+
36+
it('should extract data from object and override name', () => {
37+
expect(extractValueObject(data, 'nestedData.name', 'name')).toEqual({
38+
name: 'nestedValue',
39+
});
40+
expect(
41+
extractValueObject(
42+
data,
43+
'nestedData.level1.level2.level2Name',
44+
'level2Name'
45+
)
46+
).toEqual({ level2Name: 'level2NameValue' });
47+
expect(extractValueObject(data, 'nestedData.level1', 'level1')).toEqual({
48+
level1: {
49+
level2: {
50+
level2Name: 'level2NameValue',
51+
level2Param: 'level2ParamValue',
52+
},
53+
},
54+
});
55+
});
56+
57+
it('should extract data from object with wildcard', () => {
58+
expect(extractValueObject(data, 'nestedData.*')).toEqual({
59+
level1: {
60+
level2: {
61+
level2Name: 'level2NameValue',
62+
level2Param: 'level2ParamValue',
63+
},
64+
},
65+
name: 'nestedValue',
66+
});
67+
});
68+
});
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { JsonObject, JsonValue } from '@angular-devkit/core/src/json/utils';
2+
3+
export const extractValueObject = <T>(
4+
objectData: T,
5+
path: string,
6+
overridePath?: string
7+
): JsonObject => {
8+
const traverse = (
9+
dataObject: JsonObject,
10+
splitPaths: string[],
11+
currentPathIndex: number,
12+
defaultName = ''
13+
): void => {
14+
if (currentPathIndex === parts.length) {
15+
result[defaultName || splitPaths.join('.')] = dataObject as JsonValue;
16+
return;
17+
}
18+
if (!dataObject || typeof dataObject !== 'object') {
19+
return;
20+
}
21+
if (parts[currentPathIndex] === '*') {
22+
Object.entries(dataObject).forEach(([key, value]) =>
23+
traverse(
24+
value as JsonObject,
25+
splitPaths.concat(key),
26+
currentPathIndex + 1,
27+
key
28+
)
29+
);
30+
return;
31+
}
32+
if (parts[currentPathIndex] in dataObject) {
33+
traverse(
34+
dataObject[parts[currentPathIndex]] as JsonObject,
35+
splitPaths.concat(parts[currentPathIndex]),
36+
currentPathIndex + 1,
37+
defaultName
38+
);
39+
}
40+
};
41+
42+
const result: NonNullable<JsonObject> = {},
43+
parts = path.split('.');
44+
traverse(objectData as JsonObject, [], 0, overridePath);
45+
return result;
46+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { JSONSchema7 } from 'json-schema';
2+
3+
export class SchemaDto implements JSONSchema7 {
4+
properties: JSONSchema7['properties'];
5+
title: JSONSchema7['title'];
6+
description: JSONSchema7['title'];
7+
8+
constructor({ title, properties, description }: JSONSchema7) {
9+
this.properties = properties;
10+
this.title = title;
11+
this.description = description;
12+
}
13+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export interface ExtractValuePaths {
2+
path: string;
3+
overridePath?: string;
4+
}
5+
export const configurationsPaths: ExtractValuePaths[] = [
6+
{ path: 'definitions.project.properties.prefix', overridePath: 'prefix' },
7+
{ path: 'definitions.project.properties.root', overridePath: 'root' },
8+
{
9+
path: 'definitions.project.properties.sourceRoot',
10+
overridePath: 'sourceRoot',
11+
},
12+
];

‎apps/cli-daemon/src/app/workspace/workspace.controller.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Patch,
1010
Post,
1111
} from '@nestjs/common';
12+
import { JSONSchema7 } from 'json-schema';
1213

1314
import { ExecResult } from '../generators/dto';
1415
import { GeneratorsService } from '../generators/generators.service';
@@ -60,6 +61,11 @@ export class WorkspaceController {
6061
return this.workspaceService.readWorkspaceProjectNames();
6162
}
6263

64+
@Get('workspace-configuration')
65+
async getWorkspaceConfiguration(): Promise<JSONSchema7> {
66+
return this.workspaceService.getWorkspaceConfiguration();
67+
}
68+
6369
@Get('project/:projectName')
6470
async getProject(
6571
@Param('projectName') projectName: string

‎apps/cli-daemon/src/app/workspace/workspace.service.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { NodeJsSyncHost } from '@angular-devkit/core/node';
2+
import { JsonObject } from '@angular-devkit/core/src/json/utils';
23
import {
34
createWorkspaceHost,
45
readWorkspace as devKitReadWorkspace,
@@ -15,15 +16,20 @@ import {
1516
Logger,
1617
NotFoundException,
1718
} from '@nestjs/common';
19+
import { JSONSchema7 } from 'json-schema';
20+
import * as angularSchema from 'node_modules/@angular/cli/lib/config/schema.json';
1821

1922
import { SessionService } from '../session/session.service';
23+
import { extractValueObject } from '../utils/extract-value-object';
2024

2125
import { ProjectDto, UpdateProjectDto } from './dto';
26+
import { SchemaDto } from './dto/schema.dto';
2227
import {
2328
ANGULAR_WORKSPACE_NOT_FOUND_EXCEPTION,
2429
BAD_PATH_EXCEPTION,
2530
NOT_ANGULAR_WORKSPACE_EXCEPTION,
2631
} from './entities';
32+
import { configurationsPaths } from './entities/workspace-configuration';
2733

2834
const ANGULAR_JSON = '/angular.json';
2935

@@ -157,4 +163,24 @@ export class WorkspaceService {
157163
return new InternalServerErrorException(err);
158164
}
159165
}
166+
167+
getWorkspaceConfiguration(): Partial<JSONSchema7> {
168+
const configuration = configurationsPaths.reduce(
169+
(state: JsonObject, currentPath) => {
170+
const schemaValues = extractValueObject(
171+
angularSchema,
172+
currentPath.path,
173+
currentPath.overridePath
174+
);
175+
return { ...state, ...schemaValues };
176+
},
177+
{} as JsonObject
178+
);
179+
180+
return new SchemaDto({
181+
title: 'Angular CLI Workspace Configuration',
182+
description: 'Browser target options',
183+
properties: configuration as JSONSchema7['properties'],
184+
});
185+
}
160186
}

‎apps/cli-daemon/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"noImplicitOverride": true,
1919
"noPropertyAccessFromIndexSignature": true,
2020
"noImplicitReturns": true,
21-
"noFallthroughCasesInSwitch": true
21+
"noFallthroughCasesInSwitch": true,
22+
"resolveJsonModule": true
2223
}
2324
}
Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { CommonModule } from '@angular/common';
22
import { ChangeDetectionStrategy, Component } from '@angular/core';
33

4-
import { WorkspaceSettingsService } from './workspace-settings.service';
5-
64
@Component({
75
selector: 'cli-workspace-settings',
86
standalone: true,
@@ -11,10 +9,4 @@ import { WorkspaceSettingsService } from './workspace-settings.service';
119
styleUrls: ['./workspace-settings.component.scss'],
1210
changeDetection: ChangeDetectionStrategy.OnPush,
1311
})
14-
export class WorkspaceSettingsComponent {
15-
angularJson$ = this.workspaceSettingsService.readWorkspaceProjectNames();
16-
17-
constructor(
18-
private readonly workspaceSettingsService: WorkspaceSettingsService
19-
) {}
20-
}
12+
export class WorkspaceSettingsComponent {}

‎apps/cli-gui/src/app/workspace-settings/workspace-settings.service.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
1-
<p>configuration works!</p>
1+
<p>Edit project configuration</p>
2+
3+
<ng-container *ngIf="formly$ | async as formly">
4+
<form [formGroup]="form" (ngSubmit)="onSubmit()">
5+
<formly-form
6+
[model]="formly.formData"
7+
[fields]="formly.formFields"
8+
[form]="form"
9+
></formly-form>
10+
<button mat-button type="submit">Submit</button>
11+
</form>
12+
</ng-container>

0 commit comments

Comments
 (0)