-
-
Notifications
You must be signed in to change notification settings - Fork 75
/
scripts.ts
106 lines (84 loc) 路 2.74 KB
/
scripts.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import type { Logger } from "../core.ts";
export interface Options {
/** The logger to use */
logger: Logger;
/** The default cwd for scripts */
options: ScriptOptions;
}
/**
* Script runner to store and run commands or execute functions
* It can execute the scripts and functions in parallel or sequentially
*/
export default class Scripts {
/** The logger to output messages in the terminal */
logger: Logger;
/** The default options to execute the scripts */
options: ScriptOptions;
/** All registered scripts and functions */
scripts = new Map<string, ScriptOrFunction[]>();
constructor(options: Options) {
this.logger = options.logger;
this.options = options.options;
}
/** Register one or more scripts under a specific name */
set(name: string, ...scripts: ScriptOrFunction[]): void {
this.scripts.set(name, scripts);
}
/** Run one or more commands */
async run(
options: ScriptOptions,
...names: ScriptOrFunction[]
): Promise<boolean> {
options = { ...this.options, ...options };
for (const name of names) {
const success = await this.#run(options, name);
if (!success) {
return false;
}
}
return true;
}
/** Run an individual script or function */
async #run(options: ScriptOptions, name: ScriptOrFunction): Promise<unknown> {
if (typeof name === "string" && this.scripts.has(name)) {
this.logger.log(`鈿★笍 <green>${name}</green>`);
const command = this.scripts.get(name)!;
return this.run(options, ...command);
}
if (Array.isArray(name)) {
const results = await Promise.all(
name.map((n) => this.#run(options, n)),
);
return results.every((success) => success);
}
if (typeof name === "function") {
return this.#runFunction(name);
}
return this.#runScript(options, name);
}
/** Run a function */
async #runFunction(fn: () => unknown) {
this.logger.log(`鈿★笍 <dim>${fn.name}()</dim>`);
const result = await fn();
return result !== false;
}
/** Run a shell command */
async #runScript(options: ScriptOptions, script: string) {
this.logger.log(`鈿★笍 <dim>${script}</dim>`);
const cmd = shArgs(script);
const process = Deno.run({ cmd, ...options });
const status = await process.status();
process.close();
return status.success;
}
}
/** Returns the shell arguments for the current platform */
function shArgs(script: string) {
return Deno.build.os === "windows"
? ["PowerShell.exe", "-Command", script]
: ["/bin/bash", "-c", script];
}
/** A script or function */
export type ScriptOrFunction = string | (() => unknown) | ScriptOrFunction[];
/** The options for a script */
export type ScriptOptions = Omit<Deno.RunOptions, "cmd">;