@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
84 lines (83 loc) • 4.31 kB
TypeScript
/**
* Defines the {@link IPipelineStep} interface which specifies all data available for a single step.
* @module
*/
import type { MergeableRecord } from '../../util/objects';
import type { InternalStepPrinter, IPipelineStepPrinter, StepOutputFormat } from '../print/print';
import type { FlowrConfig } from '../../config';
/**
* This represents the format of a step processor which retrieves two things:
*
* 1) the input configuration as passed to the {@link PipelineExecutor}.
* 2) the output produced by the previous steps.
*
* Please be aware, that if the respective information is available is not ensured by the type system but rather
* ensured at runtime by your dependencies. If you want to make sure, that the information is present,
* list all steps that you require as your {@link IPipelineStepOrder#dependencies|dependencies}, even if they would be
* already covered transitively.
*/
export type StepProcessingFunction = (results: Record<string, unknown>, input: Record<string, unknown>, config: FlowrConfig) => unknown;
/**
* This represents the required execution frequency of a step.
*/
export declare const enum PipelineStepStage {
/** This step has to be executed once per file */
OncePerFile = 0,
/** This step has to be executed once per request (e.g., slice for a given variable) */
OncePerRequest = 1
}
/** Name of a single {@link IPipelineStep|step} in a pipeline (branded to avoid type-mishaps). */
export type PipelineStepName = string & {
__brand?: 'StepName';
};
/**
* Contains the data to specify the order of {@link IPipelineStep|steps} in a pipeline.
*/
export interface IPipelineStepOrder<Name extends PipelineStepName = PipelineStepName> {
/**
* Name of the respective step, it does not have to be unique in general but only unique per-pipeline.
* In other words, you can have multiple steps with a name like `parse` as long as you use only one of them in a given pipeline.
* This is, because these names are required in the {@link IPipelineStep#dependencies} field to refer to other steps this one relies on.
*/
readonly name: Name;
/**
* Give the names of other steps this one requires to be completed as a prerequisite (e.g., to gain access to their input).
* Does not have to be transitive, this will be checked by the scheduler of the pipeline.
*/
readonly dependencies: readonly PipelineStepName[];
readonly executed: PipelineStepStage;
/**
* This is similar to {@link dependencies}, but is used to say that a given step _decorates_ another one.
* This imbues two requirements:
* The step must take the output of the decorated step as input, and produce the same output as the decorated step.
*
* If so, it is ensured that _this_ step is executed _after_ the step it decorates, but before any step that depends on it.
*/
readonly decorates?: PipelineStepName;
}
/**
* Defines what is to be known of a single step in a pipeline.
* It wraps around a single {@link IPipelineStep#processor|processor} function, providing additional information.
* Steps will be executed synchronously, in-sequence, based on their {@link IPipelineStep#dependencies|dependencies}.
*/
export interface IPipelineStep<Name extends PipelineStepName = PipelineStepName, Fn extends StepProcessingFunction = (...args: any[]) => any> extends MergeableRecord, IPipelineStepOrder<Name> {
/** Human-readable name of this step */
readonly humanReadableName: string;
/** Human-readable description of this step */
readonly description: string;
/** The main processor that essentially performs the logic of this step */
readonly processor: (...input: Parameters<Fn>) => ReturnType<Fn>;
/** How to visualize the results of the respective step to the user? */
readonly printer: {
[K in StepOutputFormat]?: IPipelineStepPrinter<Fn, K, never[]>;
} & {
[StepOutputFormat.Internal]: InternalStepPrinter<Fn>;
};
/**
* Input configuration required to perform the respective steps.
* Required inputs of dependencies do not have to, but can be repeated.
* <p>
* Use the pattern `undefined as unknown as T` to indicate that the value is required but not provided.
*/
readonly requiredInput: object;
}