Hyperlinkv0.8.0-beta.28

LayerMap

LayerMap.Servicenamespaceeffect/LayerMap.ts:350
<Self>(): <
  const Id extends string,
  const Options extends
    | NoExcessProperties<
        {
          readonly lookup: (key: any) => Layer.Layer<any, any, any>
          readonly dependencies?:
            | ReadonlyArray<Layer.Layer<any, any, any>>
            | undefined
          readonly idleTimeToLive?: IdleTimeToLiveInput<any> | undefined
          readonly preloadKeys?:
            | Iterable<
                Options extends { readonly lookup: (key: infer K) => any }
                  ? K
                  : never
              >
            | undefined
        },
        Options
      >
    | NoExcessProperties<
        {
          readonly layers: Record<string, Layer.Layer<any, any, any>>
          readonly dependencies?:
            | ReadonlyArray<Layer.Layer<any, any, any>>
            | undefined
          readonly idleTimeToLive?: IdleTimeToLiveInput<any> | undefined
          readonly preload?: boolean | undefined
        },
        Options
      >
>(
  id: Id,
  options: Options
) => TagClass<
  Self,
  Id,
  Options extends { readonly lookup: (key: infer K) => any }
    ? K
    : Options extends { readonly layers: infer Layers }
    ? keyof Layers
    : never,
  Service.Success<Options>,
  Options extends { readonly preload: true }
    ? never
    : Service.Error<Options>,
  Service.Services<Options>,
  Options extends { readonly preload: true }
    ? Service.Error<Options>
    : Options extends { readonly preloadKeys: Iterable<any> }
    ? Service.Error<Options>
    : never,
  Options extends {
    readonly dependencies: ReadonlyArray<Layer.Layer<any, any, any>>
  }
    ? Options["dependencies"][number]
    : never
>

Create a LayerMap service that provides a dynamic set of resources based on a key.

Example (Defining a layer map service)

import { Console, Context, Effect, Layer, LayerMap } from "effect"

// Define a service key
const Greeter = Context.Service<{
  readonly greet: Effect.Effect<string>
}>("Greeter")

// Create a service that wraps a LayerMap
class GreeterMap extends LayerMap.Service<GreeterMap>()("GreeterMap", {
  // Define the lookup function for the layer map
  lookup: (name: string) =>
    Layer.succeed(Greeter)({
      greet: Effect.succeed(`Hello, ${name}!`)
    }),

  // If a layer is not used for a certain amount of time, it can be removed
  idleTimeToLive: "5 seconds"
}) {}

// Usage
const program = Effect.gen(function*() {
  // Access and use the Greeter service
  const greeter = yield* Greeter
  yield* Console.log(yield* greeter.greet)
}).pipe(
  // Use the GreeterMap service to provide a variant of the Greeter service
  Effect.provide(GreeterMap.get("John"))
).pipe(
  // Provide the GreeterMap layer
  Effect.provide(GreeterMap.layer)
)
services
Source effect/LayerMap.ts:350120 lines
export const Service = <Self>() =>
<
  const Id extends string,
  const Options extends
    | NoExcessProperties<{
      readonly lookup: (key: any) => Layer.Layer<any, any, any>
      readonly dependencies?: ReadonlyArray<Layer.Layer<any, any, any>> | undefined
      readonly idleTimeToLive?: IdleTimeToLiveInput<any> | undefined
      readonly preloadKeys?:
        | Iterable<Options extends { readonly lookup: (key: infer K) => any } ? K : never>
        | undefined
    }, Options>
    | NoExcessProperties<{
      readonly layers: Record<string, Layer.Layer<any, any, any>>
      readonly dependencies?: ReadonlyArray<Layer.Layer<any, any, any>> | undefined
      readonly idleTimeToLive?: IdleTimeToLiveInput<any> | undefined
      readonly preload?: boolean | undefined
    }, Options>
>(
  id: Id,
  options: Options
): TagClass<
  Self,
  Id,
  Options extends { readonly lookup: (key: infer K) => any } ? K
    : Options extends { readonly layers: infer Layers } ? keyof Layers
    : never,
  Service.Success<Options>,
  Options extends { readonly preload: true } ? never : Service.Error<Options>,
  Service.Services<Options>,
  Options extends { readonly preload: true } ? Service.Error<Options>
    : Options extends { readonly preloadKeys: Iterable<any> } ? Service.Error<Options>
    : never,
  Options extends { readonly dependencies: ReadonlyArray<Layer.Layer<any, any, any>> } ? Options["dependencies"][number]
    : never
> => {
  const Err = globalThis.Error as any
  const limit = getStackTraceLimit()
  setStackTraceLimit(2)
  const creationError = new Err()
  setStackTraceLimit(limit)

  function TagClass() {}
  const TagClass_ = TagClass as any as Mutable<TagClass<Self, Id, string, any, any, any, any, any>>
  Object.setPrototypeOf(TagClass, Object.getPrototypeOf(Context.Service<Self, any>(id)))
  TagClass.key = id
  Object.defineProperty(TagClass, "stack", {
    get() {
      return creationError.stack
    }
  })

  TagClass_.layerNoDeps = Layer.effect(TagClass_)(
    "lookup" in options
      ? make(options.lookup, options)
      : fromRecord(options.layers as any, options) as any
  )
  TagClass_.layer = options.dependencies && options.dependencies.length > 0 ?
    Layer.provide(TagClass_.layerNoDeps, options.dependencies as any) :
    TagClass_.layerNoDeps

  TagClass_.get = (key: string) => Layer.unwrap(Effect.map(TagClass_, (layerMap) => layerMap.get(key)))
  TagClass_.contextEffect = (key: string) => Effect.flatMap(TagClass_, (layerMap) => layerMap.contextEffect(key))
  TagClass_.invalidate = (key: string) => Effect.flatMap(TagClass_, (layerMap) => layerMap.invalidate(key))

  return TagClass as any
}

/**
 * Type helpers for values created with `LayerMap.Service`.
 *
 * @since 3.14.0
 */
export declare namespace Service {
  /**
   * Extracts the key type accepted by a `LayerMap.Service` definition.
   *
   * @category services
   * @since 3.14.0
   */
  export type Key<Options> = Options extends { readonly lookup: (key: infer K) => any } ? K
    : Options extends { readonly layers: infer Layers } ? keyof Layers
    : never

  /**
   * Extracts the layer type produced by a `LayerMap.Service` definition.
   *
   * @category services
   * @since 3.14.0
   */
  export type Layers<Options> = Options extends { readonly lookup: (key: infer _K) => infer Layers } ? Layers
    : Options extends { readonly layers: infer Layers } ? Layers[keyof Layers]
    : never

  /**
   * Extracts the services provided by the layers in a `LayerMap.Service`
   * definition.
   *
   * @category services
   * @since 3.14.0
   */
  export type Success<Options> = Layers<Options> extends Layer.Layer<infer _A, infer _E, infer _R> ? _A : never

  /**
   * Extracts the error type of the layers in a `LayerMap.Service` definition.
   *
   * @category services
   * @since 3.14.0
   */
  export type Error<Options> = Layers<Options> extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never

  /**
   * Extracts the service requirements of the layers in a `LayerMap.Service`
   * definition.
   *
   * @category services
   * @since 4.0.0
   */
  export type Services<Options> = Layers<Options> extends Layer.Layer<infer _A, infer _E, infer _R> ? _R : never
}