You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailchat/server/scripts/build.ts

149 lines
3.6 KiB
TypeScript

import ts from 'typescript';
import fs from 'fs-extra';
import ora from 'ora';
import { glob } from 'glob';
import path from 'path';
import execa from 'execa';
async function buildTailchatServer() {
const spinner = ora({
prefixText: 'Tailchat Server',
});
try {
spinner.start('Start compiling');
await fs.remove('./dist');
spinner.info('Compiling TS code');
await compileTsCode();
spinner.info('Moving static resource files');
await Promise.all([
fs.copy('./public', './dist/public', { recursive: true }),
fs.copy('./locales', './dist/locales', { recursive: true }),
fs.copy('./views', './dist/views', { recursive: true }),
fs.copy(
'./services/openapi/oidc/views',
'./dist/services/openapi/oidc/views',
{ recursive: true }
),
]);
if (process.platform !== 'win32' || (await isAdmin())) {
spinner.info('Building plugin dependent symlink');
const nodeModulesList = await glob('./plugins/*/node_modules/*');
for (const item of nodeModulesList) {
const src = path.resolve(__dirname, '../', item);
const dest = path.resolve(__dirname, '../dist', item);
spinner.text = `Building Symlink: ${src} -> ${dest}`;
await fs.createSymlink(src, dest, 'dir');
}
} else {
spinner.warn(
'You are run command in windows without admin permit, create symlink will be skip'
);
}
spinner.succeed('Compiled!');
} catch (e) {
console.error(e);
spinner.fail('Compilation failed!');
}
}
buildTailchatServer();
/**
* 编译Ts代码
*
* tsc的api实现
*/
function compileTsCode(): Promise<void> {
function compile(
fileNames: string[],
options: ts.CompilerOptions
): Promise<void> {
return new Promise<void>((resolve, reject) => {
const program = ts.createProgram(fileNames, options);
const emitResult = program.emit();
const allDiagnostics = ts
.getPreEmitDiagnostics(program)
.concat(emitResult.diagnostics);
allDiagnostics.forEach((diagnostic) => {
if (diagnostic.file) {
const { line, character } = ts.getLineAndCharacterOfPosition(
diagnostic.file,
diagnostic.start!
);
const message = ts.flattenDiagnosticMessageText(
diagnostic.messageText,
'\n'
);
console.log(
`${diagnostic.file.fileName} (${line + 1},${
character + 1
}): ${message}`
);
} else {
console.log(
ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')
);
}
});
const exitCode = emitResult.emitSkipped ? 1 : 0;
if (exitCode === 0) {
resolve();
} else {
reject();
}
});
}
const configPath = ts.findConfigFile(
process.cwd() /*searchPath*/,
ts.sys.fileExists,
'tsconfig.json'
);
const configFile = ts.readJsonConfigFile(configPath, ts.sys.readFile);
const { fileNames, options } = ts.parseJsonSourceFileConfigFileContent(
configFile,
ts.sys,
process.cwd()
);
return compile(fileNames, options);
}
/**
* check is window admin
*/
async function isAdmin() {
if (process.platform !== 'win32') {
return false;
}
try {
// https://stackoverflow.com/a/21295806/1641422
await execa('fsutil', ['dirty', 'query', process.env.systemdrive]);
return true;
} catch (error) {
if (error.code === 'ENOENT') {
return testFltmc();
}
return false;
}
}
async function testFltmc() {
try {
await execa('fltmc');
return true;
} catch {
return false;
}
}