// ets_tracing: off import "../Operator/index.js" /** * Ported from https://github.com/zio/zio/blob/master/core/shared/src/main/scala/zio/Has.scala * * Copyright 2020 Michael Arnaldi and the Matechs Garage Contributors. */ import type { Option } from "../Option/index.js" import { fromNullable, none } from "../Option/index.js" export type Flat = { readonly [k in keyof A]: A[k] } extends infer X ? X : never export function service>(x: X): Flat { // @ts-expect-error return x } /** * URI used in Has */ export declare const HasURI: unique symbol /** * Has signal presence of a specific service provided via Tag in the environment */ export interface Has { [HasURI]: { _T: () => T } } /** * Extract the type of a class constructor */ export type ConstructorType> = K extends { prototype: infer T } ? T : never export type Constructor = Function & { prototype: T } /** * Tag Encodes capabilities of reading and writing a service T into a generic environment */ export interface Tag { _tag: "Tag" _T: T key: PropertyKey read: (r: Has) => T readOption: (r: unknown) => Option has: (_: T) => Has of: (_: T) => T refine: () => Tag } /** * Extract the Has type from any augumented variant */ const makeTag = (key: PropertyKey = Symbol()): Tag => ({ _tag: "Tag", _T: undefined as any, key, has: (t) => ({ [key]: t } as any), of: (t) => t, read: (r: Has) => r[key], readOption: (r: unknown) => typeof r === "object" && r !== null ? fromNullable(r[key]) : none, refine: () => makeTag(key) }) /** * Create a service entry Tag from a type and a URI */ export function tag(key?: PropertyKey): Tag { return makeTag(key) } /** * Get the service type of a Has */ export type ServiceType = [T] extends [Has] ? A : never /** * Replaces the service with the required Service Entry, in the specified environment */ export const replaceServiceIn = (_: Tag, f: (t: T) => T) => (r: R & Has): R & Has => ({ ...r, [_.key]: f(r[_.key]) }) /** * Replaces the service with the required Service Entry, in the specified environment */ export const replaceServiceIn_ = ( r: R & Has, _: Tag, f: (t: T) => T ): R & Has => ({ ...r, ..._.has(f(r[_.key])) }) export function mergeEnvironments( _: Tag, r: R1, t: T ): R1 & Has { return { ...r, ..._.has(t) } }