How to add dynamic dependencies in the acquire phase of a bracket when using fp-ts?

37 views Asked by At

I was wondering if there is a way to add elements to the context / resource that will only be present in the use part of a bracket. What I'm trying to do is to create a transaction for the things I execute in use and release the tx in release. This is a simplified example of what I'm trying to achieve:

type TxContext = {
    tx: string;
}

type MyDeps = {
    getMyData: () => RTE.ReaderTaskEither<
        TxContext,
        Error,
        string
    >;
};

const executeOperation = () =>
    bracketW(
        pipe(
            Do,
            bindW("deps", () => ask<MyDeps>()),
            // start transaction would be here
            bindW("tx", () => right("this is a transaction")),
            map(({ deps, tx }) => ({
                ...deps,
                tx,
            }))
        ),
        ({ getMyData, tx }) => {
            // no way to pass the tx to the operation here
            return pipe(
                getMyData(),
                map((data) => `got the data: ${data}`),
            );
        },
        (d, e: E.Either<Error, string>) =>
            // close transaction would be here
            pipe(fromEither(e), map(constVoid))
    );

My problem is that this will add the tx as a mandatory parameter to R in the ReaderTaskEither. Is there a way to prevent this? I want to create the tx within the bracket as part of the acquire step.

I tried another solution:

const executeOperation = () =>
    bracketW(
        pipe(
            Do,
            bindW("deps", () => ask<MyDeps>()),
            bindW("tx", () => right("this is a transaction")),
            map(({ deps, tx }) => ({
                ...deps,
                tx,
            }))
        ),
        (deps) => {
            const { getMyData, tx } = deps;
            // pass the deps and re-wrap into a new ReaderTaskEither
            return fromTaskEither(
                pipe(
                    getMyData(),
                    map((data) => `got the data: ${data}`)
                )({ tx })
            );
        },
        (d, e: E.Either<Error, string>) =>
            pipe(fromEither(e), map(constVoid))
    );

but it feels hacky to me. Does fp-ts have an out-of-the-box solution for this?

0

There are 0 answers