UNPKG

2.01 kBPlain TextView Raw
1import execa, { Options as ExecaOptions } from 'execa';
2import { Arguments, ParserOptions } from '@boost/args';
3import { Blueprint, Predicates } from '@boost/common';
4import { ConcurrentEvent } from '@boost/event';
5import { Plugin } from '@boost/plugin';
6import { ScriptContext } from './contexts/ScriptContext';
7import { isClassInstance } from './helpers/isClassInstance';
8import { Argv, BeemoTool, Scriptable } from './types';
9
10export abstract class Script<O extends object = {}, Options extends object = {}>
11 extends Plugin<BeemoTool, Options>
12 implements Scriptable<O>
13{
14 // Set within a life-cycle
15 tool!: BeemoTool;
16
17 readonly onBeforeExecute = new ConcurrentEvent<[ScriptContext, Argv]>('before-execute');
18
19 readonly onAfterExecute = new ConcurrentEvent<[ScriptContext, unknown]>('after-execute');
20
21 readonly onFailedExecute = new ConcurrentEvent<[ScriptContext, Error]>('failed-execute');
22
23 static validate(script: Script) {
24 const name = (isClassInstance(script) && script.constructor.name) || 'Script';
25
26 if (typeof script.parse !== 'function') {
27 throw new TypeError(`\`${name}\` requires a \`parse()\` method.`);
28 }
29
30 if (typeof script.execute !== 'function') {
31 throw new TypeError(`\`${name}\` requires an \`execute()\` method.`);
32 }
33 }
34
35 blueprint(preds: Predicates): Blueprint<object> {
36 return {};
37 }
38
39 bootstrap() {}
40
41 override startup(tool: BeemoTool) {
42 this.tool = tool;
43 this.bootstrap();
44 }
45
46 /**
47 * Define a configuration object to parse args with.
48 */
49 parse(): ParserOptions<O> {
50 return {
51 // @ts-expect-error Allow this
52 options: {},
53 };
54 }
55
56 /**
57 * Execute a command with the given arguments and pass the results through a promise.
58 */
59 async executeCommand(command: string, args: string[], options: ExecaOptions = {}) /* infer */ {
60 return execa(command, args, {
61 preferLocal: true,
62 ...options,
63 });
64 }
65
66 /**
67 * Execute the script with the context and parsed args.
68 */
69 abstract execute(context: ScriptContext, args: Arguments<O>): Promise<unknown>;
70}