1import * as fs from "fs"; 2import * as path from "path"; 3import * as os from "os"; 4import * as childProcess from "child_process"; 5import url from "url"; 6 7const __filename = url.fileURLToPath(new URL(import.meta.url)); 8const __dirname = path.dirname(__filename); 9 10main(); 11function main() { 12 const [, progName, tscRoot, definitelyTypedRoot] = process.argv; 13 if (process.argv.length !== 4) { 14 if (process.argv.length < 2) { 15 throw new Error("Expected at least 2 argv elements."); 16 } 17 console.log("Usage:"); 18 console.log(` node ${path.relative(__dirname, progName)} [TypeScript Repo Root] [DefinitelyTyped Repo Root]`); 19 return; 20 } 21 22 const tscPath = path.resolve(tscRoot, "built", "local", "tsc.js"); 23 const rwcTestPath = path.resolve(tscRoot, "internal", "cases", "rwc"); 24 const resolvedDefinitelyTypedRoot = path.resolve(definitelyTypedRoot); 25 26 console.log(`Resolved TypeScript Compiler Path: '${tscPath}'.`); 27 console.log(`Resolved TypeScript RWC Path: '${rwcTestPath}'.`); 28 console.log(`Resolved DefinitelyTyped Repo Root: '${resolvedDefinitelyTypedRoot}'.`); 29 importDefinitelyTypedTests(tscPath, rwcTestPath, resolvedDefinitelyTypedRoot); 30} 31 32/** 33 * @param {string} path 34 * @param {string} endingString 35 * @returns {boolean} 36 */ 37function filePathEndsWith(path, endingString) { 38 const pathLen = path.length; 39 const extLen = endingString.length; 40 return pathLen > extLen && path.substr(pathLen - extLen, extLen).toLocaleLowerCase() === endingString.toLocaleLowerCase(); 41} 42 43/** 44 * @param {string} source 45 * @param {string} destination 46 */ 47function copyFileSync(source, destination) { 48 const text = fs.readFileSync(source); 49 fs.writeFileSync(destination, text); 50} 51 52/** 53 * @param {string} tscPath 54 * @param {string} rwcTestPath 55 * @param {string} testCaseName 56 * @param {string[]} testFiles 57 * @param {string | undefined} responseFile 58 */ 59function importDefinitelyTypedTest(tscPath, rwcTestPath, testCaseName, testFiles, responseFile) { 60 let cmd = "node " + tscPath + " --module commonjs " + testFiles.join(" "); 61 if (responseFile) { 62 cmd += " @" + responseFile; 63 } 64 65 const testDirectoryName = testCaseName + "_" + Math.floor((Math.random() * 10000) + 1); 66 const testDirectoryPath = path.join(os.tmpdir(), testDirectoryName); 67 if (fs.existsSync(testDirectoryPath)) { 68 throw new Error("Could not create test directory"); 69 } 70 fs.mkdirSync(testDirectoryPath); 71 72 childProcess.exec(cmd, { 73 maxBuffer: 1 * 1024 * 1024, 74 cwd: testDirectoryPath 75 }, (error, stdout, stderr) => { 76 console.log("importing " + testCaseName + " ..."); 77 console.log(cmd); 78 79 if (error) { 80 console.log("importing " + testCaseName + " ..."); 81 console.log(cmd); 82 console.log("==> error " + JSON.stringify(error)); 83 console.log("==> stdout " + String(stdout)); 84 console.log("==> stderr " + String(stderr)); 85 console.log("\r\n"); 86 return; 87 } 88 89 // copy generated file to output location 90 const outputFilePath = path.join(testDirectoryPath, "iocapture0.json"); 91 const testCasePath = path.join(rwcTestPath, "DefinitelyTyped_" + testCaseName + ".json"); 92 copyFileSync(outputFilePath, testCasePath); 93 94 //console.log("output generated at: " + outputFilePath); 95 96 if (!fs.existsSync(testCasePath)) { 97 throw new Error("could not find test case at: " + testCasePath); 98 } 99 else { 100 fs.unlinkSync(outputFilePath); 101 fs.rmdirSync(testDirectoryPath); 102 //console.log("testcase generated at: " + testCasePath); 103 //console.log("Done."); 104 } 105 //console.log("\r\n"); 106 107 }).on("error", (error) => { 108 console.log("==> error " + JSON.stringify(error)); 109 console.log("\r\n"); 110 }); 111} 112 113/** 114 * @param {string} tscPath 115 * @param {string} rwcTestPath 116 * @param {string} definitelyTypedRoot 117 */ 118function importDefinitelyTypedTests(tscPath, rwcTestPath, definitelyTypedRoot) { 119 fs.readdir(definitelyTypedRoot, (err, subDirectories) => { 120 if (err) { 121 throw err; 122 } 123 124 // When you just want to test the script out on one or two files, 125 // just add a line like the following: 126 // 127 // .filter(d => d.indexOf("sipml") >= 0 ) 128 subDirectories 129 .filter(d => ["_infrastructure", "node_modules", ".git"].indexOf(d) < 0) 130 .filter(i => fs.statSync(path.join(definitelyTypedRoot, i)).isDirectory()) 131 .forEach(d => { 132 const directoryPath = path.join(definitelyTypedRoot, d); 133 fs.readdir(directoryPath, (err, files) => { 134 if (err) { 135 throw err; 136 } 137 138 /** @type {string[]} */ 139 const tsFiles = []; 140 /** @type {string[]} */ 141 const testFiles = []; 142 /** @type {string | undefined} */ 143 let paramFile; 144 145 for (const filePath of files.map(f => path.join(directoryPath, f))) { 146 if (filePathEndsWith(filePath, ".ts")) { 147 tsFiles.push(filePath); 148 149 if (filePathEndsWith(filePath, "-tests.ts")) { 150 testFiles.push(filePath); 151 } 152 } 153 else if (filePathEndsWith(filePath, ".tscparams")) { 154 paramFile = filePath; 155 } 156 } 157 158 if (testFiles.length === 0) { 159 // no test files but multiple d.ts's, e.g. winjs 160 const regexp = new RegExp(d + "(([-][0-9])|(\\.d\\.ts))"); 161 if (tsFiles.length > 1 && tsFiles.every(t => filePathEndsWith(t, ".d.ts") && regexp.test(t))) { 162 for (const fileName of tsFiles) { 163 importDefinitelyTypedTest(tscPath, rwcTestPath, path.basename(fileName, ".d.ts"), [fileName], paramFile); 164 } 165 } 166 else { 167 importDefinitelyTypedTest(tscPath, rwcTestPath, d, tsFiles, paramFile); 168 } 169 } 170 else { 171 for (const fileName of tsFiles) { 172 importDefinitelyTypedTest(tscPath, rwcTestPath, path.basename(fileName, "-tests.ts"), [fileName], paramFile); 173 } 174 } 175 }); 176 }); 177 }); 178} 179