import type * as Cause from "../Cause.js" import type * as Effect from "../Effect.js" import { dual } from "../Function.js" import { hasProperty } from "../Predicate.js" import type * as Request from "../Request.js" import type * as Types from "../Types.js" import * as completedRequestMap from "./completedRequestMap.js" import * as core from "./core.js" import { StructuralPrototype } from "./effectable.js" /** @internal */ const RequestSymbolKey = "effect/Request" /** @internal */ export const RequestTypeId: Request.RequestTypeId = Symbol.for( RequestSymbolKey ) as Request.RequestTypeId const requestVariance = { /* c8 ignore next */ _E: (_: never) => _, /* c8 ignore next */ _A: (_: never) => _ } const RequestPrototype = { ...StructuralPrototype, [RequestTypeId]: requestVariance } /** @internal */ export const isRequest = (u: unknown): u is Request.Request => hasProperty(u, RequestTypeId) /** @internal */ export const of = >(): Request.Request.Constructor => (args) => Object.assign(Object.create(RequestPrototype), args) /** @internal */ export const tagged = & { _tag: string }>( tag: R["_tag"] ): Request.Request.Constructor => (args) => { const request = Object.assign(Object.create(RequestPrototype), args) request._tag = tag return request } /** @internal */ export const Class: new>( args: Types.Equals>, {}> extends true ? void : { readonly [P in keyof A as P extends keyof Request.Request ? never : P]: A[P] } ) => Request.Request & Readonly = (function() { function Class(this: any, args: any) { if (args) { Object.assign(this, args) } } Class.prototype = RequestPrototype return Class as any })() /** @internal */ export const TaggedClass = ( tag: Tag ): new>( args: Types.Equals>, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" | keyof Request.Request ? never : P]: A[P] } ) => Request.Request & Readonly & { readonly _tag: Tag } => { return class TaggedClass extends Class { readonly _tag = tag } as any } /** @internal */ export const complete = dual< >( result: Request.Request.Result ) => (self: A) => Effect.Effect, >( self: A, result: Request.Request.Result ) => Effect.Effect >(2, (self, result) => core.fiberRefGetWith( completedRequestMap.currentRequestMap, (map) => core.sync(() => { if (map.has(self)) { const entry = map.get(self)! if (!entry.state.completed) { entry.state.completed = true core.deferredUnsafeDone(entry.result, result) } } }) )) /** @internal */ export const completeEffect = dual< , R>( effect: Effect.Effect, Request.Request.Error, R> ) => (self: A) => Effect.Effect, , R>( self: A, effect: Effect.Effect, Request.Request.Error, R> ) => Effect.Effect >(2, (self, effect) => core.matchEffect(effect, { onFailure: (error) => complete(self, core.exitFail(error) as any), onSuccess: (value) => complete(self, core.exitSucceed(value) as any) })) /** @internal */ export const fail = dual< >( error: Request.Request.Error ) => (self: A) => Effect.Effect, >( self: A, error: Request.Request.Error ) => Effect.Effect >(2, (self, error) => complete(self, core.exitFail(error) as any)) /** @internal */ export const failCause = dual< >( cause: Cause.Cause> ) => (self: A) => Effect.Effect, >( self: A, cause: Cause.Cause> ) => Effect.Effect >(2, (self, cause) => complete(self, core.exitFailCause(cause) as any)) /** @internal */ export const succeed = dual< >( value: Request.Request.Success ) => (self: A) => Effect.Effect, >( self: A, value: Request.Request.Success ) => Effect.Effect >(2, (self, value) => complete(self, core.exitSucceed(value) as any)) /** @internal */ export class Listeners { count = 0 observers: Set<(count: number) => void> = new Set() interrupted = false addObserver(f: (count: number) => void): void { this.observers.add(f) } removeObserver(f: (count: number) => void): void { this.observers.delete(f) } increment() { this.count++ this.observers.forEach((f) => f(this.count)) } decrement() { this.count-- this.observers.forEach((f) => f(this.count)) } } /** * @internal */ export const filterOutCompleted = >(requests: Array) => core.fiberRefGetWith( completedRequestMap.currentRequestMap, (map) => core.succeed( requests.filter((request) => !(map.get(request)?.state.completed === true)) ) )