55
66/* eslint-env node */
77
8- const { Project, ts} = require ( "ts-morph" )
9- const path = require ( "path" )
10- const fs = require ( "fs-extra" )
8+ import {
9+ Directory ,
10+ ExportDeclaration ,
11+ GetAccessorDeclaration ,
12+ ImportDeclaration ,
13+ Project ,
14+ SetAccessorDeclaration ,
15+ SourceFile ,
16+ ts ,
17+ } from "ts-morph"
18+ import * as path from "path"
19+ import * as fs from "fs-extra"
1120
12- const project = new Project ( )
13- const inputDir = project . addDirectoryAtPath ( path . join ( __dirname , "../../lib/" ) )
21+ async function main ( ) {
22+ const project = new Project ( )
23+ const inputDir = project . addDirectoryAtPath ( path . join ( __dirname , "../lib/" ) )
1424
15- // Create output directory
16- fs . emptyDirSync ( path . join ( inputDir . getPath ( ) . toString ( ) , "ts3.6" ) )
17- const ts36Dir = inputDir . createDirectory ( "ts3.6" )
18- project . saveSync ( )
25+ // Create output directory
26+ const oldestSupportedTS = "ts3.7"
1927
20- // Down-level all *.d.ts files in input directory
21- const files = inputDir . addSourceFilesAtPaths ( "*.d.ts" )
22- for ( const f of files ) {
23- // Create copy for TypeScript 3.6+
24- copyTypingsFile ( f , ts36Dir )
25- downlevelTS36 ( f )
26- downlevelTS34 ( f )
27- // Original file will be overwritten by down-leveled file when saved
28+ fs . emptyDirSync ( path . join ( inputDir . getPath ( ) . toString ( ) , oldestSupportedTS ) )
29+ const tsDownDir = inputDir . createDirectory ( oldestSupportedTS )
30+ project . saveSync ( )
31+
32+ // Down-level all *.d.ts files in input directory
33+ const files = inputDir . addSourceFilesAtPaths ( "*.d.ts" )
34+ for ( const file of files ) {
35+ // Create copy for TypeScript 3.7
36+ copyTypingsFile ( file , tsDownDir )
37+ downlevelTS36 ( file )
38+ // Original file will be overwritten by down-leveled file when saved
39+ }
40+ project . saveSync ( )
2841}
29- project . saveSync ( )
42+
43+ main ( ) . catch ( err => {
44+ throw err
45+ } )
3046
3147/**
3248 * Copy typings source file *.d.ts to target dir
3349 */
34- function copyTypingsFile ( f , targetDir ) {
35- const cf = f . copyToDirectory ( targetDir , { overwrite : true } )
36- const srcPath = f . getDirectoryPath ( )
50+ function copyTypingsFile ( file : SourceFile , targetDir : Directory ) {
51+ const cFile = file . copyToDirectory ( targetDir , { overwrite : true } )
52+ const srcPath = file . getDirectoryPath ( )
3753 const targetPath = targetDir . getPath ( )
38- revertModulePathChange ( cf . getImportDeclarations ( ) , srcPath , targetPath )
39- revertModulePathChange ( cf . getExportDeclarations ( ) , srcPath , targetPath )
54+ revertModulePathChange ( cFile . getImportDeclarations ( ) , srcPath , targetPath )
55+ revertModulePathChange ( cFile . getExportDeclarations ( ) , srcPath , targetPath )
4056}
4157
58+ type StandardizedFilePath = ReturnType < SourceFile [ "getDirectoryPath" ] >
59+
4260/**
4361 * HELPER for reverting changed relative paths for import/export declarations in
4462 * copied files, so they to not point to the source-directory but the other
@@ -49,14 +67,18 @@ function copyTypingsFile(f, targetDir) {
4967 * [after copied to targetDir] from "../<module-file>"
5068 * [reverted in targetDir] from "./<module-file>"
5169 */
52- function revertModulePathChange ( importExportDecl , srcDir , targetDir ) {
70+ function revertModulePathChange (
71+ importExportDecl : ImportDeclaration [ ] | ExportDeclaration [ ] ,
72+ srcDir : StandardizedFilePath ,
73+ targetDir : StandardizedFilePath ,
74+ ) {
5375 const absSrcDir = path . resolve ( srcDir )
5476 for ( const decl of importExportDecl ) {
5577 if ( ! decl . isModuleSpecifierRelative ( ) ) {
5678 continue
5779 }
5880 const declPath = decl . getModuleSpecifierValue ( )
59- if ( ! declPath ) {
81+ if ( declPath === undefined ) {
6082 continue
6183 }
6284 const absDeclPath = path . resolve ( path . join ( targetDir , declPath ) )
@@ -69,9 +91,9 @@ function revertModulePathChange(importExportDecl, srcDir, targetDir) {
6991/**
7092 * Down-level TypeScript 3.6 types in the given source file
7193 */
72- function downlevelTS36 ( f ) {
94+ function downlevelTS36 ( file : SourceFile ) {
7395 // Replace get/set accessors with (read-only) properties
74- const gs = f . getDescendantsOfKind ( ts . SyntaxKind . GetAccessor )
96+ const gs = file . getDescendantsOfKind ( ts . SyntaxKind . GetAccessor )
7597 for ( const g of gs ) {
7698 const comment = getLeadingComments ( g )
7799 const s = g . getSetAccessor ( )
@@ -86,13 +108,13 @@ function downlevelTS36(f) {
86108 s . remove ( )
87109 }
88110 }
89- const ss = f . getDescendantsOfKind ( ts . SyntaxKind . SetAccessor )
111+ const ss = file . getDescendantsOfKind ( ts . SyntaxKind . SetAccessor )
90112 for ( const s of ss ) {
91113 const g = s . getGetAccessor ( )
92114 if ( ! g ) {
93115 const comment = getLeadingComments ( s )
94116 const firstParam = s . getParameters ( ) [ 0 ]
95- const firstParamTypeNode = firstParam && firstParam . getTypeNode ( )
117+ const firstParamTypeNode = firstParam ? .getTypeNode ( )
96118 const firstParamType = firstParamTypeNode
97119 ? firstParamTypeNode . getText ( )
98120 : "any"
@@ -103,49 +125,19 @@ function downlevelTS36(f) {
103125 }
104126}
105127
106- /**
107- * Down-level TypeScript 3.4 types in the given source file
108- */
109- function downlevelTS34 ( f ) {
110- // Replace "es2018.asynciterable" with "esnext.asynciterable" in lib references
111- const refs = f . getLibReferenceDirectives ( )
112- for ( const r of refs ) {
113- if ( r . getFileName ( ) === "es2018.asynciterable" ) {
114- f . replaceText ( [ r . getPos ( ) , r . getEnd ( ) ] , "esnext.asynciterable" )
115- }
116- }
117- downlevelEs2018 ( f )
118- }
119-
120- /**
121- * Down-level es2018 to esnext library in the given source file
122- */
123- function downlevelEs2018 ( f ) {
124- // Replace AsyncIterator<T1,T2> with AsyncIterator<T1>
125- const typeParams = f . getDescendantsOfKind ( ts . SyntaxKind . TypeReference )
126- for ( const t of typeParams ) {
127- if ( t . wasForgotten ( ) ) {
128- continue
129- }
130- const typeName = t . getTypeName ( ) . getText ( )
131- if ( typeName === "AsyncIterator" ) {
132- const params = t . getTypeArguments ( )
133- if ( params . length > 1 ) {
134- t . replaceWithText ( `${ typeName } <${ params [ 0 ] . getText ( ) } >` )
135- }
136- }
137- }
138- }
139-
140- function getModifiersText ( node ) {
128+ function getModifiersText (
129+ node : GetAccessorDeclaration | SetAccessorDeclaration ,
130+ ) {
141131 const modifiersText = node
142132 . getModifiers ( )
143133 . map ( m => m . getText ( ) )
144134 . join ( " " )
145135 return modifiersText . length > 0 ? `${ modifiersText } ` : ""
146136}
147137
148- function getLeadingComments ( node ) {
138+ function getLeadingComments (
139+ node : GetAccessorDeclaration | SetAccessorDeclaration ,
140+ ) {
149141 const t = node . getText ( )
150142 const tlen = t . length
151143 const ct = node . getText ( true )
@@ -163,7 +155,10 @@ function getLeadingComments(node) {
163155 . replace ( / ( \r ? \n ) \s + $ / gm, "$1" )
164156}
165157
166- function relativeModulePath ( fromAbsModulePath , toAbsTargetDir ) {
158+ function relativeModulePath (
159+ fromAbsModulePath : string ,
160+ toAbsTargetDir : StandardizedFilePath ,
161+ ) {
167162 const fromModDir = path . dirname ( fromAbsModulePath )
168163 const revertedPath = path . resolve (
169164 fromModDir ,
0 commit comments