lib/transform/transformer.ts (69 lines of code) (raw):
import { array as topoSort } from "toposort";
import { SwaggerSpec } from "../swagger/swaggerTypes";
import { TransformContext } from "./context";
export enum TransformerType {
Spec = "spec",
Global = "global",
}
interface TransformerBase<T> {
type: TransformerType;
before?: T[];
after?: T[];
}
export interface SpecTransformer extends TransformerBase<SpecTransformer> {
type: TransformerType.Spec;
transform: (spec: SwaggerSpec, ctx: TransformContext) => void;
}
export interface GlobalTransformer extends TransformerBase<GlobalTransformer> {
type: TransformerType.Global;
transform: (ctx: TransformContext) => void;
}
export type Transformer = SpecTransformer | GlobalTransformer;
export const sortTransformers = (transformers: Transformer[]) => {
const specTransformers = new Set<SpecTransformer>();
const globalTransformers = new Set<GlobalTransformer>();
for (const t of transformers) {
switch (t.type) {
case TransformerType.Spec:
specTransformers.add(t);
break;
case TransformerType.Global:
globalTransformers.add(t);
break;
}
}
const sortTrans = <T extends TransformerBase<T>>(ts: Set<T>): T[] => {
const edges: Array<[T, T]> = [];
for (const t of ts) {
if (t.after !== undefined) {
for (const tAfter of t.after) {
if (ts.has(tAfter)) {
edges.push([tAfter, t]);
}
}
}
if (t.before !== undefined) {
for (const tBefore of t.before) {
if (ts.has(tBefore)) {
edges.push([t, tBefore]);
}
}
}
}
return topoSort([...ts], edges);
};
return {
specTransformers: sortTrans(specTransformers),
globalTransformers: sortTrans(globalTransformers),
};
};
export const applySpecTransformers = (spec: SwaggerSpec, ctx: TransformContext) => {
for (const t of ctx.specTransformers) {
t.transform(spec, ctx);
}
};
export const applyGlobalTransformers = (ctx: TransformContext) => {
for (const t of ctx.globalTransformers) {
t.transform(ctx);
}
};