import * as Chunk from "@effect/data/Chunk" import type * as Context from "@effect/data/Context" import * as Debug from "@effect/data/Debug" import * as Duration from "@effect/data/Duration" import * as Either from "@effect/data/Either" import * as Equal from "@effect/data/Equal" import type { LazyArg } from "@effect/data/Function" import { identity, pipe } from "@effect/data/Function" import * as Hash from "@effect/data/Hash" import * as HashSet from "@effect/data/HashSet" import * as Option from "@effect/data/Option" import * as ReadonlyArray from "@effect/data/ReadonlyArray" import * as Cause from "@effect/io/Cause" import * as Clock from "@effect/io/Clock" import * as Effect from "@effect/io/Effect" import * as Exit from "@effect/io/Exit" import * as Fiber from "@effect/io/Fiber" import * as FiberRef from "@effect/io/FiberRef" import * as Layer from "@effect/io/Layer" import * as Ref from "@effect/io/Ref" import * as Cache from "@effect/query/Cache" import type * as DataSource from "@effect/query/DataSource" import type * as Described from "@effect/query/Described" import * as BlockedRequest from "@effect/query/internal_effect_untraced/blockedRequest" import * as BlockedRequests from "@effect/query/internal_effect_untraced/blockedRequests" import * as cache from "@effect/query/internal_effect_untraced/cache" import * as completedRequestMap from "@effect/query/internal_effect_untraced/completedRequestMap" import * as Continue from "@effect/query/internal_effect_untraced/continue" import * as dataSource from "@effect/query/internal_effect_untraced/dataSource" import * as described from "@effect/query/internal_effect_untraced/described" import * as queryFailure from "@effect/query/internal_effect_untraced/queryFailure" import * as Result from "@effect/query/internal_effect_untraced/result" import * as Sequential from "@effect/query/internal_effect_untraced/sequential" import type * as Query from "@effect/query/Query" import type * as Request from "@effect/query/Request" /** @internal */ const QuerySymbolKey = "@effect/query/Query" /** @internal */ export const QueryTypeId: Query.QueryTypeId = Symbol.for( QuerySymbolKey ) as Query.QueryTypeId /** @internal */ export const isQuery = (u: unknown): u is Query.Query => typeof u === "object" && u !== null && QueryTypeId in u /** @internal */ const queryVariance = { _R: (_: never) => _, _E: (_: never) => _, _A: (_: never) => _ } /** @internal */ class QueryImpl implements Query.Query { readonly _tag = "Commit" get [QueryTypeId]() { return queryVariance } public trace = undefined constructor( readonly i0: Effect.Effect>, readonly i1: any = undefined, readonly i2: any = undefined ) {} [Equal.symbol](that: unknown) { return this === that } [Hash.symbol]() { return Hash.random(this) } readonly [Effect.EffectTypeId] = queryVariance traced(trace: Debug.Trace): Query.Query { if (trace) { return new QueryImpl(matchCauseQuery(this, failCause, succeed).i0.traced(trace)) } return this } commit() { return run(this) } } const cachingEnabled: FiberRef.FiberRef = FiberRef.unsafeMake(true) const currentCache: FiberRef.FiberRef = FiberRef.unsafeMake(cache.unsafeMake()) /** @internal */ export const absolve = Debug.untracedMethod(() => (self: Query.Query>): Query.Query => flatMap(self, fromEither) ) /** @internal */ export const around = Debug.untracedDual< ( before: Described.Described>, after: Described.Described<(a: A2) => Effect.Effect> ) => (self: Query.Query) => Query.Query, ( self: Query.Query, before: Described.Described>, after: Described.Described<(a: A2) => Effect.Effect> ) => Query.Query >(3, () => (self, before, after) => mapDataSources(self, (source) => dataSource.around(source, before, after))) /** @internal */ export const as = Debug.untracedDual< (value: A2) => (self: Query.Query) => Query.Query, (self: Query.Query, value: A2) => Query.Query >(2, () => (self, value) => map(self, () => value)) /** @internal */ export const asSomeError = Debug.untracedMethod(() => (self: Query.Query): Query.Query, A> => mapError(self, Option.some) ) /** @internal */ export const asUnit = Debug.untracedMethod(() => (self: Query.Query): Query.Query => as(self, void 0) ) /** @internal */ export const cached = Debug.untracedMethod(() => (self: Query.Query): Query.Query => pipe( fromEffect(FiberRef.getAndSet(cachingEnabled, true)), flatMap((previous) => ensuring(self, fromEffect(FiberRef.set(cachingEnabled, previous)))) ) ) /** @internal */ export const catchAll = Debug.untracedDual< ( f: (error: E) => Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, f: (error: E) => Query.Query ) => Query.Query >(2, (restore) => (self, f) => matchQuery(self, restore(f), succeed)) /** @internal */ export const catchAllCause = Debug.untracedDual< ( f: (cause: Cause.Cause) => Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, f: (cause: Cause.Cause) => Query.Query ) => Query.Query >(2, (restore) => (self, f) => matchCauseQuery(self, restore(f), succeed)) /** @internal */ export const collectAll = Debug.untracedMethod(() => (queries: Iterable>): Query.Query> => forEach(queries, identity) ) /** @internal */ export const collectAllBatched = Debug.untracedMethod(() => (queries: Iterable>): Query.Query> => forEachBatched(queries, identity) ) /** @internal */ export const collectAllPar = Debug.untracedMethod(() => (queries: Iterable>): Query.Query> => forEachPar(queries, identity) ) /** @internal */ export const context = Debug.methodWithTrace((trace) => (_: void): Query.Query> => fromEffect(Effect.context().traced(trace)) ) /** @internal */ export const contextWith = Debug.untracedMethod((restore) => (f: (context: Context.Context) => A): Query.Query => map(context(), restore(f)) ) /** @internal */ export const contextWithEffect = Debug.untracedMethod((restore) => (f: (context: Context.Context) => Effect.Effect): Query.Query => mapEffect(context(), restore(f)) ) /** @internal */ export const contextWithQuery = Debug.untracedMethod((restore) => (f: (context: Context.Context) => Query.Query): Query.Query => flatMap(context(), restore(f)) ) /** @internal */ export const contramapContext = Debug.dualWithTrace< ( f: Described.Described<(context: Context.Context) => Context.Context> ) => (self: Query.Query) => Query.Query, ( self: Query.Query, f: Described.Described<(context: Context.Context) => Context.Context> ) => Query.Query >( 2, (trace, restore) => ( self: Query.Query, f: Described.Described<(context: Context.Context) => Context.Context> ) => new QueryImpl( Effect.contramapContext( Effect.map(self.i0, (result) => contramapContextResult(result, f)), (context: Context.Context) => restore(f.value)(context) ).traced(trace) ) ) /** @internal */ export const die = Debug.methodWithTrace((trace) => (defect: unknown): Query.Query => new QueryImpl(Effect.die(defect).traced(trace)) ) /** @internal */ export const dieSync = Debug.methodWithTrace((trace, restore) => (evaluate: LazyArg): Query.Query => new QueryImpl(Effect.dieSync(restore(evaluate)).traced(trace)) ) /** @internal */ export const either = Debug.untracedMethod(() => (self: Query.Query): Query.Query> => catchAll(map(self, Either.right), (e) => succeed(Either.left(e))) ) /** @internal */ export const ensuring = Debug.untracedDual< ( finalizer: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, finalizer: Query.Query ) => Query.Query >(2, () => (self, finalizer) => matchCauseQuery(self, (cause1) => matchCauseQuery( finalizer, (cause2) => failCause(Cause.sequential(cause1, cause2)), () => failCause(cause1) ), (value) => matchCauseQuery(finalizer, failCause, () => succeed(value)))) /** @internal */ export const fail = Debug.methodWithTrace((trace) => (error: E): Query.Query => new QueryImpl(Effect.succeed(Result.fail(Cause.fail(error))).traced(trace), "Fail", error) ) /** @internal */ export const failSync = Debug.methodWithTrace((trace, restore) => (evaluate: LazyArg): Query.Query => new QueryImpl(Effect.sync(() => Result.fail(Cause.fail(restore(evaluate)()))).traced(trace)) ) /** @internal */ export const failCause = Debug.methodWithTrace((trace) => (cause: Cause.Cause): Query.Query => new QueryImpl(Effect.succeed(Result.fail(cause)).traced(trace)) ) /** @internal */ export const failCauseSync = Debug.methodWithTrace((trace, restore) => (evaluate: LazyArg>): Query.Query => new QueryImpl(Effect.sync(() => Result.fail(restore(evaluate)())).traced(trace)) ) /** @internal */ export const flatMap = Debug.dualWithTrace< ( f: (a: A) => Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, f: (a: A) => Query.Query ) => Query.Query >(2, (trace, restore) => (self, f) => new QueryImpl( Effect.flatMap(self.i0, (result) => { switch (result._tag) { case "Blocked": { return Effect.succeed( Result.blocked( result.blockedRequests, mapQueryContinuation(result.continue, restore(f)) ) ) } case "Done": { return restore(f)(result.value).i0 } case "Fail": { return Effect.succeed(Result.fail(result.cause)) } } }).traced(trace) )) /** @internal */ export const flatten = Debug.untracedMethod(() => ( self: Query.Query> ): Query.Query => flatMap(self, identity) ) /** @internal */ export const forEach = Debug.untracedDual< ( f: (a: A) => Query.Query ) => ( elements: Iterable ) => Query.Query>, ( elements: Iterable, f: (a: A) => Query.Query ) => Query.Query> >(2, (restore) => (elements: Iterable, f: (a: A) => Query.Query) => { const iterator = restore(() => elements[Symbol.iterator]())() let result: Query.Query> | undefined let next: IteratorResult while ((next = iterator.next()) && !next.done) { if (result === undefined) { result = map(restore(f)(next.value), Chunk.of) } else { result = zipWith( result, restore(f)(next.value), (chunk, a) => pipe(chunk, Chunk.append(a)) ) } } return result !== undefined ? result : succeed(Chunk.empty()) }) /** @internal */ export const forEachBatched = Debug.untracedDual< ( f: (a: A) => Query.Query ) => ( elements: Iterable ) => Query.Query>, ( elements: Iterable, f: (a: A) => Query.Query ) => Query.Query> >(2, (restore) => (elements: Iterable, f: (a: A) => Query.Query) => { const iterator = restore(() => elements[Symbol.iterator]())() let result: Query.Query> | undefined let next: IteratorResult while ((next = iterator.next()) && !next.done) { if (result === undefined) { result = map(restore(f)(next.value), Chunk.of) } else { result = zipWithBatched( result, restore(f)(next.value), (chunk, a) => pipe(chunk, Chunk.append(a)) ) } } return result !== undefined ? result : succeed(Chunk.empty()) }) /** @internal */ export const forEachPar = Debug.untracedDual< ( f: (a: A) => Query.Query ) => ( elements: Iterable ) => Query.Query>, ( elements: Iterable, f: (a: A) => Query.Query ) => Query.Query> >(2, (restore) => (elements, f) => suspend(() => { const chunk = Chunk.fromIterable(elements) if (Chunk.isEmpty(chunk)) { return succeed(Chunk.empty()) } if (Chunk.size(chunk) === 1) { return map(restore(f)(pipe(chunk, Chunk.unsafeGet(0))), Chunk.of) } return new QueryImpl( Effect.map( Effect.forEachPar(chunk, (a) => restore(f)(a).i0), collectAllParResult ) ) })) /** @internal */ export const fromEffect = Debug.methodWithTrace((trace) => (effect: Effect.Effect): Query.Query => new QueryImpl(Effect.matchCause(effect, Result.fail, Result.done).traced(trace)) ) /** @internal */ export const fromEither = Debug.untracedMethod((): (either: Either.Either) => Query.Query => Either.match(fail, succeed) ) /** @internal */ export const fromOption = Debug.untracedMethod((): ( option: Option.Option ) => Query.Query, A> => Option.match(() => fail(Option.none()), succeed)) /** @internal */ export const fromRequest = Debug.methodWithTrace((trace) => , A2 extends A>( request: A, dataSource: DataSource.DataSource ): Query.Query, Request.Request.Success> => new QueryImpl( Effect.flatMap(FiberRef.get(cachingEnabled), (cachingEnabled) => cachingEnabled ? Effect.flatMap(FiberRef.get(currentCache), (currentCache) => Effect.flatMap( cache.lookup(currentCache, request), Either.match( (ref) => Effect.succeed( Result.blocked( BlockedRequests.single(dataSource, BlockedRequest.make(request, ref)), Continue.make(request, dataSource, ref) ) ), (ref) => Effect.map( Ref.get(ref), Option.match( () => Result.blocked( BlockedRequests.empty, Continue.make(request, dataSource, ref) ), Result.fromEither ) ) ) )) : Effect.map( Ref.make(Option.none, Request.Request.Success>>()), (ref) => Result.blocked( BlockedRequests.single(dataSource, BlockedRequest.make(request, ref)), Continue.make(request, dataSource, ref) ) )).traced(trace) ) ) /** @internal */ export const fromRequestUncached = Debug.untracedMethod(() => , A2 extends A>(request: A, dataSource: DataSource.DataSource) => uncached(fromRequest(request, dataSource)) ) /** @internal */ export const left = Debug.untracedMethod(() => ( self: Query.Query> ): Query.Query, A> => matchQuery( self, (e) => fail(Either.left(e)), Either.match(succeed, (a2) => fail(Either.right(a2))) ) ) /** @internal */ export const map = Debug.dualWithTrace< (f: (a: A) => B) => (self: Query.Query) => Query.Query, (self: Query.Query, f: (a: A) => B) => Query.Query >(2, (trace, restore) => (self, f) => new QueryImpl( Effect.map( self.i0, (result) => mapResult(result, restore(f)) ).traced(trace) )) /** @internal */ export const mapBoth = Debug.untracedDual< (f: (e: E) => E2, g: (a: A) => A2) => (self: Query.Query) => Query.Query, (self: Query.Query, f: (e: E) => E2, g: (a: A) => A2) => Query.Query >(3, (restore) => (self, f, g) => matchQuery( self, (e) => fail(restore(f)(e)), (a) => succeed(restore(g)(a)) )) /** @internal */ export const mapDataSources = Debug.dualWithTrace< ( f: (dataSource: DataSource.DataSource) => DataSource.DataSource ) => (self: Query.Query) => Query.Query, ( self: Query.Query, f: (dataSource: DataSource.DataSource) => DataSource.DataSource ) => Query.Query >(2, (trace, restore) => (self, f) => new QueryImpl( Effect.map( self.i0, (result) => mapDataSourcesResult(result, restore(f)) ).traced(trace) )) /** @internal */ export const mapError = Debug.untracedDual< (f: (e: E) => E2) => (self: Query.Query) => Query.Query, (self: Query.Query, f: (e: E) => E2) => Query.Query >(2, (restore) => (self, f) => mapBoth(self, restore(f), identity)) /** @internal */ export const mapErrorCause = Debug.untracedDual< (f: (cause: Cause.Cause) => Cause.Cause) => (self: Query.Query) => Query.Query, (self: Query.Query, f: (cause: Cause.Cause) => Cause.Cause) => Query.Query >(2, (restore) => (self, f) => matchCauseQuery(self, (cause) => failCause(restore(f)(cause)), succeed)) /** @internal */ export const mapEffect = Debug.untracedDual< ( f: (a: A) => Effect.Effect ) => (self: Query.Query) => Query.Query, ( self: Query.Query, f: (a: A) => Effect.Effect ) => Query.Query >(2, (restore) => (self, f) => flatMap(self, (a) => fromEffect(restore(f)(a)))) /** @internal */ export const match = Debug.untracedDual< ( onFailure: (error: E) => Z, onSuccess: (value: A) => Z ) => (self: Query.Query) => Query.Query, ( self: Query.Query, onFailure: (error: E) => Z, onSuccess: (value: A) => Z ) => Query.Query >(3, (restore) => (self, onFailure, onSuccess) => matchQuery( self, (e) => succeed(restore(onFailure)(e)), (a) => succeed(restore(onSuccess)(a)) )) /** @internal */ export const matchCauseQuery = Debug.dualWithTrace< ( onFailure: (cause: Cause.Cause) => Query.Query, onSuccess: (value: A) => Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, onFailure: (cause: Cause.Cause) => Query.Query, onSuccess: (value: A) => Query.Query ) => Query.Query >(3, (trace, restore) => ( self: Query.Query, onFailure: (cause: Cause.Cause) => Query.Query, onSuccess: (value: A) => Query.Query ) => new QueryImpl( Effect.matchCauseEffect( self.i0, (cause) => restore(onFailure)(cause).i0, (result): Effect.Effect< R | R2 | R3, never, Result.Result > => { switch (result._tag) { case "Blocked": { return Effect.succeed( Result.blocked( result.blockedRequests, matchCauseQueryContination(result.continue, restore(onFailure), restore(onSuccess)) ) ) } case "Done": { return restore(onSuccess)(result.value).i0 } case "Fail": { return restore(onFailure)(result.cause).i0 } } } ).traced(trace) )) /** @internal */ export const matchQuery = Debug.untracedDual< ( onFailure: (error: E) => Query.Query, onSuccess: (value: A) => Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, onFailure: (error: E) => Query.Query, onSuccess: (value: A) => Query.Query ) => Query.Query >(3, (restore) => (self, onFailure, onSuccess) => matchCauseQuery(self, (cause) => pipe( Cause.failureOrCause(cause), Either.match(restore(onFailure), (a) => failCause(a)) ), restore(onSuccess))) /** @internal */ export const maxBatchSize = Debug.untracedDual< (n: number) => (self: Query.Query) => Query.Query, (self: Query.Query, n: number) => Query.Query >(2, () => (self, n) => mapDataSources(self, (source) => dataSource.batchN(source, n))) /** @internal */ export const never = Debug.untracedMethod(() => (_: void): Query.Query => fromEffect(Effect.never()) ) /** @internal */ export const optional = Debug.untracedMethod(() => (self: Query.Query): Query.Query> => matchCauseQuery(self, (cause) => pipe( Cause.stripSomeDefects(cause, (defect) => queryFailure.isQueryFailure(defect) ? Option.some(void 0) : Option.none()), Option.match(succeedNone, failCause) ), succeedSome) ) /** @internal */ export const orDie = Debug.untracedMethod(() => (self: Query.Query): Query.Query => orDieWith(self, identity) ) /** @internal */ export const orDieWith = Debug.untracedDual< (f: (error: E) => unknown) => (self: Query.Query) => Query.Query, (self: Query.Query, f: (error: E) => unknown) => Query.Query >(2, (restore) => (self, f) => matchQuery(self, (e) => die(restore(f)(e)), succeed)) /** @internal */ export const partitionQuery = Debug.untracedDual< ( f: (a: A) => Query.Query ) => ( elements: Iterable ) => Query.Query, Chunk.Chunk]>, ( elements: Iterable, f: (a: A) => Query.Query ) => Query.Query, Chunk.Chunk]> >(2, (restore) => (elements, f) => map( forEach(elements, (a) => either(restore(f)(a))), partitionMap(identity) )) /** @internal */ export const partitionQueryPar = Debug.untracedDual< ( f: (a: A) => Query.Query ) => ( elements: Iterable ) => Query.Query, Chunk.Chunk]>, ( elements: Iterable, f: (a: A) => Query.Query ) => Query.Query, Chunk.Chunk]> >(2, (restore) => (elements, f) => map( forEachPar(elements, (a) => either(restore(f)(a))), partitionMap(identity) )) /** @internal */ export const provideContext = Debug.untracedDual< ( context: Described.Described> ) => ( self: Query.Query ) => Query.Query, ( self: Query.Query, context: Described.Described> ) => Query.Query >(2, () => (self, context) => contramapContext(self, described.make(() => context.value, context.description))) /** @internal */ export const provideLayer = Debug.dualWithTrace< ( layer: Described.Described> ) => (self: Query.Query) => Query.Query, ( self: Query.Query, layer: Described.Described> ) => Query.Query >(2, (trace) => ( self: Query.Query, layer: Described.Described> ) => new QueryImpl( Effect.scoped( pipe( Effect.exit(Layer.build(layer.value)), Effect.flatMap(Exit.match( (e): Effect.Effect> => Effect.succeed(Result.fail(e)), (c) => provideContext(self, described.make(c, layer.description)).i0 )) ) ).traced(trace) )) /** @internal */ export const provideSomeLayer = Debug.untracedDual< ( layer: Described.Described> ) => (self: Query.Query) => Query.Query, E2 | E, A>, ( self: Query.Query, layer: Described.Described> ) => Query.Query, E | E2, A> >( 2, () => (self: Query.Query, layer: Described.Described>) => provideLayer( // @ts-expect-error self, described.make(Layer.merge(Layer.context(), layer.value), layer.description) ) ) /** @internal */ export const race = Debug.dualWithTrace< ( that: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, (trace) => (self: Query.Query, that: Query.Query) => { const coordinate = ( exit: Exit.Exit>, fiber: Fiber.Fiber> ): Effect.Effect> => Exit.matchEffect( exit, (cause1) => Effect.map( Fiber.join(fiber), (result) => mapErrorCauseResult(result, (cause2) => Cause.parallel(cause1, cause2)) ), (result) => { switch (result._tag) { case "Blocked": { switch (result.continue._tag) { case "Eff": { return Effect.succeed( Result.blocked( result.blockedRequests, Continue.eff(raceInternal(result.continue.query, fiber)) ) ) } case "Get": { return Effect.succeed( Result.blocked( result.blockedRequests, Continue.eff(raceInternal(fromEffect(result.continue.effect), fiber)) ) ) } } } case "Done": { return Effect.zipRight( Fiber.interrupt(fiber), Effect.succeed(Result.done(result.value)) ) } case "Fail": { return Effect.map( Fiber.join(fiber), (result2) => mapErrorCauseResult(result2, (cause2) => Cause.parallel(result.cause, cause2)) ) } } } ) const raceInternal = ( query: Query.Query, fiber: Fiber.Fiber> ): Query.Query => new QueryImpl(Effect.raceWith(query.i0, Fiber.join(fiber), coordinate, coordinate)) return new QueryImpl(Effect.raceWith(self.i0, that.i0, coordinate, coordinate).traced(trace)) }) /** @internal */ export const refineOrDie = Debug.untracedDual< (pf: (error: E) => Option.Option) => (self: Query.Query) => Query.Query, (self: Query.Query, pf: (error: E) => Option.Option) => Query.Query >(2, (restore) => (self, pf) => refineOrDieWith(self, restore(pf), identity)) /** @internal */ export const refineOrDieWith = Debug.untracedDual< ( pf: (error: E) => Option.Option, f: (error: E) => unknown ) => (self: Query.Query) => Query.Query, ( self: Query.Query, pf: (error: E) => Option.Option, f: (error: E) => unknown ) => Query.Query >(3, (restore) => (self, pf, f) => catchAll( self, (e) => pipe(restore(pf)(e), Option.match(() => die(restore(f)(e)), fail)) )) /** @internal */ export const right = Debug.untracedMethod(() => ( self: Query.Query> ): Query.Query, A2> => matchQuery( self, (e) => fail(Either.right(e)), (e) => pipe(e, Either.match((a) => fail(Either.left(a)), succeed)) ) ) /** @internal */ export const run = Debug.methodWithTrace((trace) => (self: Query.Query): Effect.Effect => Effect.map(runLog(self), (tuple) => tuple[1]).traced(trace) ) /** @internal */ export const runCache = Debug.dualWithTrace< (cache: Cache.Cache) => (self: Query.Query) => Effect.Effect, (self: Query.Query, cache: Cache.Cache) => Effect.Effect >(2, (trace) => (self: Query.Query, cache: Cache.Cache) => { const runInternal = (query: Query.Query): Effect.Effect => Effect.flatMap(query.i0, (result) => { switch (result._tag) { case "Blocked": { switch (result.continue._tag) { case "Eff": { return Effect.zipRight( runBlockedRequests(result.blockedRequests), runInternal(result.continue.query) ) } case "Get": { return Effect.zipRight( runBlockedRequests(result.blockedRequests), result.continue.effect ) } } } case "Done": { return Effect.succeed(result.value) } case "Fail": { return Effect.failCause(result.cause) } } }) return FiberRef.locally(runInternal(self), currentCache, cache).traced(trace) }) /** @internal */ export const runLog = Debug.methodWithTrace((trace) => (self: Query.Query): Effect.Effect => Effect.flatMap(cache.empty(), (cache) => Effect.map( runCache(self, cache), (a) => [cache, a] as const )).traced(trace) ) /** @internal */ export const sandbox = Debug.untracedMethod(() => (self: Query.Query): Query.Query, A> => matchCauseQuery(self, fail, succeed) ) /** @internal */ export const sandboxWith = Debug.untracedDual< ( f: (self: Query.Query, A>) => Query.Query, A2> ) => (self: Query.Query) => Query.Query, ( self: Query.Query, f: (self: Query.Query, A>) => Query.Query, A2> ) => Query.Query >(2, (restore) => (self, f) => unsandbox(restore(f)(sandbox(self)))) /** @internal */ export const some = Debug.untracedMethod(() => (self: Query.Query>): Query.Query, A> => matchQuery( self, (e) => fail(Option.some(e)), Option.match(() => fail(Option.none()), succeed) ) ) /** @internal */ export const someOrElse = Debug.untracedDual< (def: LazyArg) => (self: Query.Query>) => Query.Query, (self: Query.Query>, def: LazyArg) => Query.Query >(2, (restore) => (self, def) => map(self, Option.getOrElse(restore(def)))) /** @internal */ export const someOrElseEffect = Debug.untracedDual< ( def: LazyArg> ) => (self: Query.Query>) => Query.Query, ( self: Query.Query>, def: LazyArg> ) => Query.Query >( 2, (restore) => (self: Query.Query>, def: LazyArg>) => flatMap(self, Option.match(restore(def), (a) => succeed(a))) ) /** @internal */ export const someOrFail = Debug.untracedDual< (error: LazyArg) => (self: Query.Query>) => Query.Query, (self: Query.Query>, error: LazyArg) => Query.Query >(2, (restore) => (self, error) => flatMap(self, Option.match(() => failSync(restore(error)), succeed))) /** @internal */ export const succeed = Debug.methodWithTrace((trace) => (value: A): Query.Query => new QueryImpl(Effect.succeed(Result.done(value)).traced(trace), "Succeed", value) ) /** @internal */ export const succeedNone = Debug.untracedMethod(() => (_: void): Query.Query> => succeed(Option.none()) ) /** @internal */ export const succeedSome = Debug.untracedMethod(() => (value: A): Query.Query> => succeed(Option.some(value)) ) /** @internal */ export const summarized = Debug.untracedDual< ( summary: Effect.Effect, f: (start: B, end: B) => C ) => (self: Query.Query) => Query.Query, ( self: Query.Query, summary: Effect.Effect, f: (start: B, end: B) => C ) => Query.Query >(3, (restore) => (self, summary, f) => flatMap( fromEffect(summary), (start) => flatMap( self, (value) => map( fromEffect(summary), (end) => [restore(f)(start, end), value] as const ) ) )) /** @internal */ export const suspend = Debug.untracedMethod((restore) => (evaluate: LazyArg>): Query.Query => flatMap(unit(), restore(evaluate)) ) /** @internal */ export const sync = Debug.methodWithTrace((trace, restore) => (evaluate: LazyArg): Query.Query => new QueryImpl(Effect.sync(() => Result.done(restore(evaluate)())).traced(trace)) ) /** @internal */ export const timed = Debug.untracedMethod(() => (self: Query.Query): Query.Query => summarized(self, Clock.currentTimeMillis(), (start, end) => Duration.millis(end - start)) ) /** @internal */ export const timeout = Debug.untracedDual< (duration: Duration.Duration) => (self: Query.Query) => Query.Query>, (self: Query.Query, duration: Duration.Duration) => Query.Query> >(2, () => (self, duration) => timeoutTo(self, Option.none(), Option.some, duration)) /** @internal */ export const timeoutFail = Debug.untracedDual< ( error: LazyArg, duration: Duration.Duration ) => ( self: Query.Query ) => Query.Query, ( self: Query.Query, error: LazyArg, duration: Duration.Duration ) => Query.Query >(3, (restore) => (self, error, duration) => flatten(timeoutTo( self, failSync(restore(error)), succeed, duration ))) /** @internal */ export const timeoutFailCause = Debug.untracedDual< ( evaluate: LazyArg>, duration: Duration.Duration ) => (self: Query.Query) => Query.Query, ( self: Query.Query, evaluate: LazyArg>, duration: Duration.Duration ) => Query.Query >(3, (restore) => (self, evaluate, duration) => flatten(timeoutTo( self, failCauseSync(restore(evaluate)), succeed, duration ))) /** @internal */ export const timeoutTo = Debug.untracedDual< ( def: B2, f: (a: A) => B, duration: Duration.Duration ) => (self: Query.Query) => Query.Query, ( self: Query.Query, def: B2, f: (a: A) => B, duration: Duration.Duration ) => Query.Query >(4, (restore) => ( self: Query.Query, def: B2, f: (a: A) => B, duration: Duration.Duration ) => { const race = (query: Query.Query, fiber: Fiber.Fiber): Query.Query => new QueryImpl( Effect.raceWith( query.i0, Fiber.join(fiber), (leftExit, rightFiber) => Exit.matchEffect( leftExit, (cause) => Effect.zipRight( Fiber.interrupt(rightFiber), Effect.succeed(Result.fail(cause)) ), (result) => { switch (result._tag) { case "Blocked": { switch (result.continue._tag) { case "Eff": { return Effect.succeed( Result.blocked( result.blockedRequests, Continue.eff(race(result.continue.query, fiber)) ) ) } case "Get": { return Effect.succeed( Result.blocked( result.blockedRequests, Continue.eff(race(fromEffect(result.continue.effect), fiber)) ) ) } } } case "Done": { return Effect.zipRight( Fiber.interrupt(rightFiber), Effect.succeed(Result.done(result.value)) ) } case "Fail": { return Effect.zipRight( Fiber.interrupt(rightFiber), Effect.succeed(Result.fail(result.cause)) ) } } } ), (rightExit, leftFiber) => Effect.zipRight( Fiber.interrupt(leftFiber), Effect.succeed(Result.fromExit(rightExit)) ) ) ) return flatMap( fromEffect(pipe( Effect.sleep(duration), Effect.interruptible, Effect.as(def), Effect.fork )), (fiber) => race(map(self, restore(f)), fiber) ) }) /** @internal */ export const uncached = Debug.untracedMethod(() => (self: Query.Query): Query.Query => pipe( fromEffect(FiberRef.getAndSet(cachingEnabled, false)), flatMap((previous) => ensuring(self, fromEffect(FiberRef.set(cachingEnabled, previous)))) ) ) /** @internal */ export const unit = Debug.untracedMethod(() => (_: void): Query.Query => succeed(void 0)) /** @internal */ export const unleft = Debug.untracedMethod(() => ( self: Query.Query, A> ): Query.Query> => matchQuery( self, Either.match( fail, (a) => succeed(Either.right(a)) ), (a) => succeed(Either.left(a)) ) ) /** @internal */ export const unoption = Debug.untracedMethod(() => (self: Query.Query, A>): Query.Query> => matchQuery( self, Option.match( () => succeed(Option.none()), fail ), (a) => succeed(Option.some(a)) ) ) /** @internal */ export const unrefine = Debug.untracedDual< ( pf: (defect: unknown) => Option.Option ) => (self: Query.Query) => Query.Query, (self: Query.Query, pf: (defect: unknown) => Option.Option) => Query.Query >(2, (restore) => (self, pf) => unrefineWith(self, restore(pf), identity)) /** @internal */ export const unrefineWith = Debug.untracedDual< ( pf: (defect: unknown) => Option.Option, f: (error: E) => E3 ) => (self: Query.Query) => Query.Query, ( self: Query.Query, pf: (defect: unknown) => Option.Option, f: (error: E) => E3 ) => Query.Query >(3, (restore) => ( self: Query.Query, pf: (defect: unknown) => Option.Option, f: (error: E) => E3 ) => catchAllCause(self, (cause) => pipe( Cause.find(cause, (cause) => Cause.isDieType(cause) ? restore(pf)(cause.defect) : Option.none()), Option.match( (): Query.Query => failCause(Cause.map(cause, restore(f))), fail ) ))) /** @internal */ export const unright = Debug.untracedMethod(() => ( self: Query.Query, A> ): Query.Query> => matchQuery( self, Either.match( (a) => succeed(Either.left(a)), fail ), (a) => succeed(Either.right(a)) ) ) /** @internal */ export const unsandbox = Debug.untracedMethod(() => (self: Query.Query, A>): Query.Query => mapErrorCause(self, Cause.flatten) ) /** @internal */ export const unwrap = Debug.untracedMethod(() => (effect: Effect.Effect>): Query.Query => flatten(fromEffect(effect)) ) /** @internal */ export const zip = Debug.untracedDual< ( that: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWith(self, that, (a, b) => [a, b] as const)) /** @internal */ export const zipBatched = Debug.untracedDual< ( that: Query.Query ) => ( self: Query.Query ) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWithBatched(self, that, (a, b) => [a, b] as const)) /** @internal */ export const zipBatchedLeft = Debug.untracedDual< ( that: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWithBatched(self, that, (a, _) => a)) /** @internal */ export const zipBatchedRight = Debug.untracedDual< ( that: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWithBatched(self, that, (_, b) => b)) /** @internal */ export const zipLeft = Debug.untracedDual< ( that: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWith(self, that, (a, _) => a)) /** @internal */ export const zipRight = Debug.untracedDual< ( that: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWith(self, that, (_, a2) => a2)) /** @internal */ export const zipPar = Debug.untracedDual< ( that: Query.Query ) => ( self: Query.Query ) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWithPar(self, that, (a, b) => [a, b] as const)) /** @internal */ export const zipParLeft = Debug.untracedDual< ( that: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWithPar(self, that, (a, _) => a)) /** @internal */ export const zipParRight = Debug.untracedDual< ( that: Query.Query ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query ) => Query.Query >(2, () => (self, that) => zipWithPar(self, that, (_, a2) => a2)) /** @internal */ export const zipWith: { ( that: Query.Query, f: (a: A, b: B) => C ): (self: Query.Query) => Query.Query ( self: Query.Query, that: Query.Query, f: (a: A, b: B) => C ): Query.Query } = Debug.dualWithTrace< ( that: Query.Query, f: (a: A, b: B) => C ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query, f: (a: A, b: B) => C ) => Query.Query >(3, (trace, restore) => (self, that, f) => new QueryImpl( Effect.flatMap(self.i0, (result) => { switch (result._tag) { case "Blocked": { switch (result.continue._tag) { case "Eff": { return Effect.succeed( Result.blocked( result.blockedRequests, Continue.eff(zipWith(result.continue.query, that, restore(f))) ) ) } case "Get": { return Effect.map(that.i0, (thatResult) => { switch (thatResult._tag) { case "Blocked": { return Result.blocked( BlockedRequests.seq(result.blockedRequests, thatResult.blockedRequests), zipWithContinuation(result.continue, thatResult.continue, restore(f)) ) } case "Done": { return Result.blocked( result.blockedRequests, mapContinuation(result.continue, (a) => restore(f)(a, thatResult.value)) ) } case "Fail": { return Result.fail(thatResult.cause) } } }) } } } case "Done": { return Effect.map(that.i0, (thatResult) => { switch (thatResult._tag) { case "Blocked": { return Result.blocked( thatResult.blockedRequests, mapContinuation(thatResult.continue, (b) => restore(f)(result.value, b)) ) } case "Done": { return Result.done(restore(f)(result.value, thatResult.value)) } case "Fail": { return Result.fail(thatResult.cause) } } }) } case "Fail": { return Effect.succeed(Result.fail(result.cause)) } } }).traced(trace) )) /** @internal */ export const zipWithBatched = Debug.untracedDual< ( that: Query.Query, f: (a: A, b: B) => C ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query, f: (a: A, b: B) => C ) => Query.Query >(3, (restore) => (self, that, f) => new QueryImpl(Effect.zipWith( self.i0, that.i0, (selfResult, thatResult) => { if (Result.isBlocked(selfResult) && Result.isBlocked(thatResult)) { return Result.blocked( BlockedRequests.par(selfResult.blockedRequests, thatResult.blockedRequests), zipWithBatchedContinuation(selfResult.continue, thatResult.continue, restore(f)) ) } if (Result.isBlocked(selfResult) && Result.isDone(thatResult)) { return Result.blocked( selfResult.blockedRequests, mapContinuation(selfResult.continue, (a) => restore(f)(a, thatResult.value)) ) } if (Result.isDone(selfResult) && Result.isBlocked(thatResult)) { return Result.blocked( thatResult.blockedRequests, mapContinuation(thatResult.continue, (b) => restore(f)(selfResult.value, b)) ) } if (Result.isDone(selfResult) && Result.isDone(thatResult)) { return Result.done(restore(f)(selfResult.value, thatResult.value)) } if (Result.isFail(selfResult) && Result.isFail(thatResult)) { return Result.fail(Cause.parallel(selfResult.cause, thatResult.cause)) } if (Result.isFail(selfResult)) { return Result.fail(selfResult.cause) } if (Result.isFail(thatResult)) { return Result.fail(thatResult.cause) } throw new Error( "BUG: BlockedRequests.reduce - please report an issue at https://github.com/Effect-TS/query/issues" ) } ))) /** @internal */ export const zipWithPar = Debug.untracedDual< ( that: Query.Query, f: (a: A, b: B) => C ) => (self: Query.Query) => Query.Query, ( self: Query.Query, that: Query.Query, f: (a: A, b: B) => C ) => Query.Query >(3, (restore) => (self, that, f) => new QueryImpl(Effect.zipWithPar( self.i0, that.i0, (selfResult, thatResult) => { if (Result.isBlocked(selfResult) && Result.isBlocked(thatResult)) { return Result.blocked( BlockedRequests.par(selfResult.blockedRequests, thatResult.blockedRequests), zipWithParContinuation(selfResult.continue, thatResult.continue, restore(f)) ) } if (Result.isBlocked(selfResult) && Result.isDone(thatResult)) { return Result.blocked( selfResult.blockedRequests, mapContinuation(selfResult.continue, (a) => restore(f)(a, thatResult.value)) ) } if (Result.isDone(selfResult) && Result.isBlocked(thatResult)) { return Result.blocked( thatResult.blockedRequests, mapContinuation(thatResult.continue, (b) => restore(f)(selfResult.value, b)) ) } if (Result.isDone(selfResult) && Result.isDone(thatResult)) { return Result.done(restore(f)(selfResult.value, thatResult.value)) } if (Result.isFail(selfResult) && Result.isFail(thatResult)) { return Result.fail(Cause.parallel(selfResult.cause, thatResult.cause)) } if (Result.isFail(selfResult)) { return Result.fail(selfResult.cause) } if (Result.isFail(thatResult)) { return Result.fail(thatResult.cause) } throw new Error( "BUG: BlockedRequests.reduce - please report an issue at https://github.com/Effect-TS/query/issues" ) } ))) // Circular with BlockedRequests /** * Executes all requests, submitting requests to each data source in parallel. */ const runBlockedRequests = (self: BlockedRequests.BlockedRequests) => { return Effect.flatMap( FiberRef.get(currentCache), (currentCache) => Effect.forEachDiscard( BlockedRequests.flatten(self), (requestsByDataSource) => Effect.forEachParDiscard(Sequential.toChunk(requestsByDataSource), ([dataSource, sequential]) => Effect.flatMap( dataSource.runAll(Chunk.map(sequential, (blockedRequests) => Chunk.map(blockedRequests, (blockedRequest) => blockedRequest.request))), (completedRequests) => { const blockedRequests: Chunk.Chunk> = Chunk.flatten(sequential) const leftovers = pipe( completedRequestMap.requests(completedRequests), HashSet.difference(Chunk.map(blockedRequests, (blockedRequest) => blockedRequest.request as Request.Request)) ) return pipe( Effect.forEachDiscard(blockedRequests, (blockedRequest) => Ref.set( blockedRequest.result, completedRequestMap.get(completedRequests, blockedRequest.request) )), Effect.zipRight( Effect.forEachDiscard(leftovers, (request) => Effect.flatMap( Ref.make(completedRequestMap.get(completedRequests, request)), (ref) => Cache.set(currentCache, request, ref) )) ) ) } )) ) ) } /** * Partitions the elements of a collection using the specified function. */ const partitionMap = (f: (a: A) => Either.Either) => (self: Chunk.Chunk): readonly [Chunk.Chunk, Chunk.Chunk] => { const bs: Array = [] const cs: Array = [] for (let i = 0; i < self.length; i++) { const a = pipe(self, Chunk.unsafeGet(i)) const e = f(a) if (Either.isLeft(e)) { bs.push(e.left) } else { cs.push(e.right) } } return [Chunk.unsafeFromArray(bs), Chunk.unsafeFromArray(cs)] } // Circular with Continue /** * Collects a collection of continuation into a continuation returning a * collection of their results, in parallel. */ const collectAllParContinuation = ( elements: Iterable> ): Continue.Continue> => { const queries: Array, number]> = [] const effects: Array, number]> = [] const iterator = elements[Symbol.iterator]() let index = 0 let next: IteratorResult, any> while ((next = iterator.next()) && !next.done) { const element = next.value switch (element._tag) { case "Eff": { queries.push([element.query, index]) break } case "Get": { effects.push([element.effect, index]) break } } index += 1 } if (ReadonlyArray.isEmptyReadonlyArray(queries)) { return Continue.get(Effect.collectAll(effects.map((tuple) => tuple[0]))) } const query = flatMap( collectAllPar(queries.map((tuple) => tuple[0])), (chunk) => { const array = new Array(chunk.length) const indices = queries.map((tuple) => tuple[1]) for (let i = 0; i < chunk.length; i++) { array[indices[i]] = pipe(chunk, Chunk.unsafeGet(i)) } return map( fromEffect(Effect.collectAll(effects.map((tuple) => tuple[0]))), (chunk) => { for (let i = 0; i < chunk.length; i++) { array[effects[i][1]] = pipe(chunk, Chunk.unsafeGet(i)) } return Chunk.fromIterable(array) } ) } ) return Continue.eff(query) } /** * Purely contramaps over the environment type of this continuation. */ const contramapContextContinuation = ( self: Continue.Continue, f: Described.Described<(context: Context.Context) => Context.Context> ): Continue.Continue => { switch (self._tag) { case "Eff": { return Continue.eff(contramapContext(self.query, f)) } case "Get": { return self } } } /** * Purely maps over the success type of this continuation. */ const mapContinuation = (self: Continue.Continue, f: (a: A) => B): Continue.Continue => { switch (self._tag) { case "Eff": { return Continue.eff(map(self.query, f)) } case "Get": { return Continue.get(Effect.map(self.effect, f)) } } } /** * Transforms all data sources with the specified data source aspect. */ const mapDataSourcesContinuation = ( self: Continue.Continue, f: (dataSource: DataSource.DataSource) => DataSource.DataSource ): Continue.Continue => { switch (self._tag) { case "Eff": { return Continue.eff(mapDataSources(self.query, f)) } case "Get": { return self } } } /** * Purely maps over the failure cause of this continuation. */ const mapErrorCauseContinuation = ( self: Continue.Continue, f: (e: Cause.Cause) => Cause.Cause ): Continue.Continue => { switch (self._tag) { case "Eff": { return Continue.eff(mapErrorCause(self.query, f)) } case "Get": { return Continue.get(Effect.mapErrorCause(self.effect, f)) } } } /** * Effectually maps over the success type of this continuation. */ const mapQueryContinuation = ( self: Continue.Continue, f: (a: A) => Query.Query ): Continue.Continue => { switch (self._tag) { case "Eff": { return Continue.eff(flatMap(self.query, f)) } case "Get": { return Continue.eff(flatMap(fromEffect(self.effect), f)) } } } /** * Effectually folds over the failure and success types of this continuation. */ const matchCauseQueryContination = ( self: Continue.Continue, onFailure: (cause: Cause.Cause) => Query.Query, onSuccess: (value: A) => Query.Query ): Continue.Continue => { switch (self._tag) { case "Eff": { return Continue.eff(matchCauseQuery(self.query, onFailure, onSuccess)) } case "Get": { return Continue.eff(matchCauseQuery(fromEffect(self.effect), onFailure, onSuccess)) } } } /** * Combines this continuation with that continuation using the specified * function, in sequence. */ const zipWithContinuation = ( self: Continue.Continue, that: Continue.Continue, f: (a: A, b: B) => C ): Continue.Continue => { switch (self._tag) { case "Eff": { switch (that._tag) { case "Eff": { return Continue.eff(zipWith(self.query, that.query, f)) } case "Get": { return Continue.eff(zipWith(self.query, fromEffect(that.effect), f)) } } } case "Get": { switch (that._tag) { case "Eff": { return Continue.eff(zipWith(fromEffect(self.effect), that.query, f)) } case "Get": { return Continue.get(Effect.zipWith(self.effect, that.effect, f)) } } } } } /** * Combines this continuation with that continuation using the specified * function, in parallel. */ const zipWithParContinuation = ( self: Continue.Continue, that: Continue.Continue, f: (a: A, b: B) => C ): Continue.Continue => { switch (self._tag) { case "Eff": { switch (that._tag) { case "Eff": { return Continue.eff(zipWithPar(self.query, that.query, f)) } case "Get": { return Continue.eff(zipWith(self.query, fromEffect(that.effect), f)) } } } case "Get": { switch (that._tag) { case "Eff": { return Continue.eff(zipWith(fromEffect(self.effect), that.query, f)) } case "Get": { return Continue.get(Effect.zipWith(self.effect, that.effect, f)) } } } } } /** * Combines this continuation with that continuation using the specified * function, batching requests to data sources. */ export const zipWithBatchedContinuation = ( self: Continue.Continue, that: Continue.Continue, f: (a: A, b: B) => C ): Continue.Continue => { switch (self._tag) { case "Eff": { switch (that._tag) { case "Eff": { return Continue.eff(zipWithBatched(self.query, that.query, f)) } case "Get": { return Continue.eff(zipWith(self.query, fromEffect(that.effect), f)) } } } case "Get": { switch (that._tag) { case "Eff": { return Continue.eff(zipWith(fromEffect(self.effect), that.query, f)) } case "Get": { return Continue.get(Effect.zipWith(self.effect, that.effect, f)) } } } } } // Circular with Result /** * Collects a collection of results into a single result. Blocked requests and * their continuations will be executed in parallel. */ const collectAllParResult = ( elements: Iterable> ): Result.Result> => { const blocked: Array, Continue.Continue, number]> = [] const done: Array = [] const fail: Array, number]> = [] const iterator = elements[Symbol.iterator]() let index = 0 let next: IteratorResult, any> while ((next = iterator.next()) && !next.done) { const result = next.value switch (result._tag) { case "Blocked": { blocked.push([result.blockedRequests, result.continue, index]) break } case "Done": { done.push([result.value, index]) break } case "Fail": { fail.push([result.cause, index]) break } } index++ } if (ReadonlyArray.isEmptyReadonlyArray(blocked) && ReadonlyArray.isEmptyReadonlyArray(fail)) { return Result.done(Chunk.unsafeFromArray(done.map(([a]) => a))) } if (ReadonlyArray.isEmptyReadonlyArray(fail)) { const blockedRequests = blocked.map((tuple) => tuple[0]).reduce(BlockedRequests.par, BlockedRequests.empty) const continuation = mapContinuation( collectAllParContinuation(blocked.map((tuple) => tuple[1])), (chunk) => { const array: Array = new Array(chunk.length) const indices = blocked.map((tuple) => tuple[2]) for (let i = 0; i < chunk.length; i++) { array[indices[i]] = pipe(chunk, Chunk.unsafeGet(i)) } for (let i = 0; i < done.length; i++) { array[done[i][1]] = done[i][0] } return Chunk.fromIterable(array) } ) return Result.blocked(blockedRequests, continuation) } return Result.fail(fail.map((tuple) => tuple[0]).reduce(Cause.parallel, Cause.empty)) } /** * Provides this result with part of its required environment. */ const contramapContextResult = ( self: Result.Result, f: Described.Described<(context: Context.Context) => Context.Context> ) => { switch (self._tag) { case "Blocked": { return Result.blocked( BlockedRequests.contramapContext(self.blockedRequests, f), contramapContextContinuation(self.continue, f) ) } case "Done": case "Fail": { return self } } } /** * Maps the specified function over the failure cause of this result. */ const mapErrorCauseResult = ( self: Result.Result, f: (cause: Cause.Cause) => Cause.Cause ): Result.Result => { switch (self._tag) { case "Blocked": { return Result.blocked( self.blockedRequests, mapErrorCauseContinuation(self.continue, f) ) } case "Done": { return self } case "Fail": { return Result.fail(f(self.cause)) } } } /** * Transforms all data sources with the specified data source aspect. */ const mapDataSourcesResult = ( self: Result.Result, f: (dataSource: DataSource.DataSource) => DataSource.DataSource ): Result.Result => { switch (self._tag) { case "Blocked": { return Result.blocked( BlockedRequests.mapDataSources(self.blockedRequests, f), mapDataSourcesContinuation(self.continue, f) ) } case "Done": case "Fail": { return self } } } /** * Maps the specified function over the successful value of this result. */ const mapResult = (self: Result.Result, f: (a: A) => B): Result.Result => { switch (self._tag) { case "Blocked": { return Result.blocked(self.blockedRequests, mapContinuation(self.continue, f)) } case "Done": { return Result.done(f(self.value)) } case "Fail": { return self as Result.Result } } }