@@ -14,7 +14,6 @@ import {
14
14
logging ,
15
15
normalize ,
16
16
parseJson ,
17
- parseJsonAst ,
18
17
tags ,
19
18
} from '@angular-devkit/core' ;
20
19
import {
@@ -31,10 +30,7 @@ import {
31
30
NodeDependencyType ,
32
31
addPackageJsonDependency ,
33
32
} from '../../utility/dependencies' ;
34
- import {
35
- appendValueInAstArray ,
36
- findPropertyInAstObject ,
37
- } from '../../utility/json-utils' ;
33
+ import { JSONFile } from '../../utility/json-file' ;
38
34
import { latestVersions } from '../../utility/latest-versions' ;
39
35
40
36
const defaults = {
@@ -624,41 +620,35 @@ function extractDefaultProject(config: CliConfig): string | null {
624
620
}
625
621
626
622
function updateSpecTsConfig ( config : CliConfig ) : Rule {
627
- return ( host : Tree , context : SchematicContext ) => {
623
+ return ( host ) => {
628
624
const apps = config . apps || [ ] ;
629
- apps . forEach ( ( app : AppConfig , idx : number ) => {
625
+ apps . forEach ( ( app : AppConfig ) => {
630
626
const testTsConfig = app . testTsconfig || defaults . testTsConfig ;
631
627
const tsSpecConfigPath = join ( normalize ( app . root || '' ) , testTsConfig ) ;
632
- const buffer = host . read ( tsSpecConfigPath ) ;
633
628
634
- if ( ! buffer ) {
629
+ let tsConfigJson ;
630
+ try {
631
+ tsConfigJson = new JSONFile ( host , tsSpecConfigPath ) ;
632
+ } catch {
635
633
return ;
636
634
}
637
635
638
-
639
- const tsCfgAst = parseJsonAst ( buffer . toString ( ) , JsonParseMode . Loose ) ;
640
- if ( tsCfgAst . kind != 'object' ) {
641
- throw new SchematicsException ( 'Invalid tsconfig. Was expecting an object' ) ;
636
+ const files = tsConfigJson . get ( [ 'files' ] ) ;
637
+ if ( files === undefined ) {
638
+ // Do nothing if the files array does not exist. This means exclude or include are
639
+ // set and we shouldn't mess with that.
640
+ return ;
642
641
}
643
642
644
- const filesAstNode = findPropertyInAstObject ( tsCfgAst , 'files' ) ;
645
- if ( filesAstNode && filesAstNode . kind != 'array' ) {
643
+ if ( ! Array . isArray ( files ) ) {
646
644
throw new SchematicsException ( 'Invalid tsconfig "files" property; expected an array.' ) ;
647
645
}
648
646
649
- const recorder = host . beginUpdate ( tsSpecConfigPath ) ;
650
-
651
647
const polyfills = app . polyfills || defaults . polyfills ;
652
- if ( ! filesAstNode ) {
653
- // Do nothing if the files array does not exist. This means exclude or include are
654
- // set and we shouldn't mess with that.
655
- } else {
656
- if ( filesAstNode . value . indexOf ( polyfills ) == - 1 ) {
657
- appendValueInAstArray ( recorder , filesAstNode , polyfills ) ;
658
- }
648
+ if ( polyfills && ! files . includes ( polyfills ) ) {
649
+ // Append polyfills file to the files array
650
+ tsConfigJson . modify ( [ 'files' , - 1 ] , polyfills ) ;
659
651
}
660
-
661
- host . commitUpdate ( recorder ) ;
662
652
} ) ;
663
653
} ;
664
654
}
@@ -682,111 +672,63 @@ function updatePackageJson(config: CliConfig) {
682
672
}
683
673
684
674
function updateTsLintConfig ( ) : Rule {
685
- return ( host : Tree , context : SchematicContext ) => {
675
+ return ( host ) => {
686
676
const tsLintPath = '/tslint.json' ;
687
- const buffer = host . read ( tsLintPath ) ;
688
- if ( ! buffer ) {
689
- return host ;
690
- }
691
- const tsCfgAst = parseJsonAst ( buffer . toString ( ) , JsonParseMode . Loose ) ;
692
-
693
- if ( tsCfgAst . kind != 'object' ) {
694
- return host ;
695
- }
696
-
697
- const rulesNode = findPropertyInAstObject ( tsCfgAst , 'rules' ) ;
698
- if ( ! rulesNode || rulesNode . kind != 'object' ) {
699
- return host ;
700
- }
701
677
702
- const importBlacklistNode = findPropertyInAstObject ( rulesNode , 'import-blacklist' ) ;
703
- if ( ! importBlacklistNode || importBlacklistNode . kind != 'array' ) {
704
- return host ;
678
+ let tsLintJson ;
679
+ try {
680
+ tsLintJson = new JSONFile ( host , tsLintPath ) ;
681
+ } catch {
682
+ return ;
705
683
}
706
684
707
- const recorder = host . beginUpdate ( tsLintPath ) ;
708
- for ( let i = 0 ; i < importBlacklistNode . elements . length ; i ++ ) {
709
- const element = importBlacklistNode . elements [ i ] ;
710
- if ( element . kind == 'string' && element . value == 'rxjs' ) {
711
- const { start, end } = element ;
712
- // Remove this element.
713
- if ( i == importBlacklistNode . elements . length - 1 ) {
714
- // Last element.
715
- if ( i > 0 ) {
716
- // Not first, there's a comma to remove before.
717
- const previous = importBlacklistNode . elements [ i - 1 ] ;
718
- recorder . remove ( previous . end . offset , end . offset - previous . end . offset ) ;
719
- } else {
720
- // Only element, just remove the whole rule.
721
- const { start, end } = importBlacklistNode ;
722
- recorder . remove ( start . offset , end . offset - start . offset ) ;
723
- recorder . insertLeft ( start . offset , '[]' ) ;
724
- }
725
- } else {
726
- // Middle, just remove the whole node (up to next node start).
727
- const next = importBlacklistNode . elements [ i + 1 ] ;
728
- recorder . remove ( start . offset , next . start . offset - start . offset ) ;
729
- }
730
- }
685
+ const rulePath = [ 'rules' , 'import-blacklist' ] ;
686
+ const currentRuleItems = tsLintJson . get ( rulePath ) ;
687
+ if ( ! currentRuleItems || ! Array . isArray ( currentRuleItems ) ) {
688
+ return ;
731
689
}
732
690
733
- host . commitUpdate ( recorder ) ;
734
-
735
- return host ;
691
+ // Remove all occurences of rxjs
692
+ const newRuleItems = currentRuleItems . filter ( value => value !== 'rxjs' ) ;
693
+ tsLintJson . modify ( rulePath , newRuleItems ) ;
736
694
} ;
737
695
}
738
696
739
697
function updateRootTsConfig ( ) : Rule {
740
698
return ( host : Tree , context : SchematicContext ) => {
741
699
const tsConfigPath = '/tsconfig.json' ;
742
- const buffer = host . read ( tsConfigPath ) ;
743
- if ( ! buffer ) {
744
- return ;
745
- }
746
-
747
- const tsCfgAst = parseJsonAst ( buffer . toString ( ) , JsonParseMode . Loose ) ;
748
- if ( tsCfgAst . kind !== 'object' ) {
749
- throw new SchematicsException ( 'Invalid root tsconfig. Was expecting an object' ) ;
750
- }
751
-
752
- const compilerOptionsAstNode = findPropertyInAstObject ( tsCfgAst , 'compilerOptions' ) ;
753
- if ( ! compilerOptionsAstNode || compilerOptionsAstNode . kind != 'object' ) {
754
- throw new SchematicsException (
755
- 'Invalid root tsconfig "compilerOptions" property; expected an object.' ,
756
- ) ;
757
- }
758
700
759
- if (
760
- findPropertyInAstObject ( compilerOptionsAstNode , 'baseUrl' ) &&
761
- findPropertyInAstObject ( compilerOptionsAstNode , 'module' )
762
- ) {
763
- return host ;
701
+ let tsConfigJson ;
702
+ try {
703
+ tsConfigJson = new JSONFile ( host , tsConfigPath ) ;
704
+ } catch {
705
+ return ;
764
706
}
765
707
766
- const compilerOptions = compilerOptionsAstNode . value ;
767
- const { baseUrl = './' , module = 'es2015' } = compilerOptions ;
768
-
769
- const validBaseUrl = [ './' , '' , '.' ] ;
770
- if ( ! validBaseUrl . includes ( baseUrl as string ) ) {
771
- const formattedBaseUrl = validBaseUrl . map ( x => `'${ x } '` ) . join ( ', ' ) ;
772
- context . logger . warn ( tags . oneLine
773
- `Root tsconfig option 'baseUrl' is not one of: ${ formattedBaseUrl } .
774
- This might cause unexpected behaviour when generating libraries.` ,
775
- ) ;
708
+ const baseUrlPath = [ 'compilerOptions' , 'baseUrl' ] ;
709
+ const baseUrl = tsConfigJson . get ( baseUrlPath ) ;
710
+ if ( baseUrl === undefined || typeof baseUrl !== 'string' ) {
711
+ tsConfigJson . modify ( baseUrlPath , './' ) ;
712
+ } else {
713
+ const validBaseUrl = [ './' , '' , '.' ] ;
714
+ if ( ! validBaseUrl . includes ( baseUrl ) ) {
715
+ const formattedBaseUrl = validBaseUrl . map ( x => `'${ x } '` ) . join ( ', ' ) ;
716
+ context . logger . warn ( tags . oneLine
717
+ `Root tsconfig option 'baseUrl' is not one of: ${ formattedBaseUrl } .
718
+ This might cause unexpected behaviour when generating libraries.` ,
719
+ ) ;
720
+ }
776
721
}
777
722
778
- if ( module !== 'es2015' ) {
723
+ const modulePath = [ 'compilerOptions' , 'module' ] ;
724
+ const module = tsConfigJson . get ( modulePath ) ;
725
+ if ( module === undefined || typeof module !== 'string' ) {
726
+ tsConfigJson . modify ( modulePath , 'es2015' ) ;
727
+ } else if ( module . toLowerCase ( ) !== 'es2015' ) {
779
728
context . logger . warn (
780
729
`Root tsconfig option 'module' is not 'es2015'. This might cause unexpected behaviour.` ,
781
730
) ;
782
731
}
783
-
784
- compilerOptions . module = module ;
785
- compilerOptions . baseUrl = baseUrl ;
786
-
787
- host . overwrite ( tsConfigPath , JSON . stringify ( tsCfgAst . value , null , 2 ) ) ;
788
-
789
- return host ;
790
732
} ;
791
733
}
792
734
0 commit comments