202 lines
4.9 KiB
JavaScript
202 lines
4.9 KiB
JavaScript
// @ts-check
|
|
import {exec} from 'node:child_process';
|
|
import {accessSync} from 'node:fs';
|
|
import fs from 'node:fs/promises';
|
|
import https from 'node:https';
|
|
import path from 'node:path';
|
|
|
|
/** @type {{[color: string]: (text: string) => string}} */
|
|
const colors = Object.entries({
|
|
gray: '\x1b[90m',
|
|
green: '\x1b[32m',
|
|
red: '\x1b[31m',
|
|
yellow: '\x1b[33m',
|
|
}).reduce((map, [key, value]) => Object.assign(map, {[key]: (/** @type {string} */text) => `${value}${text}\x1b[0m`}), {});
|
|
|
|
/**
|
|
* @param {string} command
|
|
* @returns {Promise<string>}
|
|
*/
|
|
export async function execute(command) {
|
|
return new Promise((resolve, reject) => exec(command, (error, stdout) => {
|
|
if (error) {
|
|
reject(`Failed to execute command ${command}`);
|
|
} else {
|
|
resolve(stdout);
|
|
}
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* @param {string} text
|
|
* @returns
|
|
*/
|
|
export function logWithTime(text) {
|
|
const now = new Date();
|
|
const hours = now.getHours();
|
|
const minutes = now.getMinutes();
|
|
const seconds = now.getSeconds();
|
|
const leftpad = (/** @type {number} */n) => String(n).padStart(2, '0');
|
|
return console.log(`${colors.gray([hours, minutes, seconds].map(leftpad).join(':'))} ${text}`);
|
|
}
|
|
|
|
export const log = Object.assign((/** @type {string} */text) => logWithTime(text), {
|
|
ok: (/** @type {string} */text) => logWithTime(colors.green(text)),
|
|
warn: (/** @type {string} */text) => logWithTime(colors.yellow(text)),
|
|
error: (/** @type {string} */text) => logWithTime(colors.red(text)),
|
|
clearLine: () => {
|
|
process.stdout.moveCursor(0, -1);
|
|
process.stdout.clearLine(1);
|
|
},
|
|
});
|
|
|
|
/**
|
|
* @param {string} dest
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
export async function pathExists(dest) {
|
|
try {
|
|
await fs.access(dest);
|
|
return true;
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} dest
|
|
* @returns {boolean}
|
|
*/
|
|
export function pathExistsSync(dest) {
|
|
try {
|
|
accessSync(dest);
|
|
return true;
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} dir
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export async function removeFolder(dir) {
|
|
if (await pathExists(dir)) {
|
|
await fs.rm(dir, {recursive: true});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} dest
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export async function mkDirIfMissing(dest) {
|
|
const dir = path.dirname(dest);
|
|
if (!(await pathExists(dir))) {
|
|
await fs.mkdir(dir, {recursive: true});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} src
|
|
* @param {string} dest
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export async function copyFile(src, dest) {
|
|
await mkDirIfMissing(dest);
|
|
await fs.copyFile(src, dest);
|
|
}
|
|
|
|
/**
|
|
* @param {string} src
|
|
* @param {BufferEncoding} [encoding]
|
|
* @returns {Promise<string>}
|
|
*/
|
|
export async function readFile(src, encoding = 'utf8') {
|
|
return await fs.readFile(src, encoding);
|
|
}
|
|
|
|
/**
|
|
* @param {string} src
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
export async function fileExists(src) {
|
|
try {
|
|
await fs.access(src, fs.constants.R_OK);
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} dest
|
|
* @param {string} content
|
|
* @param {BufferEncoding | null | undefined} encoding
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export async function writeFile(dest, content, encoding = 'utf8') {
|
|
await mkDirIfMissing(dest);
|
|
await fs.writeFile(dest, content, encoding);
|
|
}
|
|
|
|
/**
|
|
* @param {string} path
|
|
* @returns {Promise<Object>}
|
|
*/
|
|
export async function readJSON(path) {
|
|
const file = await readFile(path);
|
|
return JSON.parse(file);
|
|
}
|
|
|
|
/**
|
|
* @param {string} dest
|
|
* @param {string} content
|
|
* @param {string | number | undefined} space
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export async function writeJSON(dest, content, space = 4) {
|
|
const string = JSON.stringify(content, null, space);
|
|
return await writeFile(dest, string);
|
|
}
|
|
|
|
/**
|
|
* @param {string | string[]} patterns
|
|
* @returns {Promise<string[]>}
|
|
*/
|
|
export async function getPaths(patterns) {
|
|
const {globby} = await import('globby');
|
|
return await globby(patterns);
|
|
}
|
|
|
|
/**
|
|
* @param {number} delay
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export function timeout(delay) {
|
|
return new Promise((resolve) => setTimeout(resolve, delay));
|
|
}
|
|
|
|
/**
|
|
* @param {string} url
|
|
* @returns {Promise<{buffer(): Buffer; text(encoding?: BufferEncoding): string; type(): string}>}
|
|
*/
|
|
export function httpsRequest(url) {
|
|
return new Promise((resolve) => {
|
|
/** @type {Uint8Array[]} */
|
|
const data = [];
|
|
https.get(url, (response) => {
|
|
response
|
|
.on('data', (chunk) => data.push(chunk))
|
|
.on('end', () => {
|
|
const buffer = Buffer.concat(data);
|
|
resolve({
|
|
buffer: () => buffer,
|
|
text: (encoding = 'utf8') => buffer.toString(encoding),
|
|
type: () => response.headers['content-type'] || '',
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|