@angular-devkit/core 14.0.0-next.7 → 14.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node/host.js +6 -6
- package/package.json +2 -3
- package/src/experimental/jobs/strategy.d.ts +2 -2
- package/src/experimental/jobs/strategy.js +11 -4
- package/src/utils/object.js +1 -1
- package/src/virtual-fs/host/memory.js +5 -5
- package/src/workspace/definitions.d.ts +1 -1
- package/src/workspace/definitions.js +8 -7
- package/src/workspace/json/metadata.d.ts +12 -13
- package/src/workspace/json/metadata.js +28 -19
- package/src/workspace/json/reader.js +71 -86
- package/src/workspace/json/utilities.d.ts +3 -7
- package/src/workspace/json/utilities.js +62 -180
- package/src/workspace/json/writer.js +26 -192
- package/src/json/parser.d.ts +0 -104
- package/src/json/parser.js +0 -788
- package/src/json/parser_ast.d.ts +0 -67
- package/src/json/parser_ast.js +0 -9
package/node/host.js
CHANGED
|
@@ -111,21 +111,21 @@ class NodeJsAsyncHost {
|
|
|
111
111
|
obs.next({
|
|
112
112
|
path: (0, src_1.normalize)(path),
|
|
113
113
|
time: new Date(),
|
|
114
|
-
type: 0 /* Changed */,
|
|
114
|
+
type: 0 /* virtualFs.HostWatchEventType.Changed */,
|
|
115
115
|
});
|
|
116
116
|
})
|
|
117
117
|
.on('add', (path) => {
|
|
118
118
|
obs.next({
|
|
119
119
|
path: (0, src_1.normalize)(path),
|
|
120
120
|
time: new Date(),
|
|
121
|
-
type: 1 /* Created */,
|
|
121
|
+
type: 1 /* virtualFs.HostWatchEventType.Created */,
|
|
122
122
|
});
|
|
123
123
|
})
|
|
124
124
|
.on('unlink', (path) => {
|
|
125
125
|
obs.next({
|
|
126
126
|
path: (0, src_1.normalize)(path),
|
|
127
127
|
time: new Date(),
|
|
128
|
-
type: 2 /* Deleted */,
|
|
128
|
+
type: 2 /* virtualFs.HostWatchEventType.Deleted */,
|
|
129
129
|
});
|
|
130
130
|
});
|
|
131
131
|
return () => watcher.close();
|
|
@@ -209,21 +209,21 @@ class NodeJsSyncHost {
|
|
|
209
209
|
obs.next({
|
|
210
210
|
path: (0, src_1.normalize)(path),
|
|
211
211
|
time: new Date(),
|
|
212
|
-
type: 0 /* Changed */,
|
|
212
|
+
type: 0 /* virtualFs.HostWatchEventType.Changed */,
|
|
213
213
|
});
|
|
214
214
|
})
|
|
215
215
|
.on('add', (path) => {
|
|
216
216
|
obs.next({
|
|
217
217
|
path: (0, src_1.normalize)(path),
|
|
218
218
|
time: new Date(),
|
|
219
|
-
type: 1 /* Created */,
|
|
219
|
+
type: 1 /* virtualFs.HostWatchEventType.Created */,
|
|
220
220
|
});
|
|
221
221
|
})
|
|
222
222
|
.on('unlink', (path) => {
|
|
223
223
|
obs.next({
|
|
224
224
|
path: (0, src_1.normalize)(path),
|
|
225
225
|
time: new Date(),
|
|
226
|
-
type: 2 /* Deleted */,
|
|
226
|
+
type: 2 /* virtualFs.HostWatchEventType.Deleted */,
|
|
227
227
|
});
|
|
228
228
|
});
|
|
229
229
|
return () => watcher.close();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/core",
|
|
3
|
-
"version": "14.0.0-
|
|
3
|
+
"version": "14.0.0-rc.0",
|
|
4
4
|
"description": "Angular DevKit - Core Utility Library",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"typings": "src/index.d.ts",
|
|
@@ -15,8 +15,7 @@
|
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"ajv-formats": "2.1.1",
|
|
17
17
|
"ajv": "8.11.0",
|
|
18
|
-
"
|
|
19
|
-
"magic-string": "0.26.1",
|
|
18
|
+
"jsonc-parser": "3.0.0",
|
|
20
19
|
"rxjs": "6.6.7",
|
|
21
20
|
"source-map": "0.7.3"
|
|
22
21
|
},
|
|
@@ -16,13 +16,13 @@ export declare namespace strategy {
|
|
|
16
16
|
/**
|
|
17
17
|
* Creates a JobStrategy that will always reuse a running job, and restart it if the job ended.
|
|
18
18
|
* @param replayMessages Replay ALL messages if a job is reused, otherwise just hook up where it
|
|
19
|
-
*
|
|
19
|
+
* is.
|
|
20
20
|
*/
|
|
21
21
|
function reuse<A extends JsonValue = JsonValue, I extends JsonValue = JsonValue, O extends JsonValue = JsonValue>(replayMessages?: boolean): JobStrategy<A, I, O>;
|
|
22
22
|
/**
|
|
23
23
|
* Creates a JobStrategy that will reuse a running job if the argument matches.
|
|
24
24
|
* @param replayMessages Replay ALL messages if a job is reused, otherwise just hook up where it
|
|
25
|
-
*
|
|
25
|
+
* is.
|
|
26
26
|
*/
|
|
27
27
|
function memoize<A extends JsonValue = JsonValue, I extends JsonValue = JsonValue, O extends JsonValue = JsonValue>(replayMessages?: boolean): JobStrategy<A, I, O>;
|
|
28
28
|
}
|
|
@@ -10,8 +10,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.strategy = void 0;
|
|
11
11
|
const rxjs_1 = require("rxjs");
|
|
12
12
|
const operators_1 = require("rxjs/operators");
|
|
13
|
+
const json_1 = require("../../json");
|
|
13
14
|
const api_1 = require("./api");
|
|
14
|
-
const stableStringify = require('fast-json-stable-stringify');
|
|
15
15
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
16
16
|
var strategy;
|
|
17
17
|
(function (strategy) {
|
|
@@ -35,7 +35,7 @@ var strategy;
|
|
|
35
35
|
/**
|
|
36
36
|
* Creates a JobStrategy that will always reuse a running job, and restart it if the job ended.
|
|
37
37
|
* @param replayMessages Replay ALL messages if a job is reused, otherwise just hook up where it
|
|
38
|
-
*
|
|
38
|
+
* is.
|
|
39
39
|
*/
|
|
40
40
|
function reuse(replayMessages = false) {
|
|
41
41
|
let inboundBus = new rxjs_1.Subject();
|
|
@@ -70,13 +70,20 @@ var strategy;
|
|
|
70
70
|
/**
|
|
71
71
|
* Creates a JobStrategy that will reuse a running job if the argument matches.
|
|
72
72
|
* @param replayMessages Replay ALL messages if a job is reused, otherwise just hook up where it
|
|
73
|
-
*
|
|
73
|
+
* is.
|
|
74
74
|
*/
|
|
75
75
|
function memoize(replayMessages = false) {
|
|
76
76
|
const runs = new Map();
|
|
77
77
|
return (handler, options) => {
|
|
78
78
|
const newHandler = (argument, context) => {
|
|
79
|
-
const argumentJson =
|
|
79
|
+
const argumentJson = JSON.stringify((0, json_1.isJsonObject)(argument)
|
|
80
|
+
? Object.keys(argument)
|
|
81
|
+
.sort()
|
|
82
|
+
.reduce((result, key) => {
|
|
83
|
+
result[key] = argument[key];
|
|
84
|
+
return result;
|
|
85
|
+
}, {})
|
|
86
|
+
: argument);
|
|
80
87
|
const maybeJob = runs.get(argumentJson);
|
|
81
88
|
if (maybeJob) {
|
|
82
89
|
return maybeJob;
|
package/src/utils/object.js
CHANGED
|
@@ -71,7 +71,7 @@ class SimpleMemoryHost {
|
|
|
71
71
|
maybeWatcher.forEach((watcher) => {
|
|
72
72
|
const [options, subject] = watcher;
|
|
73
73
|
subject.next({ path, time, type });
|
|
74
|
-
if (!options.persistent && type == 2 /* Deleted */) {
|
|
74
|
+
if (!options.persistent && type == 2 /* HostWatchEventType.Deleted */) {
|
|
75
75
|
subject.complete();
|
|
76
76
|
this._watchers.delete(currentPath);
|
|
77
77
|
}
|
|
@@ -88,7 +88,7 @@ class SimpleMemoryHost {
|
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
subject.next({ path, time, type });
|
|
91
|
-
if (!options.persistent && type == 2 /* Deleted */) {
|
|
91
|
+
if (!options.persistent && type == 2 /* HostWatchEventType.Deleted */) {
|
|
92
92
|
subject.complete();
|
|
93
93
|
this._watchers.delete(currentPath);
|
|
94
94
|
}
|
|
@@ -127,7 +127,7 @@ class SimpleMemoryHost {
|
|
|
127
127
|
// Create the stats.
|
|
128
128
|
const stats = this._newFileStats(content, old);
|
|
129
129
|
this._cache.set(path, stats);
|
|
130
|
-
this._updateWatchers(path, old ? 0 /* Changed */ : 1 /* Created */);
|
|
130
|
+
this._updateWatchers(path, old ? 0 /* HostWatchEventType.Changed */ : 1 /* HostWatchEventType.Created */);
|
|
131
131
|
}
|
|
132
132
|
_read(path) {
|
|
133
133
|
path = this._toAbsolute(path);
|
|
@@ -157,7 +157,7 @@ class SimpleMemoryHost {
|
|
|
157
157
|
else {
|
|
158
158
|
this._cache.delete(path);
|
|
159
159
|
}
|
|
160
|
-
this._updateWatchers(path, 2 /* Deleted */);
|
|
160
|
+
this._updateWatchers(path, 2 /* HostWatchEventType.Deleted */);
|
|
161
161
|
}
|
|
162
162
|
_rename(from, to) {
|
|
163
163
|
from = this._toAbsolute(from);
|
|
@@ -204,7 +204,7 @@ class SimpleMemoryHost {
|
|
|
204
204
|
this._cache.set(to, content);
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
|
-
this._updateWatchers(from, 3 /* Renamed */);
|
|
207
|
+
this._updateWatchers(from, 3 /* HostWatchEventType.Renamed */);
|
|
208
208
|
}
|
|
209
209
|
_list(path) {
|
|
210
210
|
path = this._toAbsolute(path);
|
|
@@ -23,7 +23,7 @@ export interface TargetDefinition {
|
|
|
23
23
|
defaultConfiguration?: string;
|
|
24
24
|
builder: string;
|
|
25
25
|
}
|
|
26
|
-
export declare type DefinitionCollectionListener<V extends object> = (name: string,
|
|
26
|
+
export declare type DefinitionCollectionListener<V extends object> = (name: string, newValue: V | undefined, collection: DefinitionCollection<V>) => void;
|
|
27
27
|
declare class DefinitionCollection<V extends object> implements ReadonlyMap<string, V> {
|
|
28
28
|
private _listener?;
|
|
29
29
|
private _map;
|
|
@@ -14,18 +14,19 @@ class DefinitionCollection {
|
|
|
14
14
|
this._map = new Map(initial && Object.entries(initial));
|
|
15
15
|
}
|
|
16
16
|
delete(key) {
|
|
17
|
-
|
|
17
|
+
var _a;
|
|
18
18
|
const result = this._map.delete(key);
|
|
19
|
-
if (result
|
|
20
|
-
this._listener(
|
|
19
|
+
if (result) {
|
|
20
|
+
(_a = this._listener) === null || _a === void 0 ? void 0 : _a.call(this, key, undefined, this);
|
|
21
21
|
}
|
|
22
22
|
return result;
|
|
23
23
|
}
|
|
24
24
|
set(key, value) {
|
|
25
|
-
|
|
26
|
-
this.
|
|
27
|
-
if (
|
|
28
|
-
this.
|
|
25
|
+
var _a;
|
|
26
|
+
const updatedValue = value !== this.get(key);
|
|
27
|
+
if (updatedValue) {
|
|
28
|
+
this._map.set(key, value);
|
|
29
|
+
(_a = this._listener) === null || _a === void 0 ? void 0 : _a.call(this, key, value, this);
|
|
29
30
|
}
|
|
30
31
|
return this;
|
|
31
32
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
+
import { JSONPath, Node } from 'jsonc-parser';
|
|
8
9
|
import { JsonValue } from '../../json';
|
|
9
|
-
import { JsonAstArray, JsonAstKeyValue, JsonAstNode, JsonAstObject } from '../../json/parser_ast';
|
|
10
10
|
import { ProjectDefinition, TargetDefinition, WorkspaceDefinition } from '../definitions';
|
|
11
11
|
export declare const JsonWorkspaceSymbol: unique symbol;
|
|
12
12
|
export interface JsonWorkspaceDefinition extends WorkspaceDefinition {
|
|
@@ -19,23 +19,22 @@ interface ChangeValues {
|
|
|
19
19
|
projectcollection: Iterable<[string, ProjectDefinition]>;
|
|
20
20
|
targetcollection: Iterable<[string, TargetDefinition]>;
|
|
21
21
|
}
|
|
22
|
-
export interface JsonChange
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
value?: ChangeValues[T];
|
|
27
|
-
type: T;
|
|
22
|
+
export interface JsonChange {
|
|
23
|
+
value?: unknown;
|
|
24
|
+
type?: keyof ChangeValues;
|
|
25
|
+
jsonPath: string[];
|
|
28
26
|
}
|
|
29
27
|
export declare class JsonWorkspaceMetadata {
|
|
30
28
|
readonly filePath: string;
|
|
31
|
-
readonly ast
|
|
29
|
+
private readonly ast;
|
|
32
30
|
readonly raw: string;
|
|
33
|
-
readonly changes: JsonChange
|
|
34
|
-
|
|
31
|
+
readonly changes: Map<string, JsonChange>;
|
|
32
|
+
hasLegacyTargetsName: boolean;
|
|
33
|
+
constructor(filePath: string, ast: Node, raw: string);
|
|
35
34
|
get hasChanges(): boolean;
|
|
36
35
|
get changeCount(): number;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
getNodeValueFromAst(path: JSONPath): unknown;
|
|
37
|
+
findChangesForPath(path: string): JsonChange | undefined;
|
|
38
|
+
addChange<T extends keyof ChangeValues = keyof ChangeValues>(jsonPath: string[], value: ChangeValues[T] | undefined, type?: T): void;
|
|
40
39
|
}
|
|
41
40
|
export {};
|
|
@@ -8,40 +8,49 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.JsonWorkspaceMetadata = exports.JsonWorkspaceSymbol = void 0;
|
|
11
|
+
const jsonc_parser_1 = require("jsonc-parser");
|
|
11
12
|
exports.JsonWorkspaceSymbol = Symbol.for('@angular/core:workspace-json');
|
|
13
|
+
function escapeKey(key) {
|
|
14
|
+
return key.replace('~', '~0').replace('/', '~1');
|
|
15
|
+
}
|
|
12
16
|
class JsonWorkspaceMetadata {
|
|
13
17
|
constructor(filePath, ast, raw) {
|
|
14
18
|
this.filePath = filePath;
|
|
15
19
|
this.ast = ast;
|
|
16
20
|
this.raw = raw;
|
|
17
|
-
this.changes =
|
|
21
|
+
this.changes = new Map();
|
|
22
|
+
this.hasLegacyTargetsName = true;
|
|
18
23
|
}
|
|
19
24
|
get hasChanges() {
|
|
20
|
-
return this.changes.
|
|
25
|
+
return this.changes.size > 0;
|
|
21
26
|
}
|
|
22
27
|
get changeCount() {
|
|
23
|
-
return this.changes.
|
|
28
|
+
return this.changes.size;
|
|
29
|
+
}
|
|
30
|
+
getNodeValueFromAst(path) {
|
|
31
|
+
const node = (0, jsonc_parser_1.findNodeAtLocation)(this.ast, path);
|
|
32
|
+
return node && (0, jsonc_parser_1.getNodeValue)(node);
|
|
24
33
|
}
|
|
25
34
|
findChangesForPath(path) {
|
|
26
|
-
return this.changes.
|
|
35
|
+
return this.changes.get(path);
|
|
27
36
|
}
|
|
28
|
-
addChange(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
op = 'add';
|
|
36
|
-
}
|
|
37
|
-
this.changes.splice(i, 1);
|
|
38
|
-
}
|
|
37
|
+
addChange(jsonPath, value, type) {
|
|
38
|
+
let currentPath = '';
|
|
39
|
+
for (let index = 0; index < jsonPath.length - 1; index++) {
|
|
40
|
+
currentPath = currentPath + '/' + escapeKey(jsonPath[index]);
|
|
41
|
+
if (this.changes.has(currentPath)) {
|
|
42
|
+
// Ignore changes on children as parent is updated.
|
|
43
|
+
return;
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
const pathKey = '/' + jsonPath.map((k) => escapeKey(k)).join('/');
|
|
47
|
+
for (const key of this.changes.keys()) {
|
|
48
|
+
if (key.startsWith(pathKey + '/')) {
|
|
49
|
+
// changes on the same or child paths are redundant.
|
|
50
|
+
this.changes.delete(key);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
this.changes.set(pathKey, { jsonPath, type, value });
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
exports.JsonWorkspaceMetadata = JsonWorkspaceMetadata;
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.readJsonWorkspace = void 0;
|
|
11
|
-
const
|
|
11
|
+
const jsonc_parser_1 = require("jsonc-parser");
|
|
12
|
+
const utils_1 = require("../../json/utils");
|
|
12
13
|
const definitions_1 = require("../definitions");
|
|
13
14
|
const metadata_1 = require("./metadata");
|
|
14
15
|
const utilities_1 = require("./utilities");
|
|
@@ -17,18 +18,18 @@ async function readJsonWorkspace(path, host) {
|
|
|
17
18
|
if (raw === undefined) {
|
|
18
19
|
throw new Error('Unable to read workspace file.');
|
|
19
20
|
}
|
|
20
|
-
const ast = (0,
|
|
21
|
-
if (ast.
|
|
21
|
+
const ast = (0, jsonc_parser_1.parseTree)(raw, undefined, { allowTrailingComma: true, disallowComments: false });
|
|
22
|
+
if ((ast === null || ast === void 0 ? void 0 : ast.type) !== 'object' || !ast.children) {
|
|
22
23
|
throw new Error('Invalid workspace file - expected JSON object.');
|
|
23
24
|
}
|
|
24
25
|
// Version check
|
|
25
|
-
const versionNode =
|
|
26
|
+
const versionNode = (0, jsonc_parser_1.findNodeAtLocation)(ast, ['version']);
|
|
26
27
|
if (!versionNode) {
|
|
27
28
|
throw new Error('Unknown format - version specifier not found.');
|
|
28
29
|
}
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
31
|
-
throw new Error(`Invalid format version detected - Expected:[ 1 ] Found: [ ${
|
|
30
|
+
const version = versionNode.value;
|
|
31
|
+
if (version !== 1) {
|
|
32
|
+
throw new Error(`Invalid format version detected - Expected:[ 1 ] Found: [ ${version} ]`);
|
|
32
33
|
}
|
|
33
34
|
const context = {
|
|
34
35
|
host,
|
|
@@ -51,38 +52,38 @@ const specialProjectExtensions = ['cli', 'schematics', 'projectType'];
|
|
|
51
52
|
function parseWorkspace(workspaceNode, context) {
|
|
52
53
|
const jsonMetadata = context.metadata;
|
|
53
54
|
let projects;
|
|
54
|
-
let projectsNode;
|
|
55
55
|
let extensions;
|
|
56
56
|
if (!context.trackChanges) {
|
|
57
57
|
extensions = Object.create(null);
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
// TODO: `getNodeValue` - looks potentially expensive since it walks the whole tree and instantiates the full object structure each time.
|
|
60
|
+
// Might be something to look at moving forward to optimize.
|
|
61
|
+
const workspaceNodeValue = (0, jsonc_parser_1.getNodeValue)(workspaceNode);
|
|
62
|
+
for (const [name, value] of Object.entries(workspaceNodeValue)) {
|
|
61
63
|
if (name === '$schema' || name === 'version') {
|
|
62
64
|
// skip
|
|
63
65
|
}
|
|
64
66
|
else if (name === 'projects') {
|
|
65
|
-
|
|
67
|
+
const nodes = (0, jsonc_parser_1.findNodeAtLocation)(workspaceNode, ['projects']);
|
|
68
|
+
if (!(0, utils_1.isJsonObject)(value) || !nodes) {
|
|
66
69
|
context.error('Invalid "projects" field found; expected an object.', value);
|
|
67
70
|
continue;
|
|
68
71
|
}
|
|
69
|
-
|
|
70
|
-
projects = parseProjectsObject(value, context);
|
|
72
|
+
projects = parseProjectsObject(nodes, context);
|
|
71
73
|
}
|
|
72
74
|
else {
|
|
73
75
|
if (!specialWorkspaceExtensions.includes(name) && !/^[a-z]{1,3}-.*/.test(name)) {
|
|
74
|
-
context.warn(`Project extension with invalid name found.`,
|
|
76
|
+
context.warn(`Project extension with invalid name found.`, name);
|
|
75
77
|
}
|
|
76
78
|
if (extensions) {
|
|
77
|
-
extensions[name] = value
|
|
79
|
+
extensions[name] = value;
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
let collectionListener;
|
|
82
|
-
if (context.trackChanges
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
jsonMetadata.addChange(action, `/projects/${(0, utilities_1.escapeKey)(name)}`, parentNode, newValue, 'project');
|
|
84
|
+
if (context.trackChanges) {
|
|
85
|
+
collectionListener = (name, newValue) => {
|
|
86
|
+
jsonMetadata.addChange(['projects', name], newValue, 'project');
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
89
|
const projectCollection = new definitions_1.ProjectDefinitionCollection(projects, collectionListener);
|
|
@@ -91,31 +92,30 @@ function parseWorkspace(workspaceNode, context) {
|
|
|
91
92
|
projects: projectCollection,
|
|
92
93
|
// If not tracking changes the `extensions` variable will contain the parsed
|
|
93
94
|
// values. Otherwise the extensions are tracked via a virtual AST object.
|
|
94
|
-
extensions: extensions
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}),
|
|
95
|
+
extensions: extensions !== null && extensions !== void 0 ? extensions : (0, utilities_1.createVirtualAstObject)(workspaceNodeValue, {
|
|
96
|
+
exclude: ['$schema', 'version', 'projects'],
|
|
97
|
+
listener(path, value) {
|
|
98
|
+
jsonMetadata.addChange(path, value);
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
103
|
function parseProjectsObject(projectsNode, context) {
|
|
104
104
|
const projects = Object.create(null);
|
|
105
|
-
for (const
|
|
106
|
-
|
|
105
|
+
for (const [name, value] of Object.entries((0, jsonc_parser_1.getNodeValue)(projectsNode))) {
|
|
106
|
+
const nodes = (0, jsonc_parser_1.findNodeAtLocation)(projectsNode, [name]);
|
|
107
|
+
if (!(0, utils_1.isJsonObject)(value) || !nodes) {
|
|
107
108
|
context.warn('Skipping invalid project value; expected an object.', value);
|
|
108
109
|
continue;
|
|
109
110
|
}
|
|
110
|
-
|
|
111
|
-
projects[name] = parseProject(name, value, context);
|
|
111
|
+
projects[name] = parseProject(name, nodes, context);
|
|
112
112
|
}
|
|
113
113
|
return projects;
|
|
114
114
|
}
|
|
115
115
|
function parseProject(projectName, projectNode, context) {
|
|
116
116
|
const jsonMetadata = context.metadata;
|
|
117
117
|
let targets;
|
|
118
|
-
let
|
|
118
|
+
let hasTargets = false;
|
|
119
119
|
let extensions;
|
|
120
120
|
let properties;
|
|
121
121
|
if (!context.trackChanges) {
|
|
@@ -123,106 +123,91 @@ function parseProject(projectName, projectNode, context) {
|
|
|
123
123
|
extensions = Object.create(null);
|
|
124
124
|
properties = Object.create(null);
|
|
125
125
|
}
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
const projectNodeValue = (0, jsonc_parser_1.getNodeValue)(projectNode);
|
|
127
|
+
for (const [name, value] of Object.entries(projectNodeValue)) {
|
|
128
128
|
switch (name) {
|
|
129
129
|
case 'targets':
|
|
130
130
|
case 'architect':
|
|
131
|
-
|
|
131
|
+
const nodes = (0, jsonc_parser_1.findNodeAtLocation)(projectNode, [name]);
|
|
132
|
+
if (!(0, utils_1.isJsonObject)(value) || !nodes) {
|
|
132
133
|
context.error(`Invalid "${name}" field found; expected an object.`, value);
|
|
133
134
|
break;
|
|
134
135
|
}
|
|
135
|
-
|
|
136
|
-
targets = parseTargetsObject(projectName,
|
|
136
|
+
hasTargets = true;
|
|
137
|
+
targets = parseTargetsObject(projectName, nodes, context);
|
|
138
|
+
jsonMetadata.hasLegacyTargetsName = name === 'architect';
|
|
137
139
|
break;
|
|
138
140
|
case 'prefix':
|
|
139
141
|
case 'root':
|
|
140
142
|
case 'sourceRoot':
|
|
141
|
-
if (value
|
|
143
|
+
if (typeof value !== 'string') {
|
|
142
144
|
context.warn(`Project property "${name}" should be a string.`, value);
|
|
143
145
|
}
|
|
144
146
|
if (properties) {
|
|
145
|
-
properties[name] = value
|
|
147
|
+
properties[name] = value;
|
|
146
148
|
}
|
|
147
149
|
break;
|
|
148
150
|
default:
|
|
149
151
|
if (!specialProjectExtensions.includes(name) && !/^[a-z]{1,3}-.*/.test(name)) {
|
|
150
|
-
context.warn(`Project extension with invalid name found.`,
|
|
152
|
+
context.warn(`Project extension with invalid name found.`, name);
|
|
151
153
|
}
|
|
152
154
|
if (extensions) {
|
|
153
|
-
extensions[name] = value
|
|
155
|
+
extensions[name] = value;
|
|
154
156
|
}
|
|
155
157
|
break;
|
|
156
158
|
}
|
|
157
159
|
}
|
|
158
160
|
let collectionListener;
|
|
159
161
|
if (context.trackChanges) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
collectionListener = (_name, action, _new, _old, collection) => {
|
|
169
|
-
if (added || action !== 'add') {
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
jsonMetadata.addChange('add', `/projects/${projectName}/targets`, projectNode, collection, 'targetcollection');
|
|
173
|
-
added = true;
|
|
174
|
-
};
|
|
175
|
-
}
|
|
162
|
+
collectionListener = (name, newValue, collection) => {
|
|
163
|
+
if (hasTargets) {
|
|
164
|
+
jsonMetadata.addChange(['projects', projectName, 'targets', name], newValue, 'target');
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
jsonMetadata.addChange(['projects', projectName, 'targets'], collection, 'targetcollection');
|
|
168
|
+
}
|
|
169
|
+
};
|
|
176
170
|
}
|
|
177
171
|
const base = {
|
|
178
172
|
targets: new definitions_1.TargetDefinitionCollection(targets, collectionListener),
|
|
179
173
|
// If not tracking changes the `extensions` variable will contain the parsed
|
|
180
174
|
// values. Otherwise the extensions are tracked via a virtual AST object.
|
|
181
|
-
extensions: extensions
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
jsonMetadata.addChange(op, `/projects/${projectName}${path}`, node, value);
|
|
186
|
-
},
|
|
187
|
-
}),
|
|
188
|
-
};
|
|
189
|
-
let project;
|
|
190
|
-
if (context.trackChanges) {
|
|
191
|
-
project = (0, utilities_1.createVirtualAstObject)(projectNode, {
|
|
192
|
-
base,
|
|
193
|
-
include: ['prefix', 'root', 'sourceRoot'],
|
|
194
|
-
listener(op, path, node, value) {
|
|
195
|
-
jsonMetadata.addChange(op, `/projects/${projectName}${path}`, node, value);
|
|
175
|
+
extensions: extensions !== null && extensions !== void 0 ? extensions : (0, utilities_1.createVirtualAstObject)(projectNodeValue, {
|
|
176
|
+
exclude: ['architect', 'prefix', 'root', 'sourceRoot', 'targets'],
|
|
177
|
+
listener(path, value) {
|
|
178
|
+
jsonMetadata.addChange(['projects', projectName, ...path], value);
|
|
196
179
|
},
|
|
197
|
-
})
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
180
|
+
}),
|
|
181
|
+
};
|
|
182
|
+
const baseKeys = new Set(Object.keys(base));
|
|
183
|
+
const project = properties !== null && properties !== void 0 ? properties : (0, utilities_1.createVirtualAstObject)(projectNodeValue, {
|
|
184
|
+
include: ['prefix', 'root', 'sourceRoot', ...baseKeys],
|
|
185
|
+
listener(path, value) {
|
|
186
|
+
if (!baseKeys.has(path[0])) {
|
|
187
|
+
jsonMetadata.addChange(['projects', projectName, ...path], value);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
return Object.assign(project, base);
|
|
206
192
|
}
|
|
207
193
|
function parseTargetsObject(projectName, targetsNode, context) {
|
|
208
194
|
const jsonMetadata = context.metadata;
|
|
209
195
|
const targets = Object.create(null);
|
|
210
|
-
for (const
|
|
211
|
-
if (
|
|
196
|
+
for (const [name, value] of Object.entries((0, jsonc_parser_1.getNodeValue)(targetsNode))) {
|
|
197
|
+
if (!(0, utils_1.isJsonObject)(value)) {
|
|
212
198
|
context.warn('Skipping invalid target value; expected an object.', value);
|
|
213
199
|
continue;
|
|
214
200
|
}
|
|
215
|
-
const name = key.value;
|
|
216
201
|
if (context.trackChanges) {
|
|
217
202
|
targets[name] = (0, utilities_1.createVirtualAstObject)(value, {
|
|
218
203
|
include: ['builder', 'options', 'configurations', 'defaultConfiguration'],
|
|
219
|
-
listener(
|
|
220
|
-
jsonMetadata.addChange(
|
|
204
|
+
listener(path, value) {
|
|
205
|
+
jsonMetadata.addChange(['projects', projectName, 'targets', name, ...path], value);
|
|
221
206
|
},
|
|
222
207
|
});
|
|
223
208
|
}
|
|
224
209
|
else {
|
|
225
|
-
targets[name] = value
|
|
210
|
+
targets[name] = value;
|
|
226
211
|
}
|
|
227
212
|
}
|
|
228
213
|
return targets;
|
|
@@ -5,14 +5,10 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
-
import { JsonObject, JsonValue } from '../../json';
|
|
9
|
-
|
|
10
|
-
export declare
|
|
11
|
-
export declare function escapeKey(key: string | number): string | number;
|
|
12
|
-
export declare function unescapeKey(key: string | number): string | number;
|
|
13
|
-
export declare function createVirtualAstObject<T extends object = JsonObject>(root: JsonAstObject, options?: {
|
|
8
|
+
import { JsonArray, JsonObject, JsonValue } from '../../json';
|
|
9
|
+
export declare type ChangeListener = (path: string[], newValue: JsonValue | undefined) => void;
|
|
10
|
+
export declare function createVirtualAstObject<T extends object = JsonObject>(root: JsonObject | JsonArray, options?: {
|
|
14
11
|
exclude?: string[];
|
|
15
12
|
include?: string[];
|
|
16
13
|
listener?: ChangeListener;
|
|
17
|
-
base?: object;
|
|
18
14
|
}): T;
|