@craft-ng/dev-tools 0.1.4 → 0.1.5
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/package.json +1 -1
- package/src/eslint-rules/brand-angular-deps-match.cjs +33 -7
- package/src/eslint-rules/no-direct-angular-class-export.cjs +35 -6
- package/src/scripts/angular-brand-codemod.d.ts +17 -2
- package/src/scripts/angular-brand-codemod.js +454 -44
- package/src/scripts/angular-brand-codemod.js.map +1 -1
- package/src/scripts/angular-brand-codemod.spec.ts +228 -0
- package/src/scripts/angular-brand-codemod.ts +777 -63
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from 'ts-morph';
|
|
18
18
|
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
19
19
|
import { basename, extname, isAbsolute, join, resolve } from 'node:path';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
20
21
|
|
|
21
22
|
export type AngularKind = 'component' | 'directive' | 'pipe' | 'injectable';
|
|
22
23
|
|
|
@@ -28,6 +29,8 @@ export type TransformResult = {
|
|
|
28
29
|
className?: string;
|
|
29
30
|
dependencies: string[];
|
|
30
31
|
dependencyGroups: DependencyGroups;
|
|
32
|
+
generatedTypeName?: string;
|
|
33
|
+
generatedDependencyGroups: GeneratedDependencyGroups;
|
|
31
34
|
};
|
|
32
35
|
|
|
33
36
|
export type AngularBrandCodemodOptions = {
|
|
@@ -56,6 +59,21 @@ export type DependencyGroups = {
|
|
|
56
59
|
providers: string[];
|
|
57
60
|
};
|
|
58
61
|
|
|
62
|
+
export type GeneratedDependencyEntry = {
|
|
63
|
+
key: string;
|
|
64
|
+
typeText: string;
|
|
65
|
+
typeImport?: {
|
|
66
|
+
moduleSpecifier: string;
|
|
67
|
+
name: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export type GeneratedDependencyGroups = {
|
|
72
|
+
deps: GeneratedDependencyEntry[];
|
|
73
|
+
provided: GeneratedDependencyEntry[];
|
|
74
|
+
missingProvider: GeneratedDependencyEntry[];
|
|
75
|
+
};
|
|
76
|
+
|
|
59
77
|
export type DependencyAnalysisResult = Omit<TransformResult, 'changed'> & {
|
|
60
78
|
classDeclaration?: ClassDeclaration;
|
|
61
79
|
};
|
|
@@ -77,6 +95,17 @@ type MetadataDependencyGroups = {
|
|
|
77
95
|
warnings: string[];
|
|
78
96
|
};
|
|
79
97
|
|
|
98
|
+
type ProvidedDependencyExtractionResult = {
|
|
99
|
+
entries: GeneratedDependencyEntry[];
|
|
100
|
+
warnings: string[];
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
type DependencyReferenceResolution = {
|
|
104
|
+
kind: 'class' | 'enum' | 'function' | 'variable' | 'namespace' | 'unknown';
|
|
105
|
+
classDeclaration?: ClassDeclaration;
|
|
106
|
+
moduleSpecifier?: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
80
109
|
type NormalizedOptions = Required<AngularBrandCodemodOptions>;
|
|
81
110
|
|
|
82
111
|
type InjectDecoratorTokenResult =
|
|
@@ -170,15 +199,6 @@ export function transformSourceFile(
|
|
|
170
199
|
return result;
|
|
171
200
|
}
|
|
172
201
|
|
|
173
|
-
const exportSafety = getExportRewriteSafety(
|
|
174
|
-
sourceFile,
|
|
175
|
-
classDeclaration,
|
|
176
|
-
className,
|
|
177
|
-
);
|
|
178
|
-
if (!exportSafety.safe) {
|
|
179
|
-
return skip(result, exportSafety.warnings);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
202
|
const importSafety = getHelperImportSafety(
|
|
183
203
|
sourceFile,
|
|
184
204
|
normalizedOptions.helperImportPath,
|
|
@@ -187,11 +207,22 @@ export function transformSourceFile(
|
|
|
187
207
|
return skip(result, importSafety.warnings);
|
|
188
208
|
}
|
|
189
209
|
|
|
190
|
-
|
|
210
|
+
const beforeText = sourceFile.getFullText();
|
|
211
|
+
|
|
212
|
+
migrateLegacyBrandExport(sourceFile, classDeclaration, className);
|
|
191
213
|
ensureHelperImports(sourceFile, normalizedOptions.helperImportPath);
|
|
192
|
-
|
|
214
|
+
ensureGeneratedDependencyTypeImports(
|
|
215
|
+
sourceFile,
|
|
216
|
+
result.generatedDependencyGroups,
|
|
217
|
+
);
|
|
218
|
+
writeGeneratedDepsTypeAlias(
|
|
219
|
+
sourceFile,
|
|
220
|
+
className,
|
|
221
|
+
result.generatedDependencyGroups,
|
|
222
|
+
);
|
|
223
|
+
sourceFile.organizeImports();
|
|
193
224
|
|
|
194
|
-
result.changed =
|
|
225
|
+
result.changed = sourceFile.getFullText() !== beforeText;
|
|
195
226
|
return result;
|
|
196
227
|
}
|
|
197
228
|
|
|
@@ -205,6 +236,7 @@ export function analyzeSourceFileDependencies(
|
|
|
205
236
|
warnings: [],
|
|
206
237
|
dependencies: [],
|
|
207
238
|
dependencyGroups: emptyDependencyGroups(),
|
|
239
|
+
generatedDependencyGroups: emptyGeneratedDependencyGroups(),
|
|
208
240
|
};
|
|
209
241
|
|
|
210
242
|
const angularClass = findAngularDecoratedClass(sourceFile);
|
|
@@ -250,11 +282,21 @@ export function analyzeSourceFileDependencies(
|
|
|
250
282
|
normalizedOptions,
|
|
251
283
|
)
|
|
252
284
|
: emptyMetadataDependencyGroups();
|
|
285
|
+
const providedDeps =
|
|
286
|
+
angularKind === 'component' || angularKind === 'directive'
|
|
287
|
+
? extractProvidedDependencies(
|
|
288
|
+
sourceFile,
|
|
289
|
+
classDeclaration,
|
|
290
|
+
angularKind,
|
|
291
|
+
normalizedOptions,
|
|
292
|
+
)
|
|
293
|
+
: { entries: [], warnings: [] };
|
|
253
294
|
const constructorDeps = extractConstructorDeps(classDeclaration);
|
|
254
295
|
const injectCallDeps = extractInjectCallDeps(classDeclaration);
|
|
255
296
|
|
|
256
297
|
result.warnings.push(
|
|
257
298
|
...metadataDeps.warnings,
|
|
299
|
+
...providedDeps.warnings,
|
|
258
300
|
...constructorDeps.warnings,
|
|
259
301
|
...injectCallDeps.warnings,
|
|
260
302
|
);
|
|
@@ -274,6 +316,13 @@ export function analyzeSourceFileDependencies(
|
|
|
274
316
|
importDeps: mergeDeps(metadataDeps.imports, metadataDeps.hostDirectives),
|
|
275
317
|
providers: mergeDeps(metadataDeps.providers, metadataDeps.viewProviders),
|
|
276
318
|
};
|
|
319
|
+
result.generatedTypeName = getGeneratedDepsTypeName(className);
|
|
320
|
+
result.generatedDependencyGroups = createGeneratedDependencyGroups(
|
|
321
|
+
sourceFile,
|
|
322
|
+
result.dependencyGroups.importDeps,
|
|
323
|
+
result.dependencyGroups.injected,
|
|
324
|
+
providedDeps.entries,
|
|
325
|
+
);
|
|
277
326
|
|
|
278
327
|
return result;
|
|
279
328
|
}
|
|
@@ -493,8 +542,301 @@ function emptyDependencyGroups(): DependencyGroups {
|
|
|
493
542
|
};
|
|
494
543
|
}
|
|
495
544
|
|
|
496
|
-
function
|
|
497
|
-
return
|
|
545
|
+
function emptyGeneratedDependencyGroups(): GeneratedDependencyGroups {
|
|
546
|
+
return {
|
|
547
|
+
deps: [],
|
|
548
|
+
provided: [],
|
|
549
|
+
missingProvider: [],
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function getGeneratedDepsTypeName(className: string): string {
|
|
554
|
+
return `GenDeps_${className}`;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function createGeneratedDependencyGroups(
|
|
558
|
+
sourceFile: SourceFile,
|
|
559
|
+
importDependencies: string[],
|
|
560
|
+
injectedDependencies: string[],
|
|
561
|
+
providedEntries: GeneratedDependencyEntry[],
|
|
562
|
+
): GeneratedDependencyGroups {
|
|
563
|
+
const deps = mergeGeneratedDependencyEntries(
|
|
564
|
+
importDependencies.map((dependency) =>
|
|
565
|
+
createGeneratedDependencyEntry(sourceFile, dependency, 'import'),
|
|
566
|
+
),
|
|
567
|
+
injectedDependencies.map((dependency) =>
|
|
568
|
+
createGeneratedDependencyEntry(sourceFile, dependency, 'inject'),
|
|
569
|
+
),
|
|
570
|
+
);
|
|
571
|
+
const provided = mergeGeneratedDependencyEntries(providedEntries);
|
|
572
|
+
const providedKeys = new Set(provided.map((entry) => entry.key));
|
|
573
|
+
const missingProvider = mergeGeneratedDependencyEntries(
|
|
574
|
+
injectedDependencies
|
|
575
|
+
.filter((dependency) => {
|
|
576
|
+
const dependencyKey = createGeneratedDependencyKey(dependency);
|
|
577
|
+
return (
|
|
578
|
+
!providedKeys.has(dependencyKey) &&
|
|
579
|
+
!isProvidedInInjectableTree(sourceFile, dependency)
|
|
580
|
+
);
|
|
581
|
+
})
|
|
582
|
+
.map((dependency) =>
|
|
583
|
+
createGeneratedDependencyEntry(sourceFile, dependency, 'inject'),
|
|
584
|
+
),
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
return {
|
|
588
|
+
deps,
|
|
589
|
+
provided,
|
|
590
|
+
missingProvider,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function mergeGeneratedDependencyEntries(
|
|
595
|
+
...groups: readonly GeneratedDependencyEntry[][]
|
|
596
|
+
): GeneratedDependencyEntry[] {
|
|
597
|
+
const entries = new Map<string, GeneratedDependencyEntry>();
|
|
598
|
+
|
|
599
|
+
for (const group of groups) {
|
|
600
|
+
for (const entry of group) {
|
|
601
|
+
if (!entries.has(entry.key)) {
|
|
602
|
+
entries.set(entry.key, entry);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return [...entries.values()];
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function createGeneratedDependencyEntry(
|
|
611
|
+
sourceFile: SourceFile,
|
|
612
|
+
dependencyText: string,
|
|
613
|
+
context: 'import' | 'inject',
|
|
614
|
+
): GeneratedDependencyEntry {
|
|
615
|
+
if (context === 'import') {
|
|
616
|
+
const declarableResolution = resolveAngularDeclarableDependency(
|
|
617
|
+
sourceFile,
|
|
618
|
+
dependencyText,
|
|
619
|
+
);
|
|
620
|
+
if (declarableResolution) {
|
|
621
|
+
const generatedTypeName = getGeneratedDepsTypeName(
|
|
622
|
+
declarableResolution.className,
|
|
623
|
+
);
|
|
624
|
+
return {
|
|
625
|
+
key: generatedTypeName,
|
|
626
|
+
typeText: generatedTypeName,
|
|
627
|
+
typeImport: declarableResolution.moduleSpecifier
|
|
628
|
+
? {
|
|
629
|
+
moduleSpecifier: declarableResolution.moduleSpecifier,
|
|
630
|
+
name: generatedTypeName,
|
|
631
|
+
}
|
|
632
|
+
: undefined,
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
return {
|
|
638
|
+
key: createGeneratedDependencyKey(dependencyText),
|
|
639
|
+
typeText: createGeneratedDependencyTypeText(sourceFile, dependencyText),
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function createGeneratedDependencyKey(dependencyText: string): string {
|
|
644
|
+
const lastSegment = dependencyText.split('.').pop() ?? dependencyText;
|
|
645
|
+
const helperMatch = /^(inject|provide)([A-Z].*)$/.exec(lastSegment);
|
|
646
|
+
if (helperMatch) {
|
|
647
|
+
return helperMatch[2];
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const toYieldMatch = /^(.*)ToYield$/.exec(lastSegment);
|
|
651
|
+
if (toYieldMatch?.[1]) {
|
|
652
|
+
return toYieldMatch[1];
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
return lastSegment;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function createGeneratedDependencyTypeText(
|
|
659
|
+
sourceFile: SourceFile,
|
|
660
|
+
dependencyText: string,
|
|
661
|
+
): string {
|
|
662
|
+
if (isHelperLikeDependency(dependencyText)) {
|
|
663
|
+
return `ReturnType<typeof ${dependencyText}>`;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const resolution = resolveDependencyReference(sourceFile, dependencyText);
|
|
667
|
+
if (resolution.kind === 'class' || resolution.kind === 'enum') {
|
|
668
|
+
return dependencyText;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (resolution.kind === 'unknown') {
|
|
672
|
+
return dependencyText;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return `typeof ${dependencyText}`;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
function isHelperLikeDependency(dependencyText: string): boolean {
|
|
679
|
+
const lastSegment = dependencyText.split('.').pop() ?? dependencyText;
|
|
680
|
+
return (
|
|
681
|
+
/^(inject|provide)[A-Z].*/.test(lastSegment) || /ToYield$/.test(lastSegment)
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function resolveAngularDeclarableDependency(
|
|
686
|
+
sourceFile: SourceFile,
|
|
687
|
+
dependencyText: string,
|
|
688
|
+
): { className: string; moduleSpecifier?: string } | undefined {
|
|
689
|
+
const resolution = resolveDependencyReference(sourceFile, dependencyText);
|
|
690
|
+
if (!resolution.classDeclaration) {
|
|
691
|
+
return undefined;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const angularKind = getAngularKind(resolution.classDeclaration);
|
|
695
|
+
if (
|
|
696
|
+
angularKind !== 'component' &&
|
|
697
|
+
angularKind !== 'directive' &&
|
|
698
|
+
angularKind !== 'pipe'
|
|
699
|
+
) {
|
|
700
|
+
return undefined;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
const className = resolution.classDeclaration.getName();
|
|
704
|
+
if (!className) {
|
|
705
|
+
return undefined;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
const declarationSourceFile = resolution.classDeclaration.getSourceFile();
|
|
709
|
+
if (
|
|
710
|
+
declarationSourceFile === sourceFile ||
|
|
711
|
+
declarationSourceFile.isDeclarationFile()
|
|
712
|
+
) {
|
|
713
|
+
return undefined;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return {
|
|
717
|
+
className,
|
|
718
|
+
moduleSpecifier: resolution.moduleSpecifier,
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
function ensureGeneratedDependencyTypeImports(
|
|
723
|
+
sourceFile: SourceFile,
|
|
724
|
+
generatedDependencyGroups: GeneratedDependencyGroups,
|
|
725
|
+
): void {
|
|
726
|
+
const importsToAdd = new Map<string, Set<string>>();
|
|
727
|
+
|
|
728
|
+
for (const entry of generatedDependencyGroups.deps) {
|
|
729
|
+
if (!entry.typeImport) {
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
const importNames =
|
|
734
|
+
importsToAdd.get(entry.typeImport.moduleSpecifier) ?? new Set<string>();
|
|
735
|
+
importNames.add(entry.typeImport.name);
|
|
736
|
+
importsToAdd.set(entry.typeImport.moduleSpecifier, importNames);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
for (const [moduleSpecifier, importNames] of importsToAdd) {
|
|
740
|
+
const existingImport = sourceFile
|
|
741
|
+
.getImportDeclarations()
|
|
742
|
+
.find(
|
|
743
|
+
(importDeclaration) =>
|
|
744
|
+
importDeclaration.getModuleSpecifierValue() === moduleSpecifier,
|
|
745
|
+
);
|
|
746
|
+
|
|
747
|
+
if (existingImport) {
|
|
748
|
+
existingImport.addNamedImports(
|
|
749
|
+
[...importNames].map((name) => ({ name, isTypeOnly: true })),
|
|
750
|
+
);
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
sourceFile.addImportDeclaration({
|
|
755
|
+
moduleSpecifier,
|
|
756
|
+
namedImports: [...importNames].map((name) => ({
|
|
757
|
+
name,
|
|
758
|
+
isTypeOnly: true,
|
|
759
|
+
})),
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function formatGeneratedDependencyType(
|
|
765
|
+
generatedDependencyGroups: GeneratedDependencyGroups,
|
|
766
|
+
): string {
|
|
767
|
+
return [
|
|
768
|
+
'{',
|
|
769
|
+
` deps: ${formatGeneratedDependencyObject(generatedDependencyGroups.deps)};`,
|
|
770
|
+
` provided: ${formatGeneratedDependencyObject(generatedDependencyGroups.provided)};`,
|
|
771
|
+
` missingProvider: ${formatGeneratedDependencyObject(generatedDependencyGroups.missingProvider)};`,
|
|
772
|
+
'}',
|
|
773
|
+
].join('\n');
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function formatGeneratedDependencyObject(
|
|
777
|
+
entries: GeneratedDependencyEntry[],
|
|
778
|
+
): string {
|
|
779
|
+
if (entries.length === 0) {
|
|
780
|
+
return '{}';
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
return [
|
|
784
|
+
'{',
|
|
785
|
+
...entries.map(
|
|
786
|
+
(entry) => ` ${formatObjectKey(entry.key)}: ${entry.typeText};`,
|
|
787
|
+
),
|
|
788
|
+
' }',
|
|
789
|
+
].join('\n');
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
function formatObjectKey(key: string): string {
|
|
793
|
+
return /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : `'${key}'`;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
export function writeGeneratedDepsTypeAlias(
|
|
797
|
+
sourceFile: SourceFile,
|
|
798
|
+
className: string,
|
|
799
|
+
generatedDependencyGroups: GeneratedDependencyGroups,
|
|
800
|
+
): void {
|
|
801
|
+
const generatedTypeName = getGeneratedDepsTypeName(className);
|
|
802
|
+
const generatedType = `GetDeps<${formatGeneratedDependencyType(generatedDependencyGroups)}>`;
|
|
803
|
+
const existingTypeAlias = sourceFile.getTypeAlias(generatedTypeName);
|
|
804
|
+
|
|
805
|
+
if (existingTypeAlias) {
|
|
806
|
+
existingTypeAlias.setIsExported(true);
|
|
807
|
+
existingTypeAlias.setType(generatedType);
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
sourceFile.addTypeAlias({
|
|
812
|
+
isExported: true,
|
|
813
|
+
name: generatedTypeName,
|
|
814
|
+
type: generatedType,
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
export function migrateLegacyBrandExport(
|
|
819
|
+
sourceFile: SourceFile,
|
|
820
|
+
classDeclaration: ClassDeclaration,
|
|
821
|
+
className: string,
|
|
822
|
+
): void {
|
|
823
|
+
const existing = readExistingDependencyGroups(sourceFile, className);
|
|
824
|
+
if (!existing.found || !existing.exportAssignmentNode) {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
const exportAssignment = existing.exportAssignmentNode.asKind(
|
|
829
|
+
SyntaxKind.ExportAssignment,
|
|
830
|
+
);
|
|
831
|
+
exportAssignment?.remove();
|
|
832
|
+
|
|
833
|
+
if (
|
|
834
|
+
!classDeclaration.isDefaultExport() &&
|
|
835
|
+
!classDeclaration.isExported() &&
|
|
836
|
+
exportAssignment
|
|
837
|
+
) {
|
|
838
|
+
classDeclaration.setIsDefaultExport(true);
|
|
839
|
+
}
|
|
498
840
|
}
|
|
499
841
|
|
|
500
842
|
function invalidExistingDependencyGroups(
|
|
@@ -585,7 +927,7 @@ export function ensureHelperImports(
|
|
|
585
927
|
sourceFile: SourceFile,
|
|
586
928
|
helperImportPath: string,
|
|
587
929
|
): void {
|
|
588
|
-
const missingImports = ['
|
|
930
|
+
const missingImports = ['GetDeps'].filter(
|
|
589
931
|
(importName) =>
|
|
590
932
|
!hasLocalNamedImport(sourceFile, helperImportPath, importName),
|
|
591
933
|
);
|
|
@@ -602,51 +944,18 @@ export function ensureHelperImports(
|
|
|
602
944
|
);
|
|
603
945
|
|
|
604
946
|
if (existingImport) {
|
|
605
|
-
existingImport.addNamedImports(
|
|
947
|
+
existingImport.addNamedImports(
|
|
948
|
+
missingImports.map((name) => ({ name, isTypeOnly: true })),
|
|
949
|
+
);
|
|
606
950
|
return;
|
|
607
951
|
}
|
|
608
952
|
|
|
609
953
|
sourceFile.addImportDeclaration({
|
|
610
954
|
moduleSpecifier: helperImportPath,
|
|
611
|
-
namedImports: missingImports
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
export function removeConflictingExports(
|
|
616
|
-
sourceFile: SourceFile,
|
|
617
|
-
classDeclaration: ClassDeclaration,
|
|
618
|
-
className: string,
|
|
619
|
-
): void {
|
|
620
|
-
if (classDeclaration.isDefaultExport()) {
|
|
621
|
-
classDeclaration.setIsDefaultExport(false);
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
if (classDeclaration.isExported()) {
|
|
625
|
-
classDeclaration.setIsExported(false);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
for (const exportAssignment of sourceFile.getExportAssignments()) {
|
|
629
|
-
if (
|
|
630
|
-
isDefaultIdentifierExport(exportAssignment, className) ||
|
|
631
|
-
isDefaultBrandedExport(exportAssignment, className)
|
|
632
|
-
) {
|
|
633
|
-
exportAssignment.remove();
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
for (const exportDeclaration of sourceFile.getExportDeclarations()) {
|
|
638
|
-
removeClassFromExportDeclaration(exportDeclaration, className);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
export function writeDefaultBrandExport(
|
|
643
|
-
sourceFile: SourceFile,
|
|
644
|
-
className: string,
|
|
645
|
-
dependencyGroups: DependencyGroups,
|
|
646
|
-
): void {
|
|
647
|
-
sourceFile.addExportAssignment({
|
|
648
|
-
expression: `brandAngularSymbol(${className}, ${createDepsExpression(dependencyGroups)})`,
|
|
649
|
-
isExportEquals: false,
|
|
955
|
+
namedImports: missingImports.map((name) => ({
|
|
956
|
+
name,
|
|
957
|
+
isTypeOnly: true,
|
|
958
|
+
})),
|
|
650
959
|
});
|
|
651
960
|
}
|
|
652
961
|
|
|
@@ -996,6 +1305,204 @@ function emptyMetadataDependencyGroups(): MetadataDependencyGroups {
|
|
|
996
1305
|
};
|
|
997
1306
|
}
|
|
998
1307
|
|
|
1308
|
+
function extractProvidedDependencies(
|
|
1309
|
+
sourceFile: SourceFile,
|
|
1310
|
+
classDeclaration: ClassDeclaration,
|
|
1311
|
+
angularKind: AngularKind,
|
|
1312
|
+
options: NormalizedOptions,
|
|
1313
|
+
): ProvidedDependencyExtractionResult {
|
|
1314
|
+
const metadata = getDecoratorMetadataObject(classDeclaration);
|
|
1315
|
+
const warnings: string[] = [];
|
|
1316
|
+
const entries: GeneratedDependencyEntry[] = [];
|
|
1317
|
+
|
|
1318
|
+
if (!metadata) {
|
|
1319
|
+
return { entries, warnings };
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
if (options.includeProviders) {
|
|
1323
|
+
entries.push(
|
|
1324
|
+
...extractProvidedDependencyArrayProperty(
|
|
1325
|
+
sourceFile,
|
|
1326
|
+
metadata,
|
|
1327
|
+
'providers',
|
|
1328
|
+
warnings,
|
|
1329
|
+
),
|
|
1330
|
+
);
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
if (options.includeViewProviders && angularKind === 'component') {
|
|
1334
|
+
entries.push(
|
|
1335
|
+
...extractProvidedDependencyArrayProperty(
|
|
1336
|
+
sourceFile,
|
|
1337
|
+
metadata,
|
|
1338
|
+
'viewProviders',
|
|
1339
|
+
warnings,
|
|
1340
|
+
),
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
return {
|
|
1345
|
+
entries: mergeGeneratedDependencyEntries(entries),
|
|
1346
|
+
warnings,
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
function extractProvidedDependencyArrayProperty(
|
|
1351
|
+
sourceFile: SourceFile,
|
|
1352
|
+
metadata: ObjectLiteralExpression,
|
|
1353
|
+
propertyName: 'providers' | 'viewProviders',
|
|
1354
|
+
warnings: string[],
|
|
1355
|
+
): GeneratedDependencyEntry[] {
|
|
1356
|
+
const property = getObjectPropertyAssignment(metadata, propertyName);
|
|
1357
|
+
if (!property) {
|
|
1358
|
+
return [];
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
const initializer = property.getInitializer();
|
|
1362
|
+
if (!Node.isArrayLiteralExpression(initializer)) {
|
|
1363
|
+
warnings.push(
|
|
1364
|
+
`Skipped metadata property "${propertyName}" because it is not a static array.`,
|
|
1365
|
+
);
|
|
1366
|
+
return [];
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
return extractProvidedDependencyEntriesFromArray(
|
|
1370
|
+
sourceFile,
|
|
1371
|
+
initializer,
|
|
1372
|
+
propertyName,
|
|
1373
|
+
warnings,
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
function extractProvidedDependencyEntriesFromArray(
|
|
1378
|
+
sourceFile: SourceFile,
|
|
1379
|
+
arrayLiteral: ArrayLiteralExpression,
|
|
1380
|
+
context: 'providers' | 'viewProviders',
|
|
1381
|
+
warnings: string[],
|
|
1382
|
+
): GeneratedDependencyEntry[] {
|
|
1383
|
+
const entries: GeneratedDependencyEntry[] = [];
|
|
1384
|
+
|
|
1385
|
+
for (const element of arrayLiteral.getElements()) {
|
|
1386
|
+
if (Node.isArrayLiteralExpression(element)) {
|
|
1387
|
+
entries.push(
|
|
1388
|
+
...extractProvidedDependencyEntriesFromArray(
|
|
1389
|
+
sourceFile,
|
|
1390
|
+
element,
|
|
1391
|
+
context,
|
|
1392
|
+
warnings,
|
|
1393
|
+
),
|
|
1394
|
+
);
|
|
1395
|
+
continue;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
if (Node.isSpreadElement(element)) {
|
|
1399
|
+
warnings.push(
|
|
1400
|
+
`Skipped spread element in "${context}" metadata providers.`,
|
|
1401
|
+
);
|
|
1402
|
+
continue;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
if (Node.isCallExpression(element)) {
|
|
1406
|
+
const providerFactory = getStaticExpressionText(element.getExpression());
|
|
1407
|
+
if (!providerFactory) {
|
|
1408
|
+
warnings.push(
|
|
1409
|
+
`Skipped complex provider factory "${element.getText()}" in "${context}".`,
|
|
1410
|
+
);
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
entries.push({
|
|
1415
|
+
key: createGeneratedDependencyKey(providerFactory),
|
|
1416
|
+
typeText: `ReturnType<typeof ${providerFactory}>`,
|
|
1417
|
+
});
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
const staticExpression = getStaticExpressionText(element);
|
|
1422
|
+
if (staticExpression) {
|
|
1423
|
+
entries.push({
|
|
1424
|
+
key: createGeneratedDependencyKey(staticExpression),
|
|
1425
|
+
typeText: createGeneratedDependencyTypeText(
|
|
1426
|
+
sourceFile,
|
|
1427
|
+
staticExpression,
|
|
1428
|
+
),
|
|
1429
|
+
});
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
if (Node.isObjectLiteralExpression(element)) {
|
|
1434
|
+
const providerEntry = extractProvidedDependencyEntryFromObjectLiteral(
|
|
1435
|
+
sourceFile,
|
|
1436
|
+
element,
|
|
1437
|
+
context,
|
|
1438
|
+
warnings,
|
|
1439
|
+
);
|
|
1440
|
+
if (providerEntry) {
|
|
1441
|
+
entries.push(providerEntry);
|
|
1442
|
+
}
|
|
1443
|
+
continue;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
warnings.push(
|
|
1447
|
+
`Skipped complex expression "${element.getText()}" in "${context}" metadata providers.`,
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
return entries;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
function extractProvidedDependencyEntryFromObjectLiteral(
|
|
1455
|
+
sourceFile: SourceFile,
|
|
1456
|
+
objectLiteral: ObjectLiteralExpression,
|
|
1457
|
+
context: 'providers' | 'viewProviders',
|
|
1458
|
+
warnings: string[],
|
|
1459
|
+
): GeneratedDependencyEntry | undefined {
|
|
1460
|
+
const provideProperty = getObjectPropertyAssignment(objectLiteral, 'provide');
|
|
1461
|
+
const provideText = getStaticExpressionText(
|
|
1462
|
+
provideProperty?.getInitializer(),
|
|
1463
|
+
);
|
|
1464
|
+
|
|
1465
|
+
if (!provideText) {
|
|
1466
|
+
warnings.push(
|
|
1467
|
+
`Skipped provider object in "${context}" because "provide" is not static.`,
|
|
1468
|
+
);
|
|
1469
|
+
return undefined;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
const useClass = getStaticExpressionText(
|
|
1473
|
+
getObjectPropertyAssignment(objectLiteral, 'useClass')?.getInitializer(),
|
|
1474
|
+
);
|
|
1475
|
+
const useExisting = getStaticExpressionText(
|
|
1476
|
+
getObjectPropertyAssignment(objectLiteral, 'useExisting')?.getInitializer(),
|
|
1477
|
+
);
|
|
1478
|
+
const useValue = getStaticExpressionText(
|
|
1479
|
+
getObjectPropertyAssignment(objectLiteral, 'useValue')?.getInitializer(),
|
|
1480
|
+
);
|
|
1481
|
+
const useFactory = getStaticExpressionText(
|
|
1482
|
+
getObjectPropertyAssignment(objectLiteral, 'useFactory')?.getInitializer(),
|
|
1483
|
+
);
|
|
1484
|
+
|
|
1485
|
+
if (useFactory) {
|
|
1486
|
+
return {
|
|
1487
|
+
key: createGeneratedDependencyKey(provideText),
|
|
1488
|
+
typeText: `ReturnType<typeof ${useFactory}>`,
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
if (useValue) {
|
|
1493
|
+
return {
|
|
1494
|
+
key: createGeneratedDependencyKey(provideText),
|
|
1495
|
+
typeText: `typeof ${useValue}`,
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
const valueText = useClass ?? useExisting ?? provideText;
|
|
1500
|
+
return {
|
|
1501
|
+
key: createGeneratedDependencyKey(provideText),
|
|
1502
|
+
typeText: createGeneratedDependencyTypeText(sourceFile, valueText),
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
|
|
999
1506
|
function extractMetadataArrayProperty(
|
|
1000
1507
|
metadata: ObjectLiteralExpression,
|
|
1001
1508
|
propertyName: string,
|
|
@@ -1166,6 +1673,208 @@ function getStaticPropertyName(nameNode: Node): string | undefined {
|
|
|
1166
1673
|
return undefined;
|
|
1167
1674
|
}
|
|
1168
1675
|
|
|
1676
|
+
function resolveDependencyReference(
|
|
1677
|
+
sourceFile: SourceFile,
|
|
1678
|
+
dependencyText: string,
|
|
1679
|
+
): DependencyReferenceResolution {
|
|
1680
|
+
const [rootIdentifier] = dependencyText.split('.');
|
|
1681
|
+
if (!rootIdentifier) {
|
|
1682
|
+
return { kind: 'unknown' };
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
const importResolution = resolveImportedDependencyReference(
|
|
1686
|
+
sourceFile,
|
|
1687
|
+
dependencyText,
|
|
1688
|
+
rootIdentifier,
|
|
1689
|
+
);
|
|
1690
|
+
if (importResolution) {
|
|
1691
|
+
return importResolution;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
const localClass = sourceFile.getClass(rootIdentifier);
|
|
1695
|
+
if (localClass) {
|
|
1696
|
+
return { kind: 'class', classDeclaration: localClass };
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
if (sourceFile.getEnum(rootIdentifier)) {
|
|
1700
|
+
return { kind: 'enum' };
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
if (sourceFile.getFunction(rootIdentifier)) {
|
|
1704
|
+
return { kind: 'function' };
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
if (
|
|
1708
|
+
sourceFile
|
|
1709
|
+
.getVariableDeclarations()
|
|
1710
|
+
.some((declaration) => declaration.getName() === rootIdentifier)
|
|
1711
|
+
) {
|
|
1712
|
+
return { kind: 'variable' };
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
return { kind: 'unknown' };
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
function resolveImportedDependencyReference(
|
|
1719
|
+
sourceFile: SourceFile,
|
|
1720
|
+
dependencyText: string,
|
|
1721
|
+
rootIdentifier: string,
|
|
1722
|
+
): DependencyReferenceResolution | undefined {
|
|
1723
|
+
for (const importDeclaration of sourceFile.getImportDeclarations()) {
|
|
1724
|
+
const moduleSpecifier = importDeclaration.getModuleSpecifierValue();
|
|
1725
|
+
|
|
1726
|
+
if (importDeclaration.getDefaultImport()?.getText() === rootIdentifier) {
|
|
1727
|
+
const declaration = getDefaultImportClassDeclaration(importDeclaration);
|
|
1728
|
+
if (declaration) {
|
|
1729
|
+
return {
|
|
1730
|
+
kind: 'class',
|
|
1731
|
+
classDeclaration: declaration,
|
|
1732
|
+
moduleSpecifier,
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
return { kind: 'unknown', moduleSpecifier };
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
if (importDeclaration.getNamespaceImport()?.getText() === rootIdentifier) {
|
|
1740
|
+
const declaration = getNamespaceImportClassDeclaration(
|
|
1741
|
+
importDeclaration,
|
|
1742
|
+
dependencyText,
|
|
1743
|
+
);
|
|
1744
|
+
if (declaration) {
|
|
1745
|
+
return {
|
|
1746
|
+
kind: 'class',
|
|
1747
|
+
classDeclaration: declaration,
|
|
1748
|
+
moduleSpecifier,
|
|
1749
|
+
};
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
return { kind: 'namespace', moduleSpecifier };
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
const namedImport = importDeclaration
|
|
1756
|
+
.getNamedImports()
|
|
1757
|
+
.find((specifier) => {
|
|
1758
|
+
const localName =
|
|
1759
|
+
specifier.getAliasNode()?.getText() ??
|
|
1760
|
+
specifier.getNameNode().getText();
|
|
1761
|
+
return localName === rootIdentifier;
|
|
1762
|
+
});
|
|
1763
|
+
|
|
1764
|
+
if (!namedImport) {
|
|
1765
|
+
continue;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
const localIdentifier =
|
|
1769
|
+
namedImport.getAliasNode() ?? namedImport.getNameNode();
|
|
1770
|
+
const symbol =
|
|
1771
|
+
localIdentifier.getSymbol() ?? localIdentifier.getType().getSymbol();
|
|
1772
|
+
const aliasedSymbol = symbol?.getAliasedSymbol() ?? symbol;
|
|
1773
|
+
const declarations = aliasedSymbol?.getDeclarations() ?? [];
|
|
1774
|
+
const classDeclaration = declarations.find((declaration) =>
|
|
1775
|
+
Node.isClassDeclaration(declaration),
|
|
1776
|
+
);
|
|
1777
|
+
|
|
1778
|
+
if (classDeclaration && Node.isClassDeclaration(classDeclaration)) {
|
|
1779
|
+
return {
|
|
1780
|
+
kind: 'class',
|
|
1781
|
+
classDeclaration,
|
|
1782
|
+
moduleSpecifier,
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
if (
|
|
1787
|
+
declarations.some((declaration) => Node.isEnumDeclaration(declaration))
|
|
1788
|
+
) {
|
|
1789
|
+
return { kind: 'enum', moduleSpecifier };
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
if (
|
|
1793
|
+
declarations.some((declaration) =>
|
|
1794
|
+
Node.isFunctionDeclaration(declaration),
|
|
1795
|
+
)
|
|
1796
|
+
) {
|
|
1797
|
+
return { kind: 'function', moduleSpecifier };
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
if (
|
|
1801
|
+
declarations.some((declaration) =>
|
|
1802
|
+
Node.isVariableDeclaration(declaration),
|
|
1803
|
+
)
|
|
1804
|
+
) {
|
|
1805
|
+
return { kind: 'variable', moduleSpecifier };
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
return { kind: 'unknown', moduleSpecifier };
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
return undefined;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
function getDefaultImportClassDeclaration(
|
|
1815
|
+
importDeclaration: import('ts-morph').ImportDeclaration,
|
|
1816
|
+
): ClassDeclaration | undefined {
|
|
1817
|
+
const moduleSourceFile = importDeclaration.getModuleSpecifierSourceFile();
|
|
1818
|
+
if (!moduleSourceFile) {
|
|
1819
|
+
return undefined;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
const defaultExportSymbol = moduleSourceFile.getDefaultExportSymbol();
|
|
1823
|
+
const declarations = defaultExportSymbol?.getDeclarations() ?? [];
|
|
1824
|
+
return declarations.find((declaration) =>
|
|
1825
|
+
Node.isClassDeclaration(declaration),
|
|
1826
|
+
) as ClassDeclaration | undefined;
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
function getNamespaceImportClassDeclaration(
|
|
1830
|
+
importDeclaration: import('ts-morph').ImportDeclaration,
|
|
1831
|
+
dependencyText: string,
|
|
1832
|
+
): ClassDeclaration | undefined {
|
|
1833
|
+
const moduleSourceFile = importDeclaration.getModuleSpecifierSourceFile();
|
|
1834
|
+
if (!moduleSourceFile) {
|
|
1835
|
+
return undefined;
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
const leafIdentifier = dependencyText.split('.').pop();
|
|
1839
|
+
if (!leafIdentifier) {
|
|
1840
|
+
return undefined;
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
const exportedDeclarations =
|
|
1844
|
+
moduleSourceFile.getExportedDeclarations().get(leafIdentifier) ?? [];
|
|
1845
|
+
return exportedDeclarations.find((declaration) =>
|
|
1846
|
+
Node.isClassDeclaration(declaration),
|
|
1847
|
+
) as ClassDeclaration | undefined;
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
function isProvidedInInjectableTree(
|
|
1851
|
+
sourceFile: SourceFile,
|
|
1852
|
+
dependencyText: string,
|
|
1853
|
+
): boolean {
|
|
1854
|
+
const resolution = resolveDependencyReference(sourceFile, dependencyText);
|
|
1855
|
+
const classDeclaration = resolution.classDeclaration;
|
|
1856
|
+
|
|
1857
|
+
if (!classDeclaration || getAngularKind(classDeclaration) !== 'injectable') {
|
|
1858
|
+
return false;
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
const metadata = getDecoratorMetadataObject(classDeclaration);
|
|
1862
|
+
const providedInProperty = metadata
|
|
1863
|
+
? getObjectPropertyAssignment(metadata, 'providedIn')
|
|
1864
|
+
: undefined;
|
|
1865
|
+
const initializer = providedInProperty?.getInitializer();
|
|
1866
|
+
|
|
1867
|
+
if (!initializer) {
|
|
1868
|
+
return false;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
return (
|
|
1872
|
+
!Node.isNullLiteral(initializer) &&
|
|
1873
|
+
!Node.isFalseLiteral(initializer) &&
|
|
1874
|
+
!(Node.isIdentifier(initializer) && initializer.getText() === 'undefined')
|
|
1875
|
+
);
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1169
1878
|
function getDependencyTextFromTypeNode(typeNode: TypeNode): string | undefined {
|
|
1170
1879
|
if (isPrimitiveTypeNode(typeNode)) {
|
|
1171
1880
|
return undefined;
|
|
@@ -1415,7 +2124,7 @@ function getHelperImportSafety(
|
|
|
1415
2124
|
sourceFile: SourceFile,
|
|
1416
2125
|
helperImportPath: string,
|
|
1417
2126
|
): { safe: true; warnings: [] } | { safe: false; warnings: string[] } {
|
|
1418
|
-
const warnings = ['
|
|
2127
|
+
const warnings = ['GetDeps']
|
|
1419
2128
|
.filter((helperName) =>
|
|
1420
2129
|
hasConflictingTopLevelBinding(sourceFile, helperImportPath, helperName),
|
|
1421
2130
|
)
|
|
@@ -1680,9 +2389,9 @@ function logFileResult(
|
|
|
1680
2389
|
`file=${report.filePath}`,
|
|
1681
2390
|
report.angularKind ? `kind=${report.angularKind}` : undefined,
|
|
1682
2391
|
report.className ? `class=${report.className}` : undefined,
|
|
1683
|
-
`
|
|
1684
|
-
`
|
|
1685
|
-
`
|
|
2392
|
+
`deps=[${report.generatedDependencyGroups.deps.map((entry) => entry.key).join(', ')}]`,
|
|
2393
|
+
`provided=[${report.generatedDependencyGroups.provided.map((entry) => entry.key).join(', ')}]`,
|
|
2394
|
+
`missingProvider=[${report.generatedDependencyGroups.missingProvider.map((entry) => entry.key).join(', ')}]`,
|
|
1686
2395
|
`status=${status}`,
|
|
1687
2396
|
].filter(Boolean);
|
|
1688
2397
|
|
|
@@ -1760,17 +2469,22 @@ function printHelpAndExit(): never {
|
|
|
1760
2469
|
Options:
|
|
1761
2470
|
--root <dir> Project root. Defaults to cwd.
|
|
1762
2471
|
--tsconfig <path> tsconfig path. Defaults to <root>/tsconfig.json.
|
|
1763
|
-
--helper-import <path> Import path for
|
|
2472
|
+
--helper-import <path> Import path for GetDeps.
|
|
1764
2473
|
--transform-only-standalone-declarables Only transform standalone components/directives.
|
|
1765
|
-
--no-providers Do not include metadata providers in
|
|
1766
|
-
--no-view-providers Do not include component viewProviders in
|
|
2474
|
+
--no-providers Do not include metadata providers in generated types.
|
|
2475
|
+
--no-view-providers Do not include component viewProviders in generated types.
|
|
1767
2476
|
--dry-run Print results without writing files.
|
|
1768
2477
|
--help Show this help.
|
|
1769
2478
|
`);
|
|
1770
2479
|
process.exit(0);
|
|
1771
2480
|
}
|
|
1772
2481
|
|
|
1773
|
-
if (require.main === module)
|
|
2482
|
+
// Check if this module is being run directly (ESM equivalent of require.main === module)
|
|
2483
|
+
if (
|
|
2484
|
+
import.meta.url === `file://${process.argv[1]}` ||
|
|
2485
|
+
(import.meta.url.startsWith('file:') &&
|
|
2486
|
+
process.argv[1] === fileURLToPath(import.meta.url))
|
|
2487
|
+
) {
|
|
1774
2488
|
runAngularBrandCodemod(parseCliArgs(process.argv.slice(2))).catch(
|
|
1775
2489
|
(error: unknown) => {
|
|
1776
2490
|
console.error(error);
|