cloudscript-server
Version:
A local environment for cloudscript development
129 lines (104 loc) • 4.39 kB
JavaScript
const fs = require('fs');
const { spawnSync } = require('child_process');
const path = require('path');
const crypto = require('crypto');
const compilerUtils = require('./src/compilers/compilerUtils');
function clearCache() {
if (!fs.existsSync(path.join(__dirname, 'typings-cache')))
return;
fs.rmSync(path.join(__dirname, 'typings-cache'), { recursive: true });
fs.mkdirSync(path.join(__dirname, 'typings-cache'), { recursive: true });
}
function hashDirectory(directory) {
return crypto.createHash('md5').update(directory).digest('hex');
}
function loadCache(directory) {
const hash = hashDirectory(directory);
const mapsDir = path.join(__dirname, 'typings-cache');
fs.mkdirSync(mapsDir, { recursive: true });
const cachePath = path.join(mapsDir, `${hash}.typings.json`);
if (!fs.existsSync(cachePath)) {
return { cache: {}, path: cachePath };
}
const cache = JSON.parse(fs.readFileSync(cachePath, 'utf8'));
return { cache, path: cachePath };
}
function saveCache(cache, cachePath) {
fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2));
}
function generateTypings(directory) {
console.log('🔠 Generating typings...'.blue);
const startTime = Date.now();
let files = compilerUtils.getFiles(directory, `\nnode_modules\ntypings\n`, '.dtsignore');
files = files.filter(file => file.includes('.js'));
const { cache, path: cachePath } = loadCache(directory);
const filesToProcess = [];
for (let file of files) {
const relativePath = path.relative(directory, file).replace(/\\/g, '/');
const stats = fs.statSync(file);
const mtime = stats.mtimeMs;
if (!cache[relativePath] || cache[relativePath] !== mtime) {
filesToProcess.push(file);
cache[relativePath] = mtime;
}
}
if (filesToProcess.length === 0) {
console.log('All typings up to date'.blue);
} else {
console.log(`Generating typings for ${filesToProcess.length} changed files...`.yellow);
generateTypingsBatch(filesToProcess, directory);
}
saveCache(cache, cachePath);
// Now update the index.d.ts file (still always generated)
try {
let addedTypings = files.map(file => {
let absolutePath = path.relative(directory, file);
let ext = path.extname(absolutePath);
absolutePath = absolutePath.substring(0, absolutePath.length - ext.length);
let typingPath = path.join('scripts', absolutePath + '.d.ts');
typingPath = typingPath.replace(/\\/g, '/');
return `/// <reference path="${typingPath}" />`;
});
fs.writeFileSync(path.join(directory, 'typings/autogenerated/index.d.ts'), addedTypings.join('\n'));
} catch (e) {
console.error(e);
}
console.log(`✔️ Typings generated in ${Date.now() - startTime}ms`.blue);
}
function generateTypingsBatch(files, mainDir) {
try {
if (files.length === 0) {
console.log('No files to generate typings');
return;
}
const typingsDir = path.join(mainDir, 'typings', 'autogenerated', 'scripts');
fs.mkdirSync(typingsDir, { recursive: true });
const tempTsconfigPath = path.join(__dirname, 'tsconfig.typings.json');
const tsconfig = {
compilerOptions: {
declaration: true,
emitDeclarationOnly: true,
allowJs: true,
noResolve: true,
outDir: typingsDir,
target: "ESNext",
module: "ESNext",
strict: false
},
files: files
};
fs.writeFileSync(tempTsconfigPath, JSON.stringify(tsconfig, null, 2));
console.log('Running tsc...'.dim);
const result = spawnSync(process.execPath, [
path.join(__dirname, 'node_modules/typescript/lib/tsc.js'),
'-p',
tempTsconfigPath
], { encoding: 'utf-8' });
// console.log(result.stdout);
// console.error(result.stderr);
fs.unlinkSync(tempTsconfigPath);
} catch (e) {
console.error(e);
}
}
module.exports = { generateTypings, clearCache };