@craft-ng/dev-tools 0.1.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.
@@ -0,0 +1,1124 @@
1
+ import { __awaiter } from "tslib";
2
+ import { Node, Project, QuoteKind, SyntaxKind, ts, } from 'ts-morph';
3
+ import { existsSync, readdirSync, statSync } from 'node:fs';
4
+ import { basename, extname, isAbsolute, join, resolve } from 'node:path';
5
+ const SUPPORTED_DECORATORS = {
6
+ Component: 'component',
7
+ Directive: 'directive',
8
+ Pipe: 'pipe',
9
+ Injectable: 'injectable',
10
+ };
11
+ const DEFAULT_OPTIONS = {
12
+ helperImportPath: '@craft-ng/core',
13
+ transformOnlyStandaloneDeclarables: false,
14
+ includeProviders: true,
15
+ includeViewProviders: true,
16
+ };
17
+ const PRIMITIVE_TYPE_TEXTS = new Set([
18
+ 'any',
19
+ 'bigint',
20
+ 'boolean',
21
+ 'false',
22
+ 'never',
23
+ 'null',
24
+ 'number',
25
+ 'object',
26
+ 'string',
27
+ 'symbol',
28
+ 'true',
29
+ 'undefined',
30
+ 'unknown',
31
+ 'void',
32
+ 'Array',
33
+ 'Boolean',
34
+ 'Number',
35
+ 'Object',
36
+ 'ReadonlyArray',
37
+ 'String',
38
+ ]);
39
+ const GENERATED_FILE_SUFFIXES = [
40
+ '.d.ts',
41
+ '.gen.ts',
42
+ '.generated.ts',
43
+ '.ngfactory.ts',
44
+ '.ngsummary.ts',
45
+ '.ngtypecheck.ts',
46
+ ];
47
+ const IGNORED_DIRECTORIES = new Set([
48
+ '.angular',
49
+ '.git',
50
+ '.nx',
51
+ '.turbo',
52
+ 'coverage',
53
+ 'dist',
54
+ 'node_modules',
55
+ 'out-tsc',
56
+ 'tmp',
57
+ ]);
58
+ export function transformSourceFile(sourceFile, options = {}) {
59
+ const normalizedOptions = normalizeOptions(options);
60
+ const analysis = analyzeSourceFileDependencies(sourceFile, options);
61
+ const result = Object.assign(Object.assign({}, analysis), { changed: false });
62
+ const { angularKind, classDeclaration, className } = analysis;
63
+ if (analysis.skipped || !classDeclaration || !angularKind || !className) {
64
+ return result;
65
+ }
66
+ const exportSafety = getExportRewriteSafety(sourceFile, classDeclaration, className);
67
+ if (!exportSafety.safe) {
68
+ return skip(result, exportSafety.warnings);
69
+ }
70
+ const importSafety = getHelperImportSafety(sourceFile, normalizedOptions.helperImportPath);
71
+ if (!importSafety.safe) {
72
+ return skip(result, importSafety.warnings);
73
+ }
74
+ removeConflictingExports(sourceFile, classDeclaration, className);
75
+ ensureHelperImports(sourceFile, normalizedOptions.helperImportPath);
76
+ writeDefaultBrandExport(sourceFile, className, result.dependencyGroups);
77
+ result.changed = true;
78
+ return result;
79
+ }
80
+ export function analyzeSourceFileDependencies(sourceFile, options = {}) {
81
+ const normalizedOptions = normalizeOptions(options);
82
+ const result = {
83
+ skipped: false,
84
+ warnings: [],
85
+ dependencies: [],
86
+ dependencyGroups: emptyDependencyGroups(),
87
+ };
88
+ const angularClass = findAngularDecoratedClass(sourceFile);
89
+ result.warnings.push(...angularClass.warnings);
90
+ result.angularKind = angularClass.angularKind;
91
+ result.className = angularClass.className;
92
+ result.classDeclaration = angularClass.classDeclaration;
93
+ if (angularClass.skipped) {
94
+ result.skipped = true;
95
+ return result;
96
+ }
97
+ if (!angularClass.classDeclaration) {
98
+ return result;
99
+ }
100
+ const { angularKind, classDeclaration, className } = angularClass;
101
+ if (!angularKind || !className) {
102
+ result.skipped = true;
103
+ result.warnings.push('Angular class name or kind could not be resolved.');
104
+ return result;
105
+ }
106
+ if (normalizedOptions.transformOnlyStandaloneDeclarables &&
107
+ (angularKind === 'component' || angularKind === 'directive') &&
108
+ !isStandaloneDeclarable(classDeclaration)) {
109
+ result.skipped = true;
110
+ result.warnings.push(`${decoratorLabel(angularKind)} ${className} is not standalone and transformOnlyStandaloneDeclarables is enabled.`);
111
+ return result;
112
+ }
113
+ const metadataDeps = angularKind === 'component' || angularKind === 'directive'
114
+ ? extractDecoratorMetadataDepGroups(classDeclaration, angularKind, normalizedOptions)
115
+ : emptyMetadataDependencyGroups();
116
+ const constructorDeps = extractConstructorDeps(classDeclaration);
117
+ const injectCallDeps = extractInjectCallDeps(classDeclaration);
118
+ result.warnings.push(...metadataDeps.warnings, ...constructorDeps.warnings, ...injectCallDeps.warnings);
119
+ result.dependencies = mergeDeps(constructorDeps.dependencies, injectCallDeps.dependencies, metadataDeps.imports, metadataDeps.hostDirectives, metadataDeps.providers, metadataDeps.viewProviders);
120
+ result.dependencyGroups = {
121
+ injected: mergeDeps(constructorDeps.dependencies, injectCallDeps.dependencies),
122
+ importDeps: mergeDeps(metadataDeps.imports, metadataDeps.hostDirectives),
123
+ providers: mergeDeps(metadataDeps.providers, metadataDeps.viewProviders),
124
+ };
125
+ return result;
126
+ }
127
+ export function findAngularDecoratedClass(sourceFile) {
128
+ const decoratedClasses = sourceFile
129
+ .getClasses()
130
+ .map((classDeclaration) => {
131
+ const angularKind = getAngularKind(classDeclaration);
132
+ return angularKind ? { classDeclaration, angularKind } : undefined;
133
+ })
134
+ .filter((entry) => Boolean(entry));
135
+ if (decoratedClasses.length === 0) {
136
+ return { skipped: false, warnings: [] };
137
+ }
138
+ if (decoratedClasses.length > 1) {
139
+ return {
140
+ skipped: true,
141
+ warnings: [
142
+ `Skipped file because it contains ${decoratedClasses.length} supported Angular classes.`,
143
+ ],
144
+ };
145
+ }
146
+ const [{ classDeclaration, angularKind }] = decoratedClasses;
147
+ const className = classDeclaration.getName();
148
+ if (!className) {
149
+ return {
150
+ classDeclaration,
151
+ angularKind,
152
+ skipped: true,
153
+ warnings: ['Skipped anonymous default-exported Angular class.'],
154
+ };
155
+ }
156
+ return {
157
+ classDeclaration,
158
+ angularKind,
159
+ className,
160
+ skipped: false,
161
+ warnings: [],
162
+ };
163
+ }
164
+ export function getAngularKind(classDeclaration) {
165
+ for (const decorator of classDeclaration.getDecorators()) {
166
+ const decoratorName = getDecoratorName(decorator);
167
+ if (decoratorName && decoratorName in SUPPORTED_DECORATORS) {
168
+ return SUPPORTED_DECORATORS[decoratorName];
169
+ }
170
+ }
171
+ return undefined;
172
+ }
173
+ export function isStandaloneDeclarable(classDeclaration) {
174
+ const angularKind = getAngularKind(classDeclaration);
175
+ if (angularKind !== 'component' && angularKind !== 'directive') {
176
+ return false;
177
+ }
178
+ const metadata = getDecoratorMetadataObject(classDeclaration);
179
+ const standaloneProperty = metadata
180
+ ? getObjectPropertyAssignment(metadata, 'standalone')
181
+ : undefined;
182
+ const initializer = standaloneProperty === null || standaloneProperty === void 0 ? void 0 : standaloneProperty.getInitializer();
183
+ return Node.isTrueLiteral(initializer);
184
+ }
185
+ export function extractDecoratorMetadataDeps(classDeclaration, angularKind = getAngularKind(classDeclaration), options = {}) {
186
+ if (angularKind !== 'component' && angularKind !== 'directive') {
187
+ return { dependencies: [], warnings: [] };
188
+ }
189
+ const groups = extractDecoratorMetadataDepGroups(classDeclaration, angularKind, normalizeOptions(options));
190
+ return {
191
+ dependencies: mergeDeps(groups.imports, groups.hostDirectives, groups.providers, groups.viewProviders),
192
+ warnings: groups.warnings,
193
+ };
194
+ }
195
+ export function extractConstructorDeps(classDeclaration) {
196
+ const warnings = [];
197
+ const dependencies = [];
198
+ for (const constructorDeclaration of classDeclaration.getConstructors()) {
199
+ for (const parameter of constructorDeclaration.getParameters()) {
200
+ const injectToken = getInjectDecoratorToken(parameter.getDecorators(), warnings);
201
+ if (injectToken.found) {
202
+ if (injectToken.dependency) {
203
+ dependencies.push(injectToken.dependency);
204
+ }
205
+ continue;
206
+ }
207
+ const typeNode = parameter.getTypeNode();
208
+ if (!typeNode) {
209
+ warnings.push(`Skipped constructor parameter "${parameter.getName()}" because it has no type.`);
210
+ continue;
211
+ }
212
+ const dependency = getDependencyTextFromTypeNode(typeNode);
213
+ if (!dependency) {
214
+ warnings.push(`Skipped constructor parameter "${parameter.getName()}" because type "${typeNode.getText()}" is not a static Angular dependency.`);
215
+ continue;
216
+ }
217
+ if (!isRuntimeSafeTypeDependency(typeNode, dependency)) {
218
+ warnings.push(`Skipped constructor dependency "${dependency}" because it is unresolved, type-only, or not a runtime value.`);
219
+ continue;
220
+ }
221
+ dependencies.push(dependency);
222
+ }
223
+ }
224
+ return { dependencies: mergeDeps(dependencies), warnings };
225
+ }
226
+ export function extractInjectCallDeps(classDeclaration) {
227
+ var _a;
228
+ const warnings = [];
229
+ const dependencies = [];
230
+ for (const callExpression of classDeclaration.getDescendantsOfKind(SyntaxKind.CallExpression)) {
231
+ const expression = callExpression.getExpression();
232
+ const injectMethodName = getInjectMethodName(expression);
233
+ if (!(injectMethodName === null || injectMethodName === void 0 ? void 0 : injectMethodName.startsWith('inject'))) {
234
+ continue;
235
+ }
236
+ const dependency = injectMethodName === 'inject'
237
+ ? getAngularInjectCallDependency(callExpression)
238
+ : getInjectionHelperDependency(expression);
239
+ if (!dependency) {
240
+ warnings.push(`Skipped ${injectMethodName}() call in ${(_a = classDeclaration.getName()) !== null && _a !== void 0 ? _a : 'anonymous class'} because the injection dependency is not static.`);
241
+ continue;
242
+ }
243
+ dependencies.push(dependency);
244
+ }
245
+ return { dependencies: mergeDeps(dependencies), warnings };
246
+ }
247
+ export function mergeDeps(...dependencyGroups) {
248
+ const seen = new Set();
249
+ const dependencies = [];
250
+ for (const group of dependencyGroups) {
251
+ for (const dependency of group) {
252
+ if (seen.has(dependency)) {
253
+ continue;
254
+ }
255
+ seen.add(dependency);
256
+ dependencies.push(dependency);
257
+ }
258
+ }
259
+ return dependencies;
260
+ }
261
+ function emptyDependencyGroups() {
262
+ return {
263
+ injected: [],
264
+ importDeps: [],
265
+ providers: [],
266
+ };
267
+ }
268
+ function createDepsExpression(dependencyGroups) {
269
+ return `deps({ injected: [${dependencyGroups.injected.join(', ')}], importDeps: [${dependencyGroups.importDeps.join(', ')}], providers: [${dependencyGroups.providers.join(', ')}] })`;
270
+ }
271
+ function invalidExistingDependencyGroups(node, warnings) {
272
+ return {
273
+ found: true,
274
+ warnings,
275
+ dependencyGroups: emptyDependencyGroups(),
276
+ exportAssignmentNode: node,
277
+ depsObjectNode: node,
278
+ propertyNodes: {},
279
+ };
280
+ }
281
+ function readExistingDependencyGroupProperty(objectLiteral, propertyName, warnings, propertyNodes) {
282
+ const property = getObjectPropertyAssignment(objectLiteral, propertyName);
283
+ if (!property) {
284
+ warnings.push(`deps(...) is missing the "${propertyName}" array.`);
285
+ return [];
286
+ }
287
+ propertyNodes[propertyName] = property;
288
+ const initializer = property.getInitializer();
289
+ if (!Node.isArrayLiteralExpression(initializer)) {
290
+ warnings.push(`deps.${propertyName} must be a static array.`);
291
+ return [];
292
+ }
293
+ const dependencies = [];
294
+ for (const element of initializer.getElements()) {
295
+ const dependency = getStaticExpressionText(element);
296
+ if (!dependency) {
297
+ warnings.push(`deps.${propertyName} contains a non-static expression: ${element.getText()}`);
298
+ continue;
299
+ }
300
+ dependencies.push(dependency);
301
+ }
302
+ return dependencies;
303
+ }
304
+ function getInjectMethodName(expression) {
305
+ if (Node.isIdentifier(expression)) {
306
+ return expression.getText();
307
+ }
308
+ if (Node.isPropertyAccessExpression(expression)) {
309
+ return expression.getName();
310
+ }
311
+ return undefined;
312
+ }
313
+ function getAngularInjectCallDependency(callExpression) {
314
+ const [token] = callExpression.getArguments();
315
+ return getStaticExpressionText(token);
316
+ }
317
+ function getInjectionHelperDependency(expression) {
318
+ if (Node.isIdentifier(expression)) {
319
+ return expression.getText();
320
+ }
321
+ if (Node.isPropertyAccessExpression(expression)) {
322
+ const left = expression.getExpression();
323
+ if (Node.isIdentifier(left)) {
324
+ return expression.getText();
325
+ }
326
+ }
327
+ return undefined;
328
+ }
329
+ export function ensureHelperImports(sourceFile, helperImportPath) {
330
+ const missingImports = ['brandAngularSymbol', 'deps'].filter((importName) => !hasLocalNamedImport(sourceFile, helperImportPath, importName));
331
+ if (missingImports.length === 0) {
332
+ return;
333
+ }
334
+ const existingImport = sourceFile
335
+ .getImportDeclarations()
336
+ .find((importDeclaration) => importDeclaration.getModuleSpecifierValue() === helperImportPath);
337
+ if (existingImport) {
338
+ existingImport.addNamedImports(missingImports);
339
+ return;
340
+ }
341
+ sourceFile.addImportDeclaration({
342
+ moduleSpecifier: helperImportPath,
343
+ namedImports: missingImports,
344
+ });
345
+ }
346
+ export function removeConflictingExports(sourceFile, classDeclaration, className) {
347
+ if (classDeclaration.isDefaultExport()) {
348
+ classDeclaration.setIsDefaultExport(false);
349
+ }
350
+ if (classDeclaration.isExported()) {
351
+ classDeclaration.setIsExported(false);
352
+ }
353
+ for (const exportAssignment of sourceFile.getExportAssignments()) {
354
+ if (isDefaultIdentifierExport(exportAssignment, className) ||
355
+ isDefaultBrandedExport(exportAssignment, className)) {
356
+ exportAssignment.remove();
357
+ }
358
+ }
359
+ for (const exportDeclaration of sourceFile.getExportDeclarations()) {
360
+ removeClassFromExportDeclaration(exportDeclaration, className);
361
+ }
362
+ }
363
+ export function writeDefaultBrandExport(sourceFile, className, dependencyGroups) {
364
+ sourceFile.addExportAssignment({
365
+ expression: `brandAngularSymbol(${className}, ${createDepsExpression(dependencyGroups)})`,
366
+ isExportEquals: false,
367
+ });
368
+ }
369
+ export function readExistingDependencyGroups(sourceFile, className) {
370
+ const defaultExport = sourceFile
371
+ .getExportAssignments()
372
+ .find((exportAssignment) => {
373
+ if (exportAssignment.isExportEquals()) {
374
+ return false;
375
+ }
376
+ const expression = exportAssignment.getExpression();
377
+ if (!Node.isCallExpression(expression)) {
378
+ return false;
379
+ }
380
+ const callTarget = expression.getExpression();
381
+ if (!Node.isIdentifier(callTarget) ||
382
+ callTarget.getText() !== 'brandAngularSymbol') {
383
+ return false;
384
+ }
385
+ if (!className) {
386
+ return true;
387
+ }
388
+ const [targetClass] = expression.getArguments();
389
+ return (Node.isIdentifier(targetClass) && targetClass.getText() === className);
390
+ });
391
+ if (!defaultExport) {
392
+ return {
393
+ found: false,
394
+ warnings: [],
395
+ dependencyGroups: emptyDependencyGroups(),
396
+ propertyNodes: {},
397
+ };
398
+ }
399
+ const expression = defaultExport.getExpression();
400
+ if (!Node.isCallExpression(expression)) {
401
+ return invalidExistingDependencyGroups(defaultExport, [
402
+ 'Default export must call brandAngularSymbol(ClassName, deps({ ... })).',
403
+ ]);
404
+ }
405
+ const [, depsArgument] = expression.getArguments();
406
+ if (!Node.isCallExpression(depsArgument)) {
407
+ return invalidExistingDependencyGroups(defaultExport, [
408
+ 'brandAngularSymbol must receive deps({ injected, importDeps, providers }).',
409
+ ]);
410
+ }
411
+ const depsCallTarget = depsArgument.getExpression();
412
+ if (!Node.isIdentifier(depsCallTarget) ||
413
+ depsCallTarget.getText() !== 'deps') {
414
+ return invalidExistingDependencyGroups(depsArgument, [
415
+ 'brandAngularSymbol second argument must be a deps(...) call.',
416
+ ]);
417
+ }
418
+ const [depsObject] = depsArgument.getArguments();
419
+ if (!Node.isObjectLiteralExpression(depsObject)) {
420
+ return invalidExistingDependencyGroups(depsArgument, [
421
+ 'deps(...) must be called with an object literal.',
422
+ ]);
423
+ }
424
+ const warnings = [];
425
+ const propertyNodes = {};
426
+ const dependencyGroups = {
427
+ injected: readExistingDependencyGroupProperty(depsObject, 'injected', warnings, propertyNodes),
428
+ importDeps: readExistingDependencyGroupProperty(depsObject, 'importDeps', warnings, propertyNodes),
429
+ providers: readExistingDependencyGroupProperty(depsObject, 'providers', warnings, propertyNodes),
430
+ };
431
+ return {
432
+ found: true,
433
+ warnings,
434
+ dependencyGroups,
435
+ exportAssignmentNode: defaultExport,
436
+ depsObjectNode: depsObject,
437
+ propertyNodes,
438
+ };
439
+ }
440
+ export function formatDependencyGroups(dependencyGroups) {
441
+ return [
442
+ `injected=[${dependencyGroups.injected.join(', ')}]`,
443
+ `importDeps=[${dependencyGroups.importDeps.join(', ')}]`,
444
+ `providers=[${dependencyGroups.providers.join(', ')}]`,
445
+ ].join(' ');
446
+ }
447
+ export function runAngularBrandCodemod() {
448
+ return __awaiter(this, arguments, void 0, function* (options = {}) {
449
+ var _a, _b, _c;
450
+ const rootDir = resolve((_a = options.rootDir) !== null && _a !== void 0 ? _a : process.cwd());
451
+ const tsConfigFilePath = options.tsConfigFilePath
452
+ ? resolve(options.tsConfigFilePath)
453
+ : getDefaultTsConfigPath(rootDir);
454
+ const project = createProject(tsConfigFilePath);
455
+ const files = collectTypeScriptFiles(rootDir);
456
+ project.addSourceFilesAtPaths(files);
457
+ setProjectQuoteKind(project);
458
+ const summary = {
459
+ transformedFiles: 0,
460
+ skippedFiles: 0,
461
+ warnings: 0,
462
+ countByAngularKind: {
463
+ component: 0,
464
+ directive: 0,
465
+ injectable: 0,
466
+ pipe: 0,
467
+ },
468
+ files: [],
469
+ };
470
+ for (const sourceFile of project.getSourceFiles()) {
471
+ if (!isWithinRoot(sourceFile.getFilePath(), rootDir)) {
472
+ continue;
473
+ }
474
+ const result = transformSourceFile(sourceFile, options);
475
+ const report = Object.assign(Object.assign({}, result), { filePath: sourceFile.getFilePath() });
476
+ summary.files.push(report);
477
+ summary.warnings += result.warnings.length;
478
+ if (result.changed) {
479
+ summary.transformedFiles += 1;
480
+ if (result.angularKind &&
481
+ result.angularKind in summary.countByAngularKind) {
482
+ summary.countByAngularKind[result.angularKind] += 1;
483
+ }
484
+ if (!options.dryRun) {
485
+ yield sourceFile.save();
486
+ }
487
+ }
488
+ if (result.skipped) {
489
+ summary.skippedFiles += 1;
490
+ }
491
+ logFileResult(report, (_b = options.log) !== null && _b !== void 0 ? _b : console.log);
492
+ }
493
+ logSummary(summary, (_c = options.log) !== null && _c !== void 0 ? _c : console.log);
494
+ return summary;
495
+ });
496
+ }
497
+ function normalizeOptions(options) {
498
+ var _a, _b, _c, _d;
499
+ return {
500
+ helperImportPath: (_a = options.helperImportPath) !== null && _a !== void 0 ? _a : DEFAULT_OPTIONS.helperImportPath,
501
+ transformOnlyStandaloneDeclarables: (_b = options.transformOnlyStandaloneDeclarables) !== null && _b !== void 0 ? _b : DEFAULT_OPTIONS.transformOnlyStandaloneDeclarables,
502
+ includeProviders: (_c = options.includeProviders) !== null && _c !== void 0 ? _c : DEFAULT_OPTIONS.includeProviders,
503
+ includeViewProviders: (_d = options.includeViewProviders) !== null && _d !== void 0 ? _d : DEFAULT_OPTIONS.includeViewProviders,
504
+ };
505
+ }
506
+ function skip(result, warnings) {
507
+ result.skipped = true;
508
+ result.warnings.push(...warnings);
509
+ return result;
510
+ }
511
+ function getDecoratorName(decorator) {
512
+ const expression = decorator.getExpression();
513
+ if (Node.isCallExpression(expression)) {
514
+ const callTarget = expression.getExpression();
515
+ if (Node.isIdentifier(callTarget)) {
516
+ return callTarget.getText();
517
+ }
518
+ if (Node.isPropertyAccessExpression(callTarget)) {
519
+ return callTarget.getName();
520
+ }
521
+ return undefined;
522
+ }
523
+ if (Node.isIdentifier(expression)) {
524
+ return expression.getText();
525
+ }
526
+ if (Node.isPropertyAccessExpression(expression)) {
527
+ return expression.getName();
528
+ }
529
+ return undefined;
530
+ }
531
+ function decoratorLabel(angularKind) {
532
+ switch (angularKind) {
533
+ case 'component':
534
+ return '@Component';
535
+ case 'directive':
536
+ return '@Directive';
537
+ case 'pipe':
538
+ return '@Pipe';
539
+ case 'injectable':
540
+ return '@Injectable';
541
+ }
542
+ }
543
+ function getDecoratorMetadataObject(classDeclaration) {
544
+ var _a;
545
+ for (const decorator of classDeclaration.getDecorators()) {
546
+ if (!getAngularKindFromDecorator(decorator)) {
547
+ continue;
548
+ }
549
+ const callExpression = decorator.getCallExpression();
550
+ const [metadata] = (_a = callExpression === null || callExpression === void 0 ? void 0 : callExpression.getArguments()) !== null && _a !== void 0 ? _a : [];
551
+ if (Node.isObjectLiteralExpression(metadata)) {
552
+ return metadata;
553
+ }
554
+ }
555
+ return undefined;
556
+ }
557
+ function getAngularKindFromDecorator(decorator) {
558
+ const decoratorName = getDecoratorName(decorator);
559
+ return decoratorName && decoratorName in SUPPORTED_DECORATORS
560
+ ? SUPPORTED_DECORATORS[decoratorName]
561
+ : undefined;
562
+ }
563
+ function getObjectPropertyAssignment(objectLiteral, propertyName) {
564
+ const property = objectLiteral.getProperties().find((objectProperty) => {
565
+ if (!Node.isPropertyAssignment(objectProperty)) {
566
+ return false;
567
+ }
568
+ return getStaticPropertyName(objectProperty.getNameNode()) === propertyName;
569
+ });
570
+ return Node.isPropertyAssignment(property) ? property : undefined;
571
+ }
572
+ function extractDecoratorMetadataDepGroups(classDeclaration, angularKind, options) {
573
+ const metadata = getDecoratorMetadataObject(classDeclaration);
574
+ const groups = emptyMetadataDependencyGroups();
575
+ if (!metadata) {
576
+ return groups;
577
+ }
578
+ groups.imports = extractMetadataArrayProperty(metadata, 'imports', 'imports', groups.warnings);
579
+ groups.hostDirectives = extractMetadataArrayProperty(metadata, 'hostDirectives', 'hostDirectives', groups.warnings);
580
+ if (options.includeProviders) {
581
+ groups.providers = extractMetadataArrayProperty(metadata, 'providers', 'providers', groups.warnings);
582
+ }
583
+ if (options.includeViewProviders && angularKind === 'component') {
584
+ groups.viewProviders = extractMetadataArrayProperty(metadata, 'viewProviders', 'viewProviders', groups.warnings);
585
+ }
586
+ return groups;
587
+ }
588
+ function emptyMetadataDependencyGroups() {
589
+ return {
590
+ imports: [],
591
+ hostDirectives: [],
592
+ providers: [],
593
+ viewProviders: [],
594
+ warnings: [],
595
+ };
596
+ }
597
+ function extractMetadataArrayProperty(metadata, propertyName, context, warnings) {
598
+ const property = getObjectPropertyAssignment(metadata, propertyName);
599
+ if (!property) {
600
+ return [];
601
+ }
602
+ const initializer = property.getInitializer();
603
+ if (!Node.isArrayLiteralExpression(initializer)) {
604
+ warnings.push(`Skipped metadata property "${propertyName}" because it is not a static array.`);
605
+ return [];
606
+ }
607
+ return extractStaticArrayElements(initializer, context, warnings);
608
+ }
609
+ function extractStaticArrayElements(arrayLiteral, context, warnings) {
610
+ const dependencies = [];
611
+ for (const element of arrayLiteral.getElements()) {
612
+ if (Node.isArrayLiteralExpression(element)) {
613
+ dependencies.push(...extractStaticArrayElements(element, context, warnings));
614
+ continue;
615
+ }
616
+ if (Node.isSpreadElement(element)) {
617
+ warnings.push(`Skipped spread element in "${context}" metadata dependencies.`);
618
+ continue;
619
+ }
620
+ if (isProviderContext(context) && Node.isCallExpression(element)) {
621
+ const providerFactory = getStaticExpressionText(element.getExpression());
622
+ if (providerFactory) {
623
+ dependencies.push(providerFactory);
624
+ continue;
625
+ }
626
+ }
627
+ const dependency = getStaticExpressionText(element);
628
+ if (dependency) {
629
+ dependencies.push(dependency);
630
+ continue;
631
+ }
632
+ if (Node.isObjectLiteralExpression(element)) {
633
+ dependencies.push(...extractStaticObjectElementDependencies(element, context, warnings));
634
+ continue;
635
+ }
636
+ warnings.push(`Skipped complex expression "${element.getText()}" in "${context}" metadata dependencies.`);
637
+ }
638
+ return dependencies;
639
+ }
640
+ function isProviderContext(context) {
641
+ return context === 'providers' || context === 'viewProviders';
642
+ }
643
+ function extractStaticObjectElementDependencies(objectLiteral, context, warnings) {
644
+ const dependencies = [];
645
+ const knownValueProperties = context === 'hostDirectives'
646
+ ? new Set(['directive'])
647
+ : new Set(['provide', 'useClass', 'useExisting']);
648
+ for (const property of objectLiteral.getProperties()) {
649
+ if (!Node.isPropertyAssignment(property)) {
650
+ warnings.push(`Skipped complex object member in "${context}" metadata dependencies.`);
651
+ continue;
652
+ }
653
+ const propertyName = getStaticPropertyName(property.getNameNode());
654
+ if (!propertyName || !knownValueProperties.has(propertyName)) {
655
+ continue;
656
+ }
657
+ const dependency = getStaticExpressionText(property.getInitializer());
658
+ if (dependency) {
659
+ dependencies.push(dependency);
660
+ continue;
661
+ }
662
+ warnings.push(`Skipped complex "${propertyName}" value in "${context}" metadata dependencies.`);
663
+ }
664
+ return dependencies;
665
+ }
666
+ function getInjectDecoratorToken(decorators, warnings) {
667
+ var _a, _b;
668
+ for (const decorator of decorators) {
669
+ if (getDecoratorName(decorator) !== 'Inject') {
670
+ continue;
671
+ }
672
+ const [token] = (_b = (_a = decorator.getCallExpression()) === null || _a === void 0 ? void 0 : _a.getArguments()) !== null && _b !== void 0 ? _b : [];
673
+ const dependency = getStaticExpressionText(token);
674
+ if (!dependency) {
675
+ warnings.push('Skipped @Inject() dependency because the token is not a static identifier.');
676
+ return { found: true };
677
+ }
678
+ return { found: true, dependency };
679
+ }
680
+ return { found: false };
681
+ }
682
+ function getStaticExpressionText(expression) {
683
+ if (!expression) {
684
+ return undefined;
685
+ }
686
+ if (Node.isIdentifier(expression)) {
687
+ return expression.getText();
688
+ }
689
+ if (Node.isPropertyAccessExpression(expression)) {
690
+ return expression.getText();
691
+ }
692
+ return undefined;
693
+ }
694
+ function getStaticPropertyName(nameNode) {
695
+ if (Node.isIdentifier(nameNode)) {
696
+ return nameNode.getText();
697
+ }
698
+ if (Node.isStringLiteral(nameNode) || Node.isNumericLiteral(nameNode)) {
699
+ return nameNode.getLiteralText();
700
+ }
701
+ return undefined;
702
+ }
703
+ function getDependencyTextFromTypeNode(typeNode) {
704
+ if (isPrimitiveTypeNode(typeNode)) {
705
+ return undefined;
706
+ }
707
+ if (Node.isTypeReference(typeNode)) {
708
+ const typeName = typeNode.getTypeName();
709
+ const dependency = typeName.getText();
710
+ return isPrimitiveDependencyText(dependency) ? undefined : dependency;
711
+ }
712
+ if (Node.isExpressionWithTypeArguments(typeNode)) {
713
+ const expression = typeNode.getExpression();
714
+ return getStaticExpressionText(expression);
715
+ }
716
+ return undefined;
717
+ }
718
+ function isPrimitiveTypeNode(typeNode) {
719
+ return [
720
+ SyntaxKind.AnyKeyword,
721
+ SyntaxKind.BigIntKeyword,
722
+ SyntaxKind.BooleanKeyword,
723
+ SyntaxKind.FalseKeyword,
724
+ SyntaxKind.NeverKeyword,
725
+ SyntaxKind.NullKeyword,
726
+ SyntaxKind.NumberKeyword,
727
+ SyntaxKind.ObjectKeyword,
728
+ SyntaxKind.StringKeyword,
729
+ SyntaxKind.SymbolKeyword,
730
+ SyntaxKind.TrueKeyword,
731
+ SyntaxKind.UndefinedKeyword,
732
+ SyntaxKind.UnknownKeyword,
733
+ SyntaxKind.VoidKeyword,
734
+ ].includes(typeNode.getKind());
735
+ }
736
+ function isPrimitiveDependencyText(dependency) {
737
+ return PRIMITIVE_TYPE_TEXTS.has(dependency);
738
+ }
739
+ function isRuntimeSafeTypeDependency(typeNode, dependency) {
740
+ const identifiers = getDependencyIdentifiersFromTypeNode(typeNode);
741
+ if (identifiers.length === 0 ||
742
+ identifiers.map((identifier) => identifier.getText()).join('.') !==
743
+ dependency) {
744
+ return false;
745
+ }
746
+ const [rootIdentifier] = identifiers;
747
+ const leafIdentifier = identifiers[identifiers.length - 1];
748
+ const isQualifiedDependency = identifiers.length > 1;
749
+ return (isRuntimeSafeIdentifier(rootIdentifier, {
750
+ allowNamespaceContainer: isQualifiedDependency,
751
+ }) &&
752
+ isRuntimeSafeIdentifier(leafIdentifier, { allowNamespaceContainer: false }));
753
+ }
754
+ function getDependencyIdentifiersFromTypeNode(typeNode) {
755
+ if (!Node.isTypeReference(typeNode)) {
756
+ return [];
757
+ }
758
+ const typeName = typeNode.getTypeName();
759
+ if (Node.isIdentifier(typeName)) {
760
+ return [typeName];
761
+ }
762
+ return typeName.getDescendantsOfKind(SyntaxKind.Identifier);
763
+ }
764
+ function isRuntimeSafeIdentifier(identifier, options) {
765
+ var _a, _b;
766
+ const symbol = (_a = identifier.getSymbol()) !== null && _a !== void 0 ? _a : identifier.getType().getSymbol();
767
+ if (!symbol) {
768
+ return false;
769
+ }
770
+ const declarations = symbol.getDeclarations();
771
+ if (declarations.length === 0) {
772
+ return false;
773
+ }
774
+ if (declarations.some((declaration) => isTypeOnlyImportDeclaration(declaration))) {
775
+ return false;
776
+ }
777
+ if (options.allowNamespaceContainer &&
778
+ declarations.some((declaration) => Node.isNamespaceImport(declaration))) {
779
+ return true;
780
+ }
781
+ const aliasedSymbol = symbol.getAliasedSymbol();
782
+ const runtimeDeclarations = (_b = aliasedSymbol === null || aliasedSymbol === void 0 ? void 0 : aliasedSymbol.getDeclarations()) !== null && _b !== void 0 ? _b : declarations;
783
+ if (runtimeDeclarations.length === 0) {
784
+ return false;
785
+ }
786
+ return runtimeDeclarations.some((declaration) => isRuntimeValueDeclaration(declaration, options));
787
+ }
788
+ function isTypeOnlyImportDeclaration(declaration) {
789
+ var _a, _b;
790
+ if (Node.isImportSpecifier(declaration)) {
791
+ return (declaration.isTypeOnly() ||
792
+ declaration.getImportDeclaration().isTypeOnly());
793
+ }
794
+ if (Node.isImportClause(declaration)) {
795
+ return declaration.isTypeOnly();
796
+ }
797
+ if (Node.isNamespaceImport(declaration)) {
798
+ return ((_b = (_a = declaration
799
+ .getFirstAncestorByKind(SyntaxKind.ImportDeclaration)) === null || _a === void 0 ? void 0 : _a.isTypeOnly()) !== null && _b !== void 0 ? _b : false);
800
+ }
801
+ return false;
802
+ }
803
+ function isRuntimeValueDeclaration(declaration, options) {
804
+ if (Node.isClassDeclaration(declaration) ||
805
+ Node.isEnumDeclaration(declaration) ||
806
+ Node.isFunctionDeclaration(declaration) ||
807
+ Node.isVariableDeclaration(declaration)) {
808
+ return true;
809
+ }
810
+ if (options.allowNamespaceContainer &&
811
+ Node.isModuleDeclaration(declaration)) {
812
+ return true;
813
+ }
814
+ return false;
815
+ }
816
+ function getExportRewriteSafety(sourceFile, classDeclaration, className) {
817
+ const warnings = [];
818
+ for (const statement of sourceFile.getStatements()) {
819
+ if (Node.isFunctionDeclaration(statement) && statement.isDefaultExport()) {
820
+ warnings.push('Skipped file because it has an unrelated default-exported function.');
821
+ }
822
+ if (Node.isClassDeclaration(statement) &&
823
+ statement !== classDeclaration &&
824
+ statement.isDefaultExport()) {
825
+ warnings.push('Skipped file because it has an unrelated default-exported class.');
826
+ }
827
+ }
828
+ for (const exportAssignment of sourceFile.getExportAssignments()) {
829
+ if (exportAssignment.isExportEquals()) {
830
+ warnings.push('Skipped file because export = is not safe to combine with export default.');
831
+ continue;
832
+ }
833
+ if (!isDefaultIdentifierExport(exportAssignment, className) &&
834
+ !isDefaultBrandedExport(exportAssignment, className)) {
835
+ warnings.push(`Skipped file because it has a complex default export: ${exportAssignment.getText()}`);
836
+ }
837
+ }
838
+ for (const exportDeclaration of sourceFile.getExportDeclarations()) {
839
+ const defaultExportSpecifier = exportDeclaration
840
+ .getNamedExports()
841
+ .find((specifier) => {
842
+ var _a;
843
+ const alias = (_a = specifier.getAliasNode()) === null || _a === void 0 ? void 0 : _a.getText();
844
+ return (alias === 'default' || (!alias && specifier.getName() === 'default'));
845
+ });
846
+ if (defaultExportSpecifier &&
847
+ defaultExportSpecifier.getName() !== className) {
848
+ warnings.push('Skipped file because it has an unrelated named default export.');
849
+ }
850
+ if (exportDeclaration.getModuleSpecifier()) {
851
+ const reExportsClass = exportDeclaration
852
+ .getNamedExports()
853
+ .some((specifier) => specifier.getName() === className);
854
+ if (reExportsClass) {
855
+ warnings.push(`Skipped file because it re-exports "${className}" from another module.`);
856
+ }
857
+ }
858
+ }
859
+ return warnings.length === 0
860
+ ? { safe: true, warnings: [] }
861
+ : { safe: false, warnings };
862
+ }
863
+ function getHelperImportSafety(sourceFile, helperImportPath) {
864
+ const warnings = ['brandAngularSymbol', 'deps']
865
+ .filter((helperName) => hasConflictingTopLevelBinding(sourceFile, helperImportPath, helperName))
866
+ .map((helperName) => `Skipped file because "${helperName}" is already bound to a different top-level symbol.`);
867
+ return warnings.length === 0
868
+ ? { safe: true, warnings: [] }
869
+ : { safe: false, warnings };
870
+ }
871
+ function hasConflictingTopLevelBinding(sourceFile, helperImportPath, helperName) {
872
+ var _a, _b, _c, _d;
873
+ for (const importDeclaration of sourceFile.getImportDeclarations()) {
874
+ if (((_a = importDeclaration.getDefaultImport()) === null || _a === void 0 ? void 0 : _a.getText()) === helperName) {
875
+ return true;
876
+ }
877
+ if (((_b = importDeclaration.getNamespaceImport()) === null || _b === void 0 ? void 0 : _b.getText()) === helperName) {
878
+ return true;
879
+ }
880
+ for (const namedImport of importDeclaration.getNamedImports()) {
881
+ const localName = (_d = (_c = namedImport.getAliasNode()) === null || _c === void 0 ? void 0 : _c.getText()) !== null && _d !== void 0 ? _d : namedImport.getName();
882
+ if (localName !== helperName) {
883
+ continue;
884
+ }
885
+ return importDeclaration.getModuleSpecifierValue() !== helperImportPath;
886
+ }
887
+ }
888
+ for (const statement of sourceFile.getStatements()) {
889
+ if (Node.isClassDeclaration(statement) &&
890
+ statement.getName() === helperName) {
891
+ return true;
892
+ }
893
+ if (Node.isFunctionDeclaration(statement) &&
894
+ statement.getName() === helperName) {
895
+ return true;
896
+ }
897
+ if (Node.isEnumDeclaration(statement) &&
898
+ statement.getName() === helperName) {
899
+ return true;
900
+ }
901
+ if (Node.isInterfaceDeclaration(statement) &&
902
+ statement.getName() === helperName) {
903
+ return true;
904
+ }
905
+ if (Node.isTypeAliasDeclaration(statement) &&
906
+ statement.getName() === helperName) {
907
+ return true;
908
+ }
909
+ if (Node.isVariableStatement(statement)) {
910
+ const hasVariableName = statement
911
+ .getDeclarationList()
912
+ .getDeclarations()
913
+ .some((declaration) => declaration.getName() === helperName);
914
+ if (hasVariableName) {
915
+ return true;
916
+ }
917
+ }
918
+ }
919
+ return false;
920
+ }
921
+ function isDefaultIdentifierExport(exportAssignment, className) {
922
+ if (exportAssignment.isExportEquals()) {
923
+ return false;
924
+ }
925
+ const expression = exportAssignment.getExpression();
926
+ return Node.isIdentifier(expression) && expression.getText() === className;
927
+ }
928
+ function isDefaultBrandedExport(exportAssignment, className) {
929
+ if (exportAssignment.isExportEquals()) {
930
+ return false;
931
+ }
932
+ const expression = exportAssignment.getExpression();
933
+ if (!Node.isCallExpression(expression)) {
934
+ return false;
935
+ }
936
+ const callTarget = expression.getExpression();
937
+ if (!Node.isIdentifier(callTarget) ||
938
+ callTarget.getText() !== 'brandAngularSymbol') {
939
+ return false;
940
+ }
941
+ const [targetClass] = expression.getArguments();
942
+ return Node.isIdentifier(targetClass) && targetClass.getText() === className;
943
+ }
944
+ function removeClassFromExportDeclaration(exportDeclaration, className) {
945
+ if (exportDeclaration.getModuleSpecifier()) {
946
+ return;
947
+ }
948
+ for (const namedExport of exportDeclaration.getNamedExports()) {
949
+ if (namedExport.getName() === className) {
950
+ namedExport.remove();
951
+ }
952
+ }
953
+ if (exportDeclaration.getNamedExports().length === 0) {
954
+ exportDeclaration.remove();
955
+ }
956
+ }
957
+ function hasLocalNamedImport(sourceFile, helperImportPath, importName) {
958
+ return sourceFile.getImportDeclarations().some((importDeclaration) => {
959
+ if (importDeclaration.getModuleSpecifierValue() !== helperImportPath) {
960
+ return false;
961
+ }
962
+ return importDeclaration.getNamedImports().some((namedImport) => {
963
+ var _a, _b;
964
+ const localName = (_b = (_a = namedImport.getAliasNode()) === null || _a === void 0 ? void 0 : _a.getText()) !== null && _b !== void 0 ? _b : namedImport.getName();
965
+ return localName === importName;
966
+ });
967
+ });
968
+ }
969
+ function createProject(tsConfigFilePath) {
970
+ if (tsConfigFilePath) {
971
+ return new Project({
972
+ skipAddingFilesFromTsConfig: true,
973
+ tsConfigFilePath,
974
+ });
975
+ }
976
+ return new Project({
977
+ compilerOptions: {
978
+ experimentalDecorators: true,
979
+ module: ts.ModuleKind.Preserve,
980
+ moduleResolution: ts.ModuleResolutionKind.Node10,
981
+ target: ts.ScriptTarget.ES2022,
982
+ },
983
+ });
984
+ }
985
+ function getDefaultTsConfigPath(rootDir) {
986
+ const tsConfigPath = join(rootDir, 'tsconfig.json');
987
+ return existsSync(tsConfigPath) ? tsConfigPath : undefined;
988
+ }
989
+ function collectTypeScriptFiles(rootDir) {
990
+ const files = [];
991
+ collectTypeScriptFilesInto(rootDir, files);
992
+ return files;
993
+ }
994
+ function collectTypeScriptFilesInto(directory, files) {
995
+ for (const entryName of readdirSync(directory)) {
996
+ const entryPath = join(directory, entryName);
997
+ const stats = statSync(entryPath);
998
+ if (stats.isDirectory()) {
999
+ if (!IGNORED_DIRECTORIES.has(entryName)) {
1000
+ collectTypeScriptFilesInto(entryPath, files);
1001
+ }
1002
+ continue;
1003
+ }
1004
+ if (!stats.isFile() ||
1005
+ extname(entryName) !== '.ts' ||
1006
+ isGeneratedFile(entryPath)) {
1007
+ continue;
1008
+ }
1009
+ files.push(entryPath);
1010
+ }
1011
+ }
1012
+ function isGeneratedFile(filePath) {
1013
+ const fileName = basename(filePath);
1014
+ return (GENERATED_FILE_SUFFIXES.some((suffix) => fileName.endsWith(suffix)) ||
1015
+ filePath.includes('/generated/') ||
1016
+ filePath.includes('\\generated\\'));
1017
+ }
1018
+ function setProjectQuoteKind(project) {
1019
+ const firstModuleSpecifier = project
1020
+ .getSourceFiles()
1021
+ .flatMap((sourceFile) => sourceFile.getImportDeclarations())
1022
+ .map((importDeclaration) => importDeclaration.getModuleSpecifier().getText())
1023
+ .find(Boolean);
1024
+ project.manipulationSettings.set({
1025
+ quoteKind: (firstModuleSpecifier === null || firstModuleSpecifier === void 0 ? void 0 : firstModuleSpecifier.startsWith('"'))
1026
+ ? QuoteKind.Double
1027
+ : QuoteKind.Single,
1028
+ });
1029
+ }
1030
+ function isWithinRoot(filePath, rootDir) {
1031
+ const absoluteFilePath = isAbsolute(filePath) ? filePath : resolve(filePath);
1032
+ return (absoluteFilePath === rootDir || absoluteFilePath.startsWith(`${rootDir}/`));
1033
+ }
1034
+ function logFileResult(report, log) {
1035
+ if (!report.changed && !report.skipped && !report.angularKind) {
1036
+ return;
1037
+ }
1038
+ const status = report.changed
1039
+ ? 'transformed'
1040
+ : report.skipped
1041
+ ? 'skipped'
1042
+ : 'unchanged';
1043
+ const details = [
1044
+ `file=${report.filePath}`,
1045
+ report.angularKind ? `kind=${report.angularKind}` : undefined,
1046
+ report.className ? `class=${report.className}` : undefined,
1047
+ `injected=[${report.dependencyGroups.injected.join(', ')}]`,
1048
+ `importDeps=[${report.dependencyGroups.importDeps.join(', ')}]`,
1049
+ `providers=[${report.dependencyGroups.providers.join(', ')}]`,
1050
+ `status=${status}`,
1051
+ ].filter(Boolean);
1052
+ log(details.join(' '));
1053
+ for (const warning of report.warnings) {
1054
+ log(` warning: ${warning}`);
1055
+ }
1056
+ }
1057
+ function logSummary(summary, log) {
1058
+ log([
1059
+ `summary transformed=${summary.transformedFiles}`,
1060
+ `skipped=${summary.skippedFiles}`,
1061
+ `warnings=${summary.warnings}`,
1062
+ `components=${summary.countByAngularKind.component}`,
1063
+ `directives=${summary.countByAngularKind.directive}`,
1064
+ `pipes=${summary.countByAngularKind.pipe}`,
1065
+ `injectables=${summary.countByAngularKind.injectable}`,
1066
+ ].join(' '));
1067
+ }
1068
+ function parseCliArgs(argv) {
1069
+ const options = {};
1070
+ for (let index = 0; index < argv.length; index += 1) {
1071
+ const arg = argv[index];
1072
+ switch (arg) {
1073
+ case '--root':
1074
+ options.rootDir = argv[++index];
1075
+ break;
1076
+ case '--tsconfig':
1077
+ options.tsConfigFilePath = argv[++index];
1078
+ break;
1079
+ case '--helper-import':
1080
+ options.helperImportPath = argv[++index];
1081
+ break;
1082
+ case '--transform-only-standalone-declarables':
1083
+ options.transformOnlyStandaloneDeclarables = true;
1084
+ break;
1085
+ case '--no-providers':
1086
+ options.includeProviders = false;
1087
+ break;
1088
+ case '--no-view-providers':
1089
+ options.includeViewProviders = false;
1090
+ break;
1091
+ case '--dry-run':
1092
+ options.dryRun = true;
1093
+ break;
1094
+ case '--help':
1095
+ printHelpAndExit();
1096
+ break;
1097
+ default:
1098
+ throw new Error(`Unknown argument: ${arg}`);
1099
+ }
1100
+ }
1101
+ return options;
1102
+ }
1103
+ function printHelpAndExit() {
1104
+ console.log(`Usage: craft-brand [options]
1105
+
1106
+ Options:
1107
+ --root <dir> Project root. Defaults to cwd.
1108
+ --tsconfig <path> tsconfig path. Defaults to <root>/tsconfig.json.
1109
+ --helper-import <path> Import path for brandAngularSymbol and deps.
1110
+ --transform-only-standalone-declarables Only transform standalone components/directives.
1111
+ --no-providers Do not include metadata providers in deps().
1112
+ --no-view-providers Do not include component viewProviders in deps().
1113
+ --dry-run Print results without writing files.
1114
+ --help Show this help.
1115
+ `);
1116
+ process.exit(0);
1117
+ }
1118
+ if (require.main === module) {
1119
+ runAngularBrandCodemod(parseCliArgs(process.argv.slice(2))).catch((error) => {
1120
+ console.error(error);
1121
+ process.exitCode = 1;
1122
+ });
1123
+ }
1124
+ //# sourceMappingURL=angular-brand-codemod.js.map