2022-10-03 17:52:28 +08:00
|
|
|
import { execSync } from 'child_process';
|
|
|
|
import { createWriteStream } from 'fs';
|
2022-10-07 19:48:17 +08:00
|
|
|
import path from 'path';
|
2022-10-03 17:52:28 +08:00
|
|
|
|
|
|
|
import chalk from 'chalk';
|
|
|
|
import got, { Progress } from 'got';
|
2022-10-03 19:00:44 +08:00
|
|
|
import { HttpsProxyAgent } from 'hpagent';
|
2022-10-07 00:31:35 +08:00
|
|
|
import { customAlphabet } from 'nanoid';
|
2022-10-03 17:52:28 +08:00
|
|
|
import ora from 'ora';
|
|
|
|
|
|
|
|
export const safeExecSync = (command: string) => {
|
|
|
|
try {
|
|
|
|
return execSync(command, { encoding: 'utf8', stdio: 'pipe' });
|
|
|
|
} catch {}
|
|
|
|
};
|
|
|
|
|
|
|
|
type Log = Readonly<{
|
|
|
|
info: typeof console.log;
|
|
|
|
warn: typeof console.log;
|
2022-10-05 22:46:52 +08:00
|
|
|
error: (...args: Parameters<typeof console.log>) => never;
|
2022-10-03 17:52:28 +08:00
|
|
|
}>;
|
|
|
|
|
|
|
|
export const log: Log = Object.freeze({
|
|
|
|
info: (...args) => {
|
|
|
|
console.log(chalk.blue('[info]'), ...args);
|
|
|
|
},
|
|
|
|
warn: (...args) => {
|
|
|
|
console.log(chalk.yellow('[warn]'), ...args);
|
|
|
|
},
|
|
|
|
error: (...args) => {
|
|
|
|
console.log(chalk.red('[error]'), ...args);
|
|
|
|
// eslint-disable-next-line unicorn/no-process-exit
|
|
|
|
process.exit(1);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
export const downloadFile = async (url: string, destination: string) => {
|
2022-10-03 19:00:44 +08:00
|
|
|
const { HTTPS_PROXY, HTTP_PROXY, https_proxy, http_proxy } = process.env;
|
2022-10-03 17:52:28 +08:00
|
|
|
const file = createWriteStream(destination);
|
2022-10-03 19:00:44 +08:00
|
|
|
const proxy = HTTPS_PROXY ?? https_proxy ?? HTTP_PROXY ?? http_proxy;
|
|
|
|
const stream = got.stream(url, {
|
|
|
|
...(proxy && { agent: { https: new HttpsProxyAgent({ proxy }) } }),
|
|
|
|
});
|
2022-10-03 17:52:28 +08:00
|
|
|
const spinner = ora({
|
|
|
|
text: 'Connecting',
|
|
|
|
prefixText: chalk.blue('[info]'),
|
|
|
|
}).start();
|
|
|
|
|
|
|
|
stream.pipe(file);
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
stream.on('downloadProgress', ({ total, percent }: Progress) => {
|
|
|
|
if (!total) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// eslint-disable-next-line @silverhand/fp/no-mutation
|
|
|
|
spinner.text = `${(percent * 100).toFixed(1)}%`;
|
|
|
|
});
|
|
|
|
|
|
|
|
file.on('error', (error) => {
|
|
|
|
spinner.fail();
|
|
|
|
reject(error.message);
|
|
|
|
});
|
|
|
|
|
|
|
|
file.on('finish', () => {
|
|
|
|
file.close();
|
|
|
|
spinner.succeed();
|
|
|
|
resolve(file);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2022-10-05 02:30:37 +08:00
|
|
|
|
2022-10-07 19:48:17 +08:00
|
|
|
export const getPathInModule = (moduleName: string, relativePath = '/') =>
|
|
|
|
// https://stackoverflow.com/a/49455609/12514940
|
|
|
|
path.join(
|
|
|
|
// Until we migrate to ESM
|
|
|
|
// eslint-disable-next-line unicorn/prefer-module
|
|
|
|
path.dirname(require.resolve(`${moduleName}/package.json`)),
|
|
|
|
relativePath
|
|
|
|
);
|
|
|
|
|
2022-10-07 00:31:35 +08:00
|
|
|
// TODO: Move to `@silverhand/essentials`
|
2022-10-05 02:30:37 +08:00
|
|
|
// Intended
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
|
|
export const noop = () => {};
|
2022-10-05 22:46:52 +08:00
|
|
|
|
|
|
|
export const deduplicate = <T>(array: T[]) => [...new Set(array)];
|
2022-10-07 00:31:35 +08:00
|
|
|
|
|
|
|
export const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
|
|
|
|
|
|
export const buildIdGenerator = (size: number) => customAlphabet(alphabet, size);
|
|
|
|
|
|
|
|
export const buildApplicationSecret = buildIdGenerator(21);
|