|
|
|
@ -108,8 +108,17 @@ export async function catchingPromise<T>(executor: (resolve: (value?: T | Promis
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 定义了一个类型,用于表示异步操作的回调函数。
|
|
|
|
|
export type toPromiseCallback<T> = (err?: Error | null | void, res?: T) => void;
|
|
|
|
|
/** Wrapper around async callback-based functions */
|
|
|
|
|
/**
|
|
|
|
|
* 将接受回调函数的函数转换为返回 Promise 的函数。
|
|
|
|
|
* @param func - 一个函数,它接受一个回调函数作为参数,并在完成时调用该回调函数。
|
|
|
|
|
* @returns 一个 Promise,它将解析为回调函数中提供的值。
|
|
|
|
|
* @description
|
|
|
|
|
* 这个函数用于将基于回调的异步操作转换为基于 Promise 的操作。
|
|
|
|
|
* 它通过捕获回调函数中的错误并将其转换为 Promise 的拒绝来实现这一点。
|
|
|
|
|
*/
|
|
|
|
|
export async function toPromise<T>(func: (cb: toPromiseCallback<T>) => void): Promise<T> {
|
|
|
|
|
return catchingPromise((resolve, reject) => {
|
|
|
|
|
func((err, res) => err ? reject(err) : resolve(res!));
|
|
|
|
@ -117,43 +126,112 @@ export async function toPromise<T>(func: (cb: toPromiseCallback<T>) => void): Pr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Converts the given number/string to a port number. Throws an error for invalid strings or ports outside the 1-65565 range */
|
|
|
|
|
/**
|
|
|
|
|
* 验证并返回一个有效的端口号
|
|
|
|
|
* @param port - 要验证的端口号,可以是字符串或数字
|
|
|
|
|
* @returns 一个有效的端口号,如果端口号无效则抛出错误
|
|
|
|
|
* @throws {Error} 如果端口号不是整数,则抛出错误
|
|
|
|
|
* @throws {Error} 如果端口号不在 1-65565 范围内,则抛出错误
|
|
|
|
|
*/
|
|
|
|
|
export function validatePort(port: string | number): number {
|
|
|
|
|
// 将端口号转换为数字
|
|
|
|
|
const p = Number(port);
|
|
|
|
|
// 如果转换后的结果不是整数,抛出错误
|
|
|
|
|
if (!Number.isInteger(p)) throw new Error(`Wanting to use non-int '${port}' as port`);
|
|
|
|
|
// 如果端口号小于 0 或大于 65565,抛出错误
|
|
|
|
|
if (p < 0 || p > 65565) throw new Error(`Wanting to use port ${p} outside the 1-65565 range`);
|
|
|
|
|
// 返回有效的端口号
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 定义一个正则表达式,用于匹配符合特定规则的字符串。
|
|
|
|
|
* 这个正则表达式用于验证 Bash 环境变量的值是否合法。
|
|
|
|
|
* 合法的值应该只包含字母、数字、下划线、连字符、斜杠和反斜杠。
|
|
|
|
|
*/
|
|
|
|
|
const CLEAN_BASH_VALUE_REGEX = /^[\w-/\\]+$/;
|
|
|
|
|
/** Based on way 1 in https://stackoverflow.com/a/20053121 */
|
|
|
|
|
/**
|
|
|
|
|
* 转义 Bash 字符串中的特殊字符
|
|
|
|
|
* @param value - 要转义的字符串
|
|
|
|
|
* @returns 转义后的字符串,如果字符串已经符合 CLEAN_BASH_VALUE_REGEX 则直接返回
|
|
|
|
|
* @throws {Error} 如果字符串包含 CLEAN_BASH_VALUE_REGEX 不允许的字符,则抛出错误
|
|
|
|
|
*/
|
|
|
|
|
export function escapeBashValue(value: string) {
|
|
|
|
|
// 如果值通过了 CLEAN_BASH_VALUE_REGEX 测试,则返回原始值
|
|
|
|
|
if (CLEAN_BASH_VALUE_REGEX.test(value)) return value;
|
|
|
|
|
// 否则,将值用单引号包围,并将所有单引号替换为 '\''
|
|
|
|
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Convert an {@link EnvironmentVariable} array to a `export var1=val; export var2='escaped$val'` etc */
|
|
|
|
|
/**
|
|
|
|
|
* 将环境变量数组转换为可导出的字符串格式
|
|
|
|
|
* @param env - 环境变量数组
|
|
|
|
|
* @param createSetEnv - 创建设置环境变量的字符串的函数
|
|
|
|
|
* @returns 一个字符串,其中包含了以分号分隔的设置环境变量的命令
|
|
|
|
|
* @description
|
|
|
|
|
* 这个函数用于将一组环境变量转换为可以在 Bash 或其他 shell 中导出的字符串格式。
|
|
|
|
|
* 它通过调用 `createSetEnv` 函数来为每个环境变量创建一个设置命令,并将这些命令连接起来。
|
|
|
|
|
*/
|
|
|
|
|
export function environmentToExportString(env: EnvironmentVariable[], createSetEnv: (key: string, value: string) => string): string {
|
|
|
|
|
// 使用 map 方法遍历环境变量数组,为每个环境变量创建一个设置命令
|
|
|
|
|
return env.map(({ key, value }) => createSetEnv(escapeBashValue(key), escapeBashValue(value))).join('; ');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Returns a new {@link EnvironmentVariable} array with all the given environments merged into it, overwriting same-key variables */
|
|
|
|
|
/**
|
|
|
|
|
* 合并多个环境变量数组或对象,返回一个新的环境变量数组
|
|
|
|
|
* @param environments - 一个或多个环境变量数组或对象
|
|
|
|
|
* @returns 一个新的环境变量数组,其中包含了所有传入的环境变量,相同键的值会被覆盖
|
|
|
|
|
* @description
|
|
|
|
|
* 这个函数用于合并多个环境变量数组或对象。它会遍历所有传入的参数,将它们转换为 `EnvironmentVariable` 对象,并存储在一个 `Map` 中。
|
|
|
|
|
* 如果传入的参数是一个数组,它会遍历数组中的每个元素,并将其添加到 `Map` 中。如果传入的参数是一个对象,它会遍历对象的所有键值对,并将它们添加到 `Map` 中。
|
|
|
|
|
* 最后,它会将 `Map` 转换为一个数组并返回。
|
|
|
|
|
*/
|
|
|
|
|
export function mergeEnvironment(...environments: (EnvironmentVariable[] | Record<string, string> | undefined)[]): EnvironmentVariable[] {
|
|
|
|
|
// 创建一个 Map 用于存储合并后的环境变量
|
|
|
|
|
const result = new Map<string, EnvironmentVariable>();
|
|
|
|
|
// 遍历所有传入的环境变量数组或对象
|
|
|
|
|
for (let other of environments) {
|
|
|
|
|
// 如果当前项为 undefined,则跳过
|
|
|
|
|
if (!other) continue;
|
|
|
|
|
// 如果当前项是一个数组
|
|
|
|
|
if (Array.isArray(other)) {
|
|
|
|
|
for (const variable of other) result.set(variable.key, variable);
|
|
|
|
|
} else {
|
|
|
|
|
// 遍历数组中的每个环境变量
|
|
|
|
|
for (const variable of other) {
|
|
|
|
|
// 将环境变量的键和值添加到结果 Map 中
|
|
|
|
|
result.set(variable.key, variable);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 如果当前项是一个对象
|
|
|
|
|
else {
|
|
|
|
|
// 遍历对象的所有键值对
|
|
|
|
|
for (const [key, value] of Object.entries(other)) {
|
|
|
|
|
// 将键值对转换为 EnvironmentVariable 对象并添加到结果 Map 中
|
|
|
|
|
result.set(key, { key, value });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 将结果 Map 转换为数组并返回
|
|
|
|
|
return [...result.values()];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Joins the commands together using the given separator. Automatically ignores `undefined` and empty strings */
|
|
|
|
|
/**
|
|
|
|
|
* 使用指定的分隔符连接命令字符串或字符串数组
|
|
|
|
|
* @param commands - 要连接的命令,可以是字符串或字符串数组
|
|
|
|
|
* @param separator - 用于连接命令的分隔符
|
|
|
|
|
* @returns 连接后的命令字符串,如果 commands 为 undefined,则返回 undefined
|
|
|
|
|
* @description
|
|
|
|
|
* 这个函数用于将一个或多个命令字符串连接成一个字符串,使用指定的分隔符分隔每个命令。
|
|
|
|
|
* 如果 commands 是一个字符串,它将直接返回这个字符串。
|
|
|
|
|
* 如果 commands 是一个数组,它将过滤掉数组中的空字符串和 undefined 值,然后使用指定的分隔符将这些字符串连接起来。
|
|
|
|
|
* 如果 commands 是 undefined,函数将返回 undefined。
|
|
|
|
|
*/
|
|
|
|
|
export function joinCommands(commands: string | string[] | undefined, separator: string): string | undefined {
|
|
|
|
|
// 如果 commands 是一个字符串,直接返回它
|
|
|
|
|
if (typeof commands === 'string') return commands;
|
|
|
|
|
// 如果 commands 是一个数组,使用分隔符连接其中的非空字符串
|
|
|
|
|
return commands?.filter(c => c?.trim()).join(separator);
|
|
|
|
|
}
|
|
|
|
|