@ngrx/store-devtools 12.5.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/README.md +5 -0
- package/bundles/ngrx-store-devtools.umd.js +1318 -0
- package/bundles/ngrx-store-devtools.umd.js.map +1 -0
- package/esm2015/index.js +7 -0
- package/esm2015/ngrx-store-devtools.js +9 -0
- package/esm2015/public_api.js +2 -0
- package/esm2015/src/actions.js +97 -0
- package/esm2015/src/config.js +61 -0
- package/esm2015/src/devtools-dispatcher.js +9 -0
- package/esm2015/src/devtools.js +115 -0
- package/esm2015/src/extension.js +160 -0
- package/esm2015/src/index.js +5 -0
- package/esm2015/src/instrument.js +67 -0
- package/esm2015/src/reducer.js +365 -0
- package/esm2015/src/utils.js +106 -0
- package/fesm2015/ngrx-store-devtools.js +964 -0
- package/fesm2015/ngrx-store-devtools.js.map +1 -0
- package/index.d.ts +6 -0
- package/migrations/6_0_0/index.js +8 -0
- package/migrations/6_0_0/index.js.map +1 -0
- package/migrations/migration.json +10 -0
- package/ngrx-store-devtools.d.ts +8 -0
- package/ngrx-store-devtools.metadata.json +1 -0
- package/package.json +52 -0
- package/public_api.d.ts +1 -0
- package/schematics/collection.json +10 -0
- package/schematics/ng-add/index.js +110 -0
- package/schematics/ng-add/index.js.map +1 -0
- package/schematics/ng-add/schema.js +3 -0
- package/schematics/ng-add/schema.js.map +1 -0
- package/schematics/ng-add/schema.json +42 -0
- package/schematics-core/index.js +86 -0
- package/schematics-core/index.js.map +1 -0
- package/schematics-core/utility/angular-utils.js +33 -0
- package/schematics-core/utility/angular-utils.js.map +1 -0
- package/schematics-core/utility/ast-utils.js +701 -0
- package/schematics-core/utility/ast-utils.js.map +1 -0
- package/schematics-core/utility/change.js +162 -0
- package/schematics-core/utility/change.js.map +1 -0
- package/schematics-core/utility/config.js +21 -0
- package/schematics-core/utility/config.js.map +1 -0
- package/schematics-core/utility/find-component.js +101 -0
- package/schematics-core/utility/find-component.js.map +1 -0
- package/schematics-core/utility/find-module.js +102 -0
- package/schematics-core/utility/find-module.js.map +1 -0
- package/schematics-core/utility/json-utilts.js +37 -0
- package/schematics-core/utility/json-utilts.js.map +1 -0
- package/schematics-core/utility/libs-version.js +5 -0
- package/schematics-core/utility/libs-version.js.map +1 -0
- package/schematics-core/utility/ngrx-utils.js +246 -0
- package/schematics-core/utility/ngrx-utils.js.map +1 -0
- package/schematics-core/utility/package.js +23 -0
- package/schematics-core/utility/package.js.map +1 -0
- package/schematics-core/utility/parse-name.js +14 -0
- package/schematics-core/utility/parse-name.js.map +1 -0
- package/schematics-core/utility/project.js +35 -0
- package/schematics-core/utility/project.js.map +1 -0
- package/schematics-core/utility/strings.js +138 -0
- package/schematics-core/utility/strings.js.map +1 -0
- package/schematics-core/utility/update.js +34 -0
- package/schematics-core/utility/update.js.map +1 -0
- package/schematics-core/utility/visitors.js +250 -0
- package/schematics-core/utility/visitors.js.map +1 -0
- package/src/actions.d.ts +79 -0
- package/src/config.d.ts +113 -0
- package/src/devtools-dispatcher.d.ts +3 -0
- package/src/devtools.d.ts +31 -0
- package/src/extension.d.ts +46 -0
- package/src/index.d.ts +4 -0
- package/src/instrument.d.ts +12 -0
- package/src/reducer.d.ts +47 -0
- package/src/utils.d.ts +42 -0
|
@@ -0,0 +1,701 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __values = (this && this.__values) || function(o) {
|
|
3
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
4
|
+
if (m) return m.call(o);
|
|
5
|
+
if (o && typeof o.length === "number") return {
|
|
6
|
+
next: function () {
|
|
7
|
+
if (o && i >= o.length) o = void 0;
|
|
8
|
+
return { value: o && o[i++], done: !o };
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
12
|
+
};
|
|
13
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
14
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
15
|
+
if (!m) return o;
|
|
16
|
+
var i = m.call(o), r, ar = [], e;
|
|
17
|
+
try {
|
|
18
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
19
|
+
}
|
|
20
|
+
catch (error) { e = { error: error }; }
|
|
21
|
+
finally {
|
|
22
|
+
try {
|
|
23
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
24
|
+
}
|
|
25
|
+
finally { if (e) throw e.error; }
|
|
26
|
+
}
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
|
|
30
|
+
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
|
31
|
+
to[j] = from[i];
|
|
32
|
+
return to;
|
|
33
|
+
};
|
|
34
|
+
exports.__esModule = true;
|
|
35
|
+
exports.containsProperty = exports.replaceImport = exports.insertImport = exports.addBootstrapToModule = exports.addExportToModule = exports.addProviderToComponent = exports.addProviderToModule = exports.addImportToModule = exports.addDeclarationToModule = exports.getDecoratorMetadata = exports.getContentOfKeyLiteral = exports.insertAfterLastOccurrence = exports.getSourceNodes = exports.findNodes = void 0;
|
|
36
|
+
/* istanbul ignore file */
|
|
37
|
+
/**
|
|
38
|
+
* @license
|
|
39
|
+
* Copyright Google Inc. All Rights Reserved.
|
|
40
|
+
*
|
|
41
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
42
|
+
* found in the LICENSE file at https://angular.io/license
|
|
43
|
+
*/
|
|
44
|
+
var ts = require("typescript");
|
|
45
|
+
var change_1 = require("./change");
|
|
46
|
+
/**
|
|
47
|
+
* Find all nodes from the AST in the subtree of node of SyntaxKind kind.
|
|
48
|
+
* @param node
|
|
49
|
+
* @param kind
|
|
50
|
+
* @param max The maximum number of items to return.
|
|
51
|
+
* @return all nodes of kind, or [] if none is found
|
|
52
|
+
*/
|
|
53
|
+
function findNodes(node, kind, max) {
|
|
54
|
+
var e_1, _a;
|
|
55
|
+
if (max === void 0) { max = Infinity; }
|
|
56
|
+
if (!node || max == 0) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
var arr = [];
|
|
60
|
+
if (node.kind === kind) {
|
|
61
|
+
arr.push(node);
|
|
62
|
+
max--;
|
|
63
|
+
}
|
|
64
|
+
if (max > 0) {
|
|
65
|
+
try {
|
|
66
|
+
for (var _b = __values(node.getChildren()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
67
|
+
var child = _c.value;
|
|
68
|
+
findNodes(child, kind, max).forEach(function (node) {
|
|
69
|
+
if (max > 0) {
|
|
70
|
+
arr.push(node);
|
|
71
|
+
}
|
|
72
|
+
max--;
|
|
73
|
+
});
|
|
74
|
+
if (max <= 0) {
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
80
|
+
finally {
|
|
81
|
+
try {
|
|
82
|
+
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
|
|
83
|
+
}
|
|
84
|
+
finally { if (e_1) throw e_1.error; }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return arr;
|
|
88
|
+
}
|
|
89
|
+
exports.findNodes = findNodes;
|
|
90
|
+
/**
|
|
91
|
+
* Get all the nodes from a source.
|
|
92
|
+
* @param sourceFile The source file object.
|
|
93
|
+
* @returns {Observable<ts.Node>} An observable of all the nodes in the source.
|
|
94
|
+
*/
|
|
95
|
+
function getSourceNodes(sourceFile) {
|
|
96
|
+
var nodes = [sourceFile];
|
|
97
|
+
var result = [];
|
|
98
|
+
while (nodes.length > 0) {
|
|
99
|
+
var node = nodes.shift();
|
|
100
|
+
if (node) {
|
|
101
|
+
result.push(node);
|
|
102
|
+
if (node.getChildCount(sourceFile) >= 0) {
|
|
103
|
+
nodes.unshift.apply(nodes, __spreadArray([], __read(node.getChildren())));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
exports.getSourceNodes = getSourceNodes;
|
|
110
|
+
/**
|
|
111
|
+
* Helper for sorting nodes.
|
|
112
|
+
* @return function to sort nodes in increasing order of position in sourceFile
|
|
113
|
+
*/
|
|
114
|
+
function nodesByPosition(first, second) {
|
|
115
|
+
return first.pos - second.pos;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Insert `toInsert` after the last occurence of `ts.SyntaxKind[nodes[i].kind]`
|
|
119
|
+
* or after the last of occurence of `syntaxKind` if the last occurence is a sub child
|
|
120
|
+
* of ts.SyntaxKind[nodes[i].kind] and save the changes in file.
|
|
121
|
+
*
|
|
122
|
+
* @param nodes insert after the last occurence of nodes
|
|
123
|
+
* @param toInsert string to insert
|
|
124
|
+
* @param file file to insert changes into
|
|
125
|
+
* @param fallbackPos position to insert if toInsert happens to be the first occurence
|
|
126
|
+
* @param syntaxKind the ts.SyntaxKind of the subchildren to insert after
|
|
127
|
+
* @return Change instance
|
|
128
|
+
* @throw Error if toInsert is first occurence but fall back is not set
|
|
129
|
+
*/
|
|
130
|
+
function insertAfterLastOccurrence(nodes, toInsert, file, fallbackPos, syntaxKind) {
|
|
131
|
+
var lastItem = nodes.sort(nodesByPosition).pop();
|
|
132
|
+
if (!lastItem) {
|
|
133
|
+
throw new Error();
|
|
134
|
+
}
|
|
135
|
+
if (syntaxKind) {
|
|
136
|
+
lastItem = findNodes(lastItem, syntaxKind).sort(nodesByPosition).pop();
|
|
137
|
+
}
|
|
138
|
+
if (!lastItem && fallbackPos == undefined) {
|
|
139
|
+
throw new Error("tried to insert " + toInsert + " as first occurence with no fallback position");
|
|
140
|
+
}
|
|
141
|
+
var lastItemPosition = lastItem ? lastItem.end : fallbackPos;
|
|
142
|
+
return new change_1.InsertChange(file, lastItemPosition, toInsert);
|
|
143
|
+
}
|
|
144
|
+
exports.insertAfterLastOccurrence = insertAfterLastOccurrence;
|
|
145
|
+
function getContentOfKeyLiteral(_source, node) {
|
|
146
|
+
if (node.kind == ts.SyntaxKind.Identifier) {
|
|
147
|
+
return node.text;
|
|
148
|
+
}
|
|
149
|
+
else if (node.kind == ts.SyntaxKind.StringLiteral) {
|
|
150
|
+
return node.text;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.getContentOfKeyLiteral = getContentOfKeyLiteral;
|
|
157
|
+
function _angularImportsFromNode(node, _sourceFile) {
|
|
158
|
+
var _a;
|
|
159
|
+
var ms = node.moduleSpecifier;
|
|
160
|
+
var modulePath;
|
|
161
|
+
switch (ms.kind) {
|
|
162
|
+
case ts.SyntaxKind.StringLiteral:
|
|
163
|
+
modulePath = ms.text;
|
|
164
|
+
break;
|
|
165
|
+
default:
|
|
166
|
+
return {};
|
|
167
|
+
}
|
|
168
|
+
if (!modulePath.startsWith('@angular/')) {
|
|
169
|
+
return {};
|
|
170
|
+
}
|
|
171
|
+
if (node.importClause) {
|
|
172
|
+
if (node.importClause.name) {
|
|
173
|
+
// This is of the form `import Name from 'path'`. Ignore.
|
|
174
|
+
return {};
|
|
175
|
+
}
|
|
176
|
+
else if (node.importClause.namedBindings) {
|
|
177
|
+
var nb = node.importClause.namedBindings;
|
|
178
|
+
if (nb.kind == ts.SyntaxKind.NamespaceImport) {
|
|
179
|
+
// This is of the form `import * as name from 'path'`. Return `name.`.
|
|
180
|
+
return _a = {},
|
|
181
|
+
_a[nb.name.text + '.'] = modulePath,
|
|
182
|
+
_a;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
// This is of the form `import {a,b,c} from 'path'`
|
|
186
|
+
var namedImports = nb;
|
|
187
|
+
return namedImports.elements
|
|
188
|
+
.map(function (is) {
|
|
189
|
+
return is.propertyName ? is.propertyName.text : is.name.text;
|
|
190
|
+
})
|
|
191
|
+
.reduce(function (acc, curr) {
|
|
192
|
+
acc[curr] = modulePath;
|
|
193
|
+
return acc;
|
|
194
|
+
}, {});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return {};
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
// This is of the form `import 'path';`. Nothing to do.
|
|
201
|
+
return {};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function getDecoratorMetadata(source, identifier, module) {
|
|
205
|
+
var angularImports = findNodes(source, ts.SyntaxKind.ImportDeclaration)
|
|
206
|
+
.map(function (node) {
|
|
207
|
+
return _angularImportsFromNode(node, source);
|
|
208
|
+
})
|
|
209
|
+
.reduce(function (acc, current) {
|
|
210
|
+
var e_2, _a;
|
|
211
|
+
try {
|
|
212
|
+
for (var _b = __values(Object.keys(current)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
213
|
+
var key = _c.value;
|
|
214
|
+
acc[key] = current[key];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
218
|
+
finally {
|
|
219
|
+
try {
|
|
220
|
+
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
|
|
221
|
+
}
|
|
222
|
+
finally { if (e_2) throw e_2.error; }
|
|
223
|
+
}
|
|
224
|
+
return acc;
|
|
225
|
+
}, {});
|
|
226
|
+
return getSourceNodes(source)
|
|
227
|
+
.filter(function (node) {
|
|
228
|
+
return (node.kind == ts.SyntaxKind.Decorator &&
|
|
229
|
+
node.expression.kind == ts.SyntaxKind.CallExpression);
|
|
230
|
+
})
|
|
231
|
+
.map(function (node) { return node.expression; })
|
|
232
|
+
.filter(function (expr) {
|
|
233
|
+
if (expr.expression.kind == ts.SyntaxKind.Identifier) {
|
|
234
|
+
var id = expr.expression;
|
|
235
|
+
return (id.getFullText(source) == identifier &&
|
|
236
|
+
angularImports[id.getFullText(source)] === module);
|
|
237
|
+
}
|
|
238
|
+
else if (expr.expression.kind == ts.SyntaxKind.PropertyAccessExpression) {
|
|
239
|
+
// This covers foo.NgModule when importing * as foo.
|
|
240
|
+
var paExpr = expr.expression;
|
|
241
|
+
// If the left expression is not an identifier, just give up at that point.
|
|
242
|
+
if (paExpr.expression.kind !== ts.SyntaxKind.Identifier) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
var id = paExpr.name.text;
|
|
246
|
+
var moduleId = paExpr.expression.getText(source);
|
|
247
|
+
return id === identifier && angularImports[moduleId + '.'] === module;
|
|
248
|
+
}
|
|
249
|
+
return false;
|
|
250
|
+
})
|
|
251
|
+
.filter(function (expr) {
|
|
252
|
+
return expr.arguments[0] &&
|
|
253
|
+
expr.arguments[0].kind == ts.SyntaxKind.ObjectLiteralExpression;
|
|
254
|
+
})
|
|
255
|
+
.map(function (expr) { return expr.arguments[0]; });
|
|
256
|
+
}
|
|
257
|
+
exports.getDecoratorMetadata = getDecoratorMetadata;
|
|
258
|
+
function _addSymbolToNgModuleMetadata(source, ngModulePath, metadataField, symbolName, importPath) {
|
|
259
|
+
var nodes = getDecoratorMetadata(source, 'NgModule', '@angular/core');
|
|
260
|
+
var node = nodes[0]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
261
|
+
// Find the decorator declaration.
|
|
262
|
+
if (!node) {
|
|
263
|
+
return [];
|
|
264
|
+
}
|
|
265
|
+
// Get all the children property assignment of object literals.
|
|
266
|
+
var matchingProperties = node.properties
|
|
267
|
+
.filter(function (prop) { return prop.kind == ts.SyntaxKind.PropertyAssignment; })
|
|
268
|
+
// Filter out every fields that's not "metadataField". Also handles string literals
|
|
269
|
+
// (but not expressions).
|
|
270
|
+
.filter(function (prop) {
|
|
271
|
+
var name = prop.name;
|
|
272
|
+
switch (name.kind) {
|
|
273
|
+
case ts.SyntaxKind.Identifier:
|
|
274
|
+
return name.getText(source) == metadataField;
|
|
275
|
+
case ts.SyntaxKind.StringLiteral:
|
|
276
|
+
return name.text == metadataField;
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
});
|
|
280
|
+
// Get the last node of the array literal.
|
|
281
|
+
if (!matchingProperties) {
|
|
282
|
+
return [];
|
|
283
|
+
}
|
|
284
|
+
if (matchingProperties.length == 0) {
|
|
285
|
+
// We haven't found the field in the metadata declaration. Insert a new field.
|
|
286
|
+
var expr = node;
|
|
287
|
+
var position_1;
|
|
288
|
+
var toInsert_1;
|
|
289
|
+
if (expr.properties.length == 0) {
|
|
290
|
+
position_1 = expr.getEnd() - 1;
|
|
291
|
+
toInsert_1 = " " + metadataField + ": [" + symbolName + "]\n";
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
node = expr.properties[expr.properties.length - 1];
|
|
295
|
+
position_1 = node.getEnd();
|
|
296
|
+
// Get the indentation of the last element, if any.
|
|
297
|
+
var text = node.getFullText(source);
|
|
298
|
+
var matches = text.match(/^\r?\n\s*/);
|
|
299
|
+
if (matches.length > 0) {
|
|
300
|
+
toInsert_1 = "," + matches[0] + metadataField + ": [" + symbolName + "]";
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
toInsert_1 = ", " + metadataField + ": [" + symbolName + "]";
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
var newMetadataProperty = new change_1.InsertChange(ngModulePath, position_1, toInsert_1);
|
|
307
|
+
var newMetadataImport = insertImport(source, ngModulePath, symbolName.replace(/\..*$/, ''), importPath);
|
|
308
|
+
return [newMetadataProperty, newMetadataImport];
|
|
309
|
+
}
|
|
310
|
+
var assignment = matchingProperties[0];
|
|
311
|
+
// If it's not an array, nothing we can do really.
|
|
312
|
+
if (assignment.initializer.kind !== ts.SyntaxKind.ArrayLiteralExpression) {
|
|
313
|
+
return [];
|
|
314
|
+
}
|
|
315
|
+
var arrLiteral = assignment.initializer;
|
|
316
|
+
if (arrLiteral.elements.length == 0) {
|
|
317
|
+
// Forward the property.
|
|
318
|
+
node = arrLiteral;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
node = arrLiteral.elements;
|
|
322
|
+
}
|
|
323
|
+
if (!node) {
|
|
324
|
+
console.log('No app module found. Please add your new class to your component.');
|
|
325
|
+
return [];
|
|
326
|
+
}
|
|
327
|
+
if (Array.isArray(node)) {
|
|
328
|
+
var nodeArray = node;
|
|
329
|
+
var symbolsArray = nodeArray.map(function (node) { return node.getText(); });
|
|
330
|
+
if (symbolsArray.includes(symbolName)) {
|
|
331
|
+
return [];
|
|
332
|
+
}
|
|
333
|
+
node = node[node.length - 1];
|
|
334
|
+
var effectsModule = nodeArray.find(function (node) {
|
|
335
|
+
return (node.getText().includes('EffectsModule.forRoot') &&
|
|
336
|
+
symbolName.includes('EffectsModule.forRoot')) ||
|
|
337
|
+
(node.getText().includes('EffectsModule.forFeature') &&
|
|
338
|
+
symbolName.includes('EffectsModule.forFeature'));
|
|
339
|
+
});
|
|
340
|
+
if (effectsModule && symbolName.includes('EffectsModule')) {
|
|
341
|
+
var effectsArgs = effectsModule.arguments.shift();
|
|
342
|
+
if (effectsArgs &&
|
|
343
|
+
effectsArgs.kind === ts.SyntaxKind.ArrayLiteralExpression) {
|
|
344
|
+
var effectsElements = effectsArgs
|
|
345
|
+
.elements;
|
|
346
|
+
var _a = __read(symbolName.match(/\[(.*)\]/), 2), effectsSymbol = _a[1];
|
|
347
|
+
var epos = void 0;
|
|
348
|
+
if (effectsElements.length === 0) {
|
|
349
|
+
epos = effectsArgs.getStart() + 1;
|
|
350
|
+
return [new change_1.InsertChange(ngModulePath, epos, effectsSymbol)];
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
var lastEffect = effectsElements[effectsElements.length - 1];
|
|
354
|
+
epos = lastEffect.getEnd();
|
|
355
|
+
// Get the indentation of the last element, if any.
|
|
356
|
+
var text = lastEffect.getFullText(source);
|
|
357
|
+
var effectInsert = void 0;
|
|
358
|
+
if (text.match('^\r?\r?\n')) {
|
|
359
|
+
effectInsert = "," + text.match(/^\r?\n\s+/)[0] + effectsSymbol;
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
effectInsert = ", " + effectsSymbol;
|
|
363
|
+
}
|
|
364
|
+
return [new change_1.InsertChange(ngModulePath, epos, effectInsert)];
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
return [];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
var toInsert;
|
|
373
|
+
var position = node.getEnd();
|
|
374
|
+
if (node.kind == ts.SyntaxKind.ObjectLiteralExpression) {
|
|
375
|
+
// We haven't found the field in the metadata declaration. Insert a new
|
|
376
|
+
// field.
|
|
377
|
+
var expr = node;
|
|
378
|
+
if (expr.properties.length == 0) {
|
|
379
|
+
position = expr.getEnd() - 1;
|
|
380
|
+
toInsert = " " + metadataField + ": [" + symbolName + "]\n";
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
node = expr.properties[expr.properties.length - 1];
|
|
384
|
+
position = node.getEnd();
|
|
385
|
+
// Get the indentation of the last element, if any.
|
|
386
|
+
var text = node.getFullText(source);
|
|
387
|
+
if (text.match('^\r?\r?\n')) {
|
|
388
|
+
toInsert = "," + text.match(/^\r?\n\s+/)[0] + metadataField + ": [" + symbolName + "]";
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
toInsert = ", " + metadataField + ": [" + symbolName + "]";
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
else if (node.kind == ts.SyntaxKind.ArrayLiteralExpression) {
|
|
396
|
+
// We found the field but it's empty. Insert it just before the `]`.
|
|
397
|
+
position--;
|
|
398
|
+
toInsert = "" + symbolName;
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
// Get the indentation of the last element, if any.
|
|
402
|
+
var text = node.getFullText(source);
|
|
403
|
+
if (text.match(/^\r?\n/)) {
|
|
404
|
+
toInsert = "," + text.match(/^\r?\n(\r?)\s+/)[0] + symbolName;
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
toInsert = ", " + symbolName;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
var insert = new change_1.InsertChange(ngModulePath, position, toInsert);
|
|
411
|
+
var importInsert = insertImport(source, ngModulePath, symbolName.replace(/\..*$/, ''), importPath);
|
|
412
|
+
return [insert, importInsert];
|
|
413
|
+
}
|
|
414
|
+
function _addSymbolToComponentMetadata(source, componentPath, metadataField, symbolName, importPath) {
|
|
415
|
+
var nodes = getDecoratorMetadata(source, 'Component', '@angular/core');
|
|
416
|
+
var node = nodes[0]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
417
|
+
// Find the decorator declaration.
|
|
418
|
+
if (!node) {
|
|
419
|
+
return [];
|
|
420
|
+
}
|
|
421
|
+
// Get all the children property assignment of object literals.
|
|
422
|
+
var matchingProperties = node.properties
|
|
423
|
+
.filter(function (prop) { return prop.kind == ts.SyntaxKind.PropertyAssignment; })
|
|
424
|
+
// Filter out every fields that's not "metadataField". Also handles string literals
|
|
425
|
+
// (but not expressions).
|
|
426
|
+
.filter(function (prop) {
|
|
427
|
+
var name = prop.name;
|
|
428
|
+
switch (name.kind) {
|
|
429
|
+
case ts.SyntaxKind.Identifier:
|
|
430
|
+
return name.getText(source) == metadataField;
|
|
431
|
+
case ts.SyntaxKind.StringLiteral:
|
|
432
|
+
return name.text == metadataField;
|
|
433
|
+
}
|
|
434
|
+
return false;
|
|
435
|
+
});
|
|
436
|
+
// Get the last node of the array literal.
|
|
437
|
+
if (!matchingProperties) {
|
|
438
|
+
return [];
|
|
439
|
+
}
|
|
440
|
+
if (matchingProperties.length == 0) {
|
|
441
|
+
// We haven't found the field in the metadata declaration. Insert a new field.
|
|
442
|
+
var expr = node;
|
|
443
|
+
var position_2;
|
|
444
|
+
var toInsert_2;
|
|
445
|
+
if (expr.properties.length == 0) {
|
|
446
|
+
position_2 = expr.getEnd() - 1;
|
|
447
|
+
toInsert_2 = " " + metadataField + ": [" + symbolName + "]\n";
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
node = expr.properties[expr.properties.length - 1];
|
|
451
|
+
position_2 = node.getEnd();
|
|
452
|
+
// Get the indentation of the last element, if any.
|
|
453
|
+
var text = node.getFullText(source);
|
|
454
|
+
var matches = text.match(/^\r?\n\s*/);
|
|
455
|
+
if (matches.length > 0) {
|
|
456
|
+
toInsert_2 = "," + matches[0] + metadataField + ": [" + symbolName + "]";
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
toInsert_2 = ", " + metadataField + ": [" + symbolName + "]";
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
var newMetadataProperty = new change_1.InsertChange(componentPath, position_2, toInsert_2);
|
|
463
|
+
var newMetadataImport = insertImport(source, componentPath, symbolName.replace(/\..*$/, ''), importPath);
|
|
464
|
+
return [newMetadataProperty, newMetadataImport];
|
|
465
|
+
}
|
|
466
|
+
var assignment = matchingProperties[0];
|
|
467
|
+
// If it's not an array, nothing we can do really.
|
|
468
|
+
if (assignment.initializer.kind !== ts.SyntaxKind.ArrayLiteralExpression) {
|
|
469
|
+
return [];
|
|
470
|
+
}
|
|
471
|
+
var arrLiteral = assignment.initializer;
|
|
472
|
+
if (arrLiteral.elements.length == 0) {
|
|
473
|
+
// Forward the property.
|
|
474
|
+
node = arrLiteral;
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
node = arrLiteral.elements;
|
|
478
|
+
}
|
|
479
|
+
if (!node) {
|
|
480
|
+
console.log('No component found. Please add your new class to your component.');
|
|
481
|
+
return [];
|
|
482
|
+
}
|
|
483
|
+
if (Array.isArray(node)) {
|
|
484
|
+
var nodeArray = node;
|
|
485
|
+
var symbolsArray = nodeArray.map(function (node) { return node.getText(); });
|
|
486
|
+
if (symbolsArray.includes(symbolName)) {
|
|
487
|
+
return [];
|
|
488
|
+
}
|
|
489
|
+
node = node[node.length - 1];
|
|
490
|
+
}
|
|
491
|
+
var toInsert;
|
|
492
|
+
var position = node.getEnd();
|
|
493
|
+
if (node.kind == ts.SyntaxKind.ObjectLiteralExpression) {
|
|
494
|
+
// We haven't found the field in the metadata declaration. Insert a new
|
|
495
|
+
// field.
|
|
496
|
+
var expr = node;
|
|
497
|
+
if (expr.properties.length == 0) {
|
|
498
|
+
position = expr.getEnd() - 1;
|
|
499
|
+
toInsert = " " + metadataField + ": [" + symbolName + "]\n";
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
node = expr.properties[expr.properties.length - 1];
|
|
503
|
+
position = node.getEnd();
|
|
504
|
+
// Get the indentation of the last element, if any.
|
|
505
|
+
var text = node.getFullText(source);
|
|
506
|
+
if (text.match('^\r?\r?\n')) {
|
|
507
|
+
toInsert = "," + text.match(/^\r?\n\s+/)[0] + metadataField + ": [" + symbolName + "]";
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
toInsert = ", " + metadataField + ": [" + symbolName + "]";
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
else if (node.kind == ts.SyntaxKind.ArrayLiteralExpression) {
|
|
515
|
+
// We found the field but it's empty. Insert it just before the `]`.
|
|
516
|
+
position--;
|
|
517
|
+
toInsert = "" + symbolName;
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
// Get the indentation of the last element, if any.
|
|
521
|
+
var text = node.getFullText(source);
|
|
522
|
+
if (text.match(/^\r?\n/)) {
|
|
523
|
+
toInsert = "," + text.match(/^\r?\n(\r?)\s+/)[0] + symbolName;
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
toInsert = ", " + symbolName;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
var insert = new change_1.InsertChange(componentPath, position, toInsert);
|
|
530
|
+
var importInsert = insertImport(source, componentPath, symbolName.replace(/\..*$/, ''), importPath);
|
|
531
|
+
return [insert, importInsert];
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Custom function to insert a declaration (component, pipe, directive)
|
|
535
|
+
* into NgModule declarations. It also imports the component.
|
|
536
|
+
*/
|
|
537
|
+
function addDeclarationToModule(source, modulePath, classifiedName, importPath) {
|
|
538
|
+
return _addSymbolToNgModuleMetadata(source, modulePath, 'declarations', classifiedName, importPath);
|
|
539
|
+
}
|
|
540
|
+
exports.addDeclarationToModule = addDeclarationToModule;
|
|
541
|
+
/**
|
|
542
|
+
* Custom function to insert a declaration (component, pipe, directive)
|
|
543
|
+
* into NgModule declarations. It also imports the component.
|
|
544
|
+
*/
|
|
545
|
+
function addImportToModule(source, modulePath, classifiedName, importPath) {
|
|
546
|
+
return _addSymbolToNgModuleMetadata(source, modulePath, 'imports', classifiedName, importPath);
|
|
547
|
+
}
|
|
548
|
+
exports.addImportToModule = addImportToModule;
|
|
549
|
+
/**
|
|
550
|
+
* Custom function to insert a provider into NgModule. It also imports it.
|
|
551
|
+
*/
|
|
552
|
+
function addProviderToModule(source, modulePath, classifiedName, importPath) {
|
|
553
|
+
return _addSymbolToNgModuleMetadata(source, modulePath, 'providers', classifiedName, importPath);
|
|
554
|
+
}
|
|
555
|
+
exports.addProviderToModule = addProviderToModule;
|
|
556
|
+
/**
|
|
557
|
+
* Custom function to insert a provider into Component. It also imports it.
|
|
558
|
+
*/
|
|
559
|
+
function addProviderToComponent(source, componentPath, classifiedName, importPath) {
|
|
560
|
+
return _addSymbolToComponentMetadata(source, componentPath, 'providers', classifiedName, importPath);
|
|
561
|
+
}
|
|
562
|
+
exports.addProviderToComponent = addProviderToComponent;
|
|
563
|
+
/**
|
|
564
|
+
* Custom function to insert an export into NgModule. It also imports it.
|
|
565
|
+
*/
|
|
566
|
+
function addExportToModule(source, modulePath, classifiedName, importPath) {
|
|
567
|
+
return _addSymbolToNgModuleMetadata(source, modulePath, 'exports', classifiedName, importPath);
|
|
568
|
+
}
|
|
569
|
+
exports.addExportToModule = addExportToModule;
|
|
570
|
+
/**
|
|
571
|
+
* Custom function to insert an export into NgModule. It also imports it.
|
|
572
|
+
*/
|
|
573
|
+
function addBootstrapToModule(source, modulePath, classifiedName, importPath) {
|
|
574
|
+
return _addSymbolToNgModuleMetadata(source, modulePath, 'bootstrap', classifiedName, importPath);
|
|
575
|
+
}
|
|
576
|
+
exports.addBootstrapToModule = addBootstrapToModule;
|
|
577
|
+
/**
|
|
578
|
+
* Add Import `import { symbolName } from fileName` if the import doesn't exit
|
|
579
|
+
* already. Assumes fileToEdit can be resolved and accessed.
|
|
580
|
+
* @param fileToEdit (file we want to add import to)
|
|
581
|
+
* @param symbolName (item to import)
|
|
582
|
+
* @param fileName (path to the file)
|
|
583
|
+
* @param isDefault (if true, import follows style for importing default exports)
|
|
584
|
+
* @return Change
|
|
585
|
+
*/
|
|
586
|
+
function insertImport(source, fileToEdit, symbolName, fileName, isDefault) {
|
|
587
|
+
if (isDefault === void 0) { isDefault = false; }
|
|
588
|
+
var rootNode = source;
|
|
589
|
+
var allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration);
|
|
590
|
+
// get nodes that map to import statements from the file fileName
|
|
591
|
+
var relevantImports = allImports.filter(function (node) {
|
|
592
|
+
// StringLiteral of the ImportDeclaration is the import file (fileName in this case).
|
|
593
|
+
var importFiles = node
|
|
594
|
+
.getChildren()
|
|
595
|
+
.filter(function (child) { return child.kind === ts.SyntaxKind.StringLiteral; })
|
|
596
|
+
.map(function (n) { return n.text; });
|
|
597
|
+
return importFiles.filter(function (file) { return file === fileName; }).length === 1;
|
|
598
|
+
});
|
|
599
|
+
if (relevantImports.length > 0) {
|
|
600
|
+
var importsAsterisk_1 = false;
|
|
601
|
+
// imports from import file
|
|
602
|
+
var imports_1 = [];
|
|
603
|
+
relevantImports.forEach(function (n) {
|
|
604
|
+
Array.prototype.push.apply(imports_1, findNodes(n, ts.SyntaxKind.Identifier));
|
|
605
|
+
if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) {
|
|
606
|
+
importsAsterisk_1 = true;
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
// if imports * from fileName, don't add symbolName
|
|
610
|
+
if (importsAsterisk_1) {
|
|
611
|
+
return new change_1.NoopChange();
|
|
612
|
+
}
|
|
613
|
+
var importTextNodes = imports_1.filter(function (n) { return n.text === symbolName; });
|
|
614
|
+
// insert import if it's not there
|
|
615
|
+
if (importTextNodes.length === 0) {
|
|
616
|
+
var fallbackPos_1 = findNodes(relevantImports[0], ts.SyntaxKind.CloseBraceToken)[0].getStart() ||
|
|
617
|
+
findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart();
|
|
618
|
+
return insertAfterLastOccurrence(imports_1, ", " + symbolName, fileToEdit, fallbackPos_1);
|
|
619
|
+
}
|
|
620
|
+
return new change_1.NoopChange();
|
|
621
|
+
}
|
|
622
|
+
// no such import declaration exists
|
|
623
|
+
var useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter(function (n) { return n.getText() === 'use strict'; });
|
|
624
|
+
var fallbackPos = 0;
|
|
625
|
+
if (useStrict.length > 0) {
|
|
626
|
+
fallbackPos = useStrict[0].end;
|
|
627
|
+
}
|
|
628
|
+
var open = isDefault ? '' : '{ ';
|
|
629
|
+
var close = isDefault ? '' : ' }';
|
|
630
|
+
// if there are no imports or 'use strict' statement, insert import at beginning of file
|
|
631
|
+
var insertAtBeginning = allImports.length === 0 && useStrict.length === 0;
|
|
632
|
+
var separator = insertAtBeginning ? '' : ';\n';
|
|
633
|
+
var toInsert = separator + "import " + open + symbolName + close +
|
|
634
|
+
(" from '" + fileName + "'" + (insertAtBeginning ? ';\n' : ''));
|
|
635
|
+
return insertAfterLastOccurrence(allImports, toInsert, fileToEdit, fallbackPos, ts.SyntaxKind.StringLiteral);
|
|
636
|
+
}
|
|
637
|
+
exports.insertImport = insertImport;
|
|
638
|
+
function replaceImport(sourceFile, path, importFrom, importAsIs, importToBe) {
|
|
639
|
+
var imports = sourceFile.statements
|
|
640
|
+
.filter(ts.isImportDeclaration)
|
|
641
|
+
.filter(function (_a) {
|
|
642
|
+
var moduleSpecifier = _a.moduleSpecifier;
|
|
643
|
+
return moduleSpecifier.getText(sourceFile) === "'" + importFrom + "'" ||
|
|
644
|
+
moduleSpecifier.getText(sourceFile) === "\"" + importFrom + "\"";
|
|
645
|
+
});
|
|
646
|
+
if (imports.length === 0) {
|
|
647
|
+
return [];
|
|
648
|
+
}
|
|
649
|
+
var importText = function (specifier) {
|
|
650
|
+
if (specifier.name.text) {
|
|
651
|
+
return specifier.name.text;
|
|
652
|
+
}
|
|
653
|
+
// if import is renamed
|
|
654
|
+
if (specifier.propertyName && specifier.propertyName.text) {
|
|
655
|
+
return specifier.propertyName.text;
|
|
656
|
+
}
|
|
657
|
+
return '';
|
|
658
|
+
};
|
|
659
|
+
var changes = imports.map(function (p) {
|
|
660
|
+
var _a;
|
|
661
|
+
var namedImports = (_a = p === null || p === void 0 ? void 0 : p.importClause) === null || _a === void 0 ? void 0 : _a.namedBindings;
|
|
662
|
+
if (!namedImports) {
|
|
663
|
+
return [];
|
|
664
|
+
}
|
|
665
|
+
var importSpecifiers = namedImports.elements;
|
|
666
|
+
var isAlreadyImported = importSpecifiers
|
|
667
|
+
.map(importText)
|
|
668
|
+
.includes(importToBe);
|
|
669
|
+
var importChanges = importSpecifiers.map(function (specifier, index) {
|
|
670
|
+
var text = importText(specifier);
|
|
671
|
+
// import is not the one we're looking for, can be skipped
|
|
672
|
+
if (text !== importAsIs) {
|
|
673
|
+
return undefined;
|
|
674
|
+
}
|
|
675
|
+
// identifier has not been imported, simply replace the old text with the new text
|
|
676
|
+
if (!isAlreadyImported) {
|
|
677
|
+
return change_1.createReplaceChange(sourceFile, specifier, importAsIs, importToBe);
|
|
678
|
+
}
|
|
679
|
+
var nextIdentifier = importSpecifiers[index + 1];
|
|
680
|
+
// identifer is not the last, also clean up the comma
|
|
681
|
+
if (nextIdentifier) {
|
|
682
|
+
return change_1.createRemoveChange(sourceFile, specifier, specifier.getStart(sourceFile), nextIdentifier.getStart(sourceFile));
|
|
683
|
+
}
|
|
684
|
+
// there are no imports following, just remove it
|
|
685
|
+
return change_1.createRemoveChange(sourceFile, specifier, specifier.getStart(sourceFile), specifier.getEnd());
|
|
686
|
+
});
|
|
687
|
+
return importChanges.filter(Boolean);
|
|
688
|
+
});
|
|
689
|
+
return changes.reduce(function (imports, curr) { return imports.concat(curr); }, []);
|
|
690
|
+
}
|
|
691
|
+
exports.replaceImport = replaceImport;
|
|
692
|
+
function containsProperty(objectLiteral, propertyName) {
|
|
693
|
+
return (objectLiteral &&
|
|
694
|
+
objectLiteral.properties.some(function (prop) {
|
|
695
|
+
return ts.isPropertyAssignment(prop) &&
|
|
696
|
+
ts.isIdentifier(prop.name) &&
|
|
697
|
+
prop.name.text === propertyName;
|
|
698
|
+
}));
|
|
699
|
+
}
|
|
700
|
+
exports.containsProperty = containsProperty;
|
|
701
|
+
//# sourceMappingURL=ast-utils.js.map
|