-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathgenerate-tns-compat.ts
More file actions
171 lines (137 loc) · 5.72 KB
/
generate-tns-compat.ts
File metadata and controls
171 lines (137 loc) · 5.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import * as path from 'path';
import * as fs from 'fs';
import readdirp, { EntryInfo } from 'readdirp';
const inputFolder = path.resolve('dist/packages/core');
const outputFolder = path.resolve('dist/packages/tns-core-modules');
const testImports: string[] = [];
// List of definition files that don't need to be exported.
const dtsBlacklist = ['global-types.d.ts', 'references.d.ts'];
// List of modules that should be re-exported despite they are private
const privateModulesWhitelist = [
'ui/styling/style-scope', //Reason: nativescript-dev-webpack generates code that imports this module
];
// There are few module using the "export default" syntax
// They should be handled differently when re-exporting
const modulesWithDefaultExports = ['utils/lazy'];
function traverseInputDir(fileFilter: string[], callback: (entry: EntryInfo) => void) {
return new Promise((resolve, reject) => {
readdirp(inputFolder, {
fileFilter,
directoryFilter: (di: EntryInfo) => {
return !di.path.startsWith('node_modules') && !di.path.startsWith('platforms');
},
})
.on('data', callback)
.on('error', reject)
.on('end', resolve);
});
}
function processPackageJsonFile(entry: EntryInfo) {
const dirPath = path.dirname(entry.path);
const outputFilePath = path.join(outputFolder, entry.path);
ensureDirectoryExistence(outputFilePath);
const json = require(entry.fullPath);
if (json.main) {
(<any>fs).copyFileSync(entry.fullPath, outputFilePath);
logFileCreated(outputFilePath);
addTestImport(dirPath);
const mainFile = path.join(dirPath, json.main);
createReExportFile(mainFile, '.ts');
addTestImport(mainFile);
}
}
function processDefinitionFile(entry: EntryInfo) {
if (dtsBlacklist.includes(entry.path)) {
return;
}
const relativeFilePathNoExt = entry.path.replace(/\.d\.ts$/, '');
// Re-export everything from d.ts file
createReExportFile(relativeFilePathNoExt, '.d.ts');
// This might be only a definitions file.
// So check if there is ts/js files before creating TS file with re-exports
const baseFile = path.join(inputFolder, relativeFilePathNoExt);
if (fs.existsSync(baseFile + '.ts') || fs.existsSync(baseFile + '.js') || (fs.existsSync(baseFile + '.android.ts') && fs.existsSync(baseFile + '.ios.ts')) || (fs.existsSync(baseFile + '.android.js') && fs.existsSync(baseFile + '.ios.js'))) {
createReExportFile(relativeFilePathNoExt, '.ts');
addTestImport(relativeFilePathNoExt);
}
}
function processTypeScriptFile(entry: EntryInfo) {
const relativeFilePathNoExt = entry.path.replace(/\.ts$/, '');
createReExportFile(relativeFilePathNoExt, '.ts');
addTestImport(relativeFilePathNoExt);
}
function createReExportFile(pathNoExt: string, ext: '.ts' | '.d.ts') {
const outputFile = path.join(outputFolder, pathNoExt + ext);
if (!fs.existsSync(outputFile)) {
ensureDirectoryExistence(outputFile);
let content = `export * from "@nativescript/core/${pathNoExt}";`;
if (modulesWithDefaultExports.includes(pathNoExt)) {
content = `import defExport from "@nativescript/core/${pathNoExt}";\n`;
content += `export default defExport;`;
}
fs.writeFileSync(outputFile, content);
logFileCreated(outputFile);
}
}
function ensureDirectoryExistence(filePath: string) {
const dirname = path.dirname(filePath);
if (fs.existsSync(dirname)) {
return true;
}
ensureDirectoryExistence(dirname);
fs.mkdirSync(dirname);
}
function logFileCreated(file: string) {
console.log(`CREATED: ${file}`);
}
function addTestImport(moduleName: string) {
testImports.push(moduleName);
}
function generateTestFile() {
const uniqueImports = Array.from(new Set(testImports)).sort();
const output: string[] = [];
output.push(`/* tslint:disable */`);
output.push(`import { compare, report } from "./module-compare";\n\n`);
uniqueImports.forEach((name) => {
const moduleName = name.replace(/[\.\/\-]/g, '_');
const compatName = `module_${moduleName}_compat`;
const coreName = `module_${moduleName}_core`;
output.push(`import * as ${coreName} from "@nativescript/core/${name}";`);
output.push(`import * as ${compatName} from "tns-core-modules/${name}";`);
output.push(`compare("${name}", ${coreName}, ${compatName});\n`);
});
output.push(`\n`);
output.push(`report();`);
const testFilePath = path.resolve('dist/generated-tests/tests.ts');
ensureDirectoryExistence(testFilePath);
fs.writeFileSync(testFilePath, output.join('\n'), 'utf8');
(<any>fs).copyFileSync(path.resolve('build/generated-compat-checks/module-compare.ts'), path.resolve('dist/generated-tests/module-compare.ts'));
console.log(`Compat tests generated: ${testFilePath}`);
}
function generateExportsForPrivateModules() {
privateModulesWhitelist.forEach((pathNoExt) => {
createReExportFile(pathNoExt, '.ts');
addTestImport(pathNoExt);
});
}
(async () => {
console.log(' ------> GENERATING FILES FORM PACKAGE.JSON');
// Traverse all package.json files and create:
// * .ts file with re-exports for the package.json/main
// * .d.ts file with re-exports for the package.json/types
await traverseInputDir(['package.json'], processPackageJsonFile);
console.log(' ------> GENERATING FILES FORM DEFINITIONS');
// Traverse all d.ts files and create
// * .d.ts file with re-exports for definitions for the .d.ts
// * .ts file with re-exports for the corresponding ts/js file (is such exists)
await traverseInputDir(['*.d.ts'], processDefinitionFile);
console.log(' ------> GENERATING FILES FROM TYPESCRIPT');
// Traverse all ts files which are not platform specific and create
// * .ts file with re-exports for the corresponding ts file
await traverseInputDir(['*(?<!.(d|android|ios)).ts'], processTypeScriptFile);
generateExportsForPrivateModules();
// Generate tests in
generateTestFile();
})().catch((e) => {
console.log('Error generating tns-core-modules files: ' + e);
});