@plugjs/plug
Version:
PlugJS Build System ===================
95 lines (94 loc) • 4.41 kB
TypeScript
import type { Files } from './files';
import type { Pipe } from './index';
import type { AbsolutePath } from './paths';
/**
* A type describing the ultimate result of a {@link Plug}, {@link Pipe} or
* {@link Task}, that is either a {@link Files} instance or `undefined`.
*/
export type Result = Files | undefined;
/**
* The {@link State} interface defines a component tracking the current
* _state_ of a build, caching the result of {@link Task}s, and tracking their
* invocation stack to avoid infinite loops.
*/
export interface State {
/** The cache of the result of {@link Task}s execution */
readonly cache: Map<Task, Promise<Result>>;
/** The current {@link Task} invocation stack (to avoid infinite loops) */
readonly stack: Task[];
/** All {@link Tasks} available in this {@link State} */
readonly tasks: Tasks;
/** All _properties_ available in this {@link State} */
readonly props: Props;
/** All _tasks_ that have failed in this {@link State} */
readonly fails: Set<Task>;
}
/**
* The {@link Task} interface normalizes a task definition, associating it with
* its build file, its sibling {@link Task}s and available _properties_.
*/
export interface Task<T extends Result = Result> {
/** The unique ID of this {@link Task} */
readonly id: number;
/** The _original_ name of this task */
readonly name: string;
/** All _properties_ siblings to this {@link Task} */
readonly props: Props;
/** All {@link Tasks} sibling to this {@link Task} */
readonly tasks: Tasks;
/** The absolute file name where this {@link Task} was defined */
readonly buildFile: AbsolutePath;
/** Other {@link Task}s hooked _before_ this one */
readonly before: Task[];
/** Other {@link Task}s hooked _after_ this one */
readonly after: Task[];
/** Invoke a task from in the context of a {@link Build} */
invoke(state: State, taskName: string): Promise<T>;
}
/**
* The {@link TaskResult} type identifies _what_ can be returned by a
* {@link TaskDef | _task definition_}.
*/
export type TaskResult = Pipe | Files | void | undefined;
/** The {@link TaskDef} type identifies the _definition_ of a task. */
export type TaskDef<R extends TaskResult = TaskResult> = () => R | Promise<R>;
/** A callable, compiled {@link Task} from a {@link TaskDef} */
export type TaskCall<D extends BuildDef = BuildDef, R extends Result = Result> = {
(props?: Partial<Props<D>>): Promise<R>;
task: Task<R>;
};
/** A type identifying all _properties_ of a {@link Build}. */
export type Props<D extends BuildDef = BuildDef> = {
readonly [k in string & keyof D as D[k] extends string ? k : never]: string;
};
/** A type identifying all _tasks_ in a {@link Build} */
export type Tasks<D extends BuildDef = BuildDef> = {
readonly [k in string & keyof D as D[k] extends TaskDef | TaskCall ? k : never]: D[k] extends TaskDef<infer R> ? R extends void | undefined ? TaskCall<D, undefined> : R extends Pipe | Files ? TaskCall<D, Files> : never : D[k] extends TaskCall ? D[k] : never;
};
/**
* The {@link BuildDef} interface describes the _definition_ of a {@link Build},
* all its properties and tasks.
*/
export interface BuildDef {
[k: string]: string | TaskDef | TaskCall;
}
/**
* The type that will be used for `this` when invoking
* {@link TaskDef | task definitions }.
*/
export type ThisBuild<D extends BuildDef> = {
readonly [k in keyof D as k extends string ? k : never]: D[k] extends TaskDef<infer R> ? R extends Promise<undefined> | void | undefined ? () => Promise<undefined> : R extends Pipe | Files ? () => Pipe : never : D[k] extends TaskCall<any, infer R> ? R extends undefined ? () => Promise<undefined> : R extends Files ? () => Pipe : never : D[k] extends string ? string : never;
};
/**
* The {@link Build} type represents the collection of {@link Task}s
* and _properties_ compiled from a {@link BuildDef | build definition}.
*/
export type Build<D extends BuildDef = BuildDef> = Props<D> & Tasks<D>;
/** A type identifying all _task names_ in a {@link Build}. */
export type BuildTasks<B extends Build> = string & keyof {
[name in keyof B as B[name] extends (() => any) ? name : never]: any;
};
/** A type identifying a subset of _properties_ for a {@link Build}. */
export type BuildProps<B extends Build> = {
[name in keyof B as B[name] extends string ? name : never]?: string;
};