@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.
Files changed (72) hide show
  1. package/README.md +5 -0
  2. package/bundles/ngrx-store-devtools.umd.js +1318 -0
  3. package/bundles/ngrx-store-devtools.umd.js.map +1 -0
  4. package/esm2015/index.js +7 -0
  5. package/esm2015/ngrx-store-devtools.js +9 -0
  6. package/esm2015/public_api.js +2 -0
  7. package/esm2015/src/actions.js +97 -0
  8. package/esm2015/src/config.js +61 -0
  9. package/esm2015/src/devtools-dispatcher.js +9 -0
  10. package/esm2015/src/devtools.js +115 -0
  11. package/esm2015/src/extension.js +160 -0
  12. package/esm2015/src/index.js +5 -0
  13. package/esm2015/src/instrument.js +67 -0
  14. package/esm2015/src/reducer.js +365 -0
  15. package/esm2015/src/utils.js +106 -0
  16. package/fesm2015/ngrx-store-devtools.js +964 -0
  17. package/fesm2015/ngrx-store-devtools.js.map +1 -0
  18. package/index.d.ts +6 -0
  19. package/migrations/6_0_0/index.js +8 -0
  20. package/migrations/6_0_0/index.js.map +1 -0
  21. package/migrations/migration.json +10 -0
  22. package/ngrx-store-devtools.d.ts +8 -0
  23. package/ngrx-store-devtools.metadata.json +1 -0
  24. package/package.json +52 -0
  25. package/public_api.d.ts +1 -0
  26. package/schematics/collection.json +10 -0
  27. package/schematics/ng-add/index.js +110 -0
  28. package/schematics/ng-add/index.js.map +1 -0
  29. package/schematics/ng-add/schema.js +3 -0
  30. package/schematics/ng-add/schema.js.map +1 -0
  31. package/schematics/ng-add/schema.json +42 -0
  32. package/schematics-core/index.js +86 -0
  33. package/schematics-core/index.js.map +1 -0
  34. package/schematics-core/utility/angular-utils.js +33 -0
  35. package/schematics-core/utility/angular-utils.js.map +1 -0
  36. package/schematics-core/utility/ast-utils.js +701 -0
  37. package/schematics-core/utility/ast-utils.js.map +1 -0
  38. package/schematics-core/utility/change.js +162 -0
  39. package/schematics-core/utility/change.js.map +1 -0
  40. package/schematics-core/utility/config.js +21 -0
  41. package/schematics-core/utility/config.js.map +1 -0
  42. package/schematics-core/utility/find-component.js +101 -0
  43. package/schematics-core/utility/find-component.js.map +1 -0
  44. package/schematics-core/utility/find-module.js +102 -0
  45. package/schematics-core/utility/find-module.js.map +1 -0
  46. package/schematics-core/utility/json-utilts.js +37 -0
  47. package/schematics-core/utility/json-utilts.js.map +1 -0
  48. package/schematics-core/utility/libs-version.js +5 -0
  49. package/schematics-core/utility/libs-version.js.map +1 -0
  50. package/schematics-core/utility/ngrx-utils.js +246 -0
  51. package/schematics-core/utility/ngrx-utils.js.map +1 -0
  52. package/schematics-core/utility/package.js +23 -0
  53. package/schematics-core/utility/package.js.map +1 -0
  54. package/schematics-core/utility/parse-name.js +14 -0
  55. package/schematics-core/utility/parse-name.js.map +1 -0
  56. package/schematics-core/utility/project.js +35 -0
  57. package/schematics-core/utility/project.js.map +1 -0
  58. package/schematics-core/utility/strings.js +138 -0
  59. package/schematics-core/utility/strings.js.map +1 -0
  60. package/schematics-core/utility/update.js +34 -0
  61. package/schematics-core/utility/update.js.map +1 -0
  62. package/schematics-core/utility/visitors.js +250 -0
  63. package/schematics-core/utility/visitors.js.map +1 -0
  64. package/src/actions.d.ts +79 -0
  65. package/src/config.d.ts +113 -0
  66. package/src/devtools-dispatcher.d.ts +3 -0
  67. package/src/devtools.d.ts +31 -0
  68. package/src/extension.d.ts +46 -0
  69. package/src/index.d.ts +4 -0
  70. package/src/instrument.d.ts +12 -0
  71. package/src/reducer.d.ts +47 -0
  72. 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