rescribet/link-lib

View on GitHub
src/createStore.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import { LinkedDataAPI } from "./LinkedDataAPI";
import { LinkedRenderStore } from "./LinkedRenderStore";
import { linkMiddleware } from "./linkMiddleware";
import { DataProcessor } from "./processor/DataProcessor";
import {
    LinkedRenderStoreOptions,
    MiddlewareActionHandler,
    MiddlewareFn,
    SomeNode,
} from "./types";

function applyMiddleware<T, API extends LinkedDataAPI = DataProcessor>(
  lrs: LinkedRenderStore<T, API>,
  ...layers: Array<MiddlewareFn<T, API>>
): MiddlewareActionHandler {
    const storeBound = layers.map((middleware) => middleware(lrs));

    const finish: MiddlewareActionHandler = (a: SomeNode, _o: any): Promise<any> => Promise.resolve(a);

    return storeBound.reduceRight((composed, f) => {
        const next = f(composed);
        if (!next) {
            throw new Error("Provided middleware did not return handler.");
        }
        return next;
    }, finish);
}

/**
 * Initializes a {LinkedRenderStore} with tied together middleware.
 * @param storeOpts Constructor arguments for the LRS.
 * @param middleware Main middleware, to be executed before the {linkMiddleware}.
 * @param trailingMiddleware Middleware to be placed after the {linkMiddleware}. Note: defining trailing middleware
 *  causes actions not to be executed via {LinkedRenderStore#execActionByIRI} anymore, this behaviour can be enabled
 *  manually in one of the defined middlewares if still desired.
 */
export function createStore<T, API extends LinkedDataAPI = DataProcessor>(
  storeOpts: LinkedRenderStoreOptions<T, API> = {},
  middleware: Array<MiddlewareFn<any, API>> = [],
  trailingMiddleware: Array<MiddlewareFn<any, API>> = [],
): LinkedRenderStore<T, API> {
    const LRS = new LinkedRenderStore<T, API>(storeOpts);

    LRS.dispatch = applyMiddleware<T, API>(
        LRS,
        ...middleware,
        linkMiddleware(trailingMiddleware.length === 0),
        ...trailingMiddleware,
    );

    return LRS;
}