{"version":3,"file":"index.mjs","names":[],"sources":["../../src/di/types.ts","../../src/di/env.ts","../../src/di/plan.ts","../../src/di/index.ts"],"sourcesContent":["import type { Op } from \"../index.js\";\nimport type { Dependency } from \"./index.js\";\nimport {\n  type Blocking,\n  type NormalizeMeta,\n  type Simplify,\n  type StripEmpty,\n} from \"../core/metadata.js\";\n\n/** Binding failure when an injected dependency was not provided for the run. */\nexport class MissingDependencyError extends Error {\n  override readonly name = \"MissingDependencyError\";\n  readonly _tag = \"MissingDependencyError\";\n  readonly key: string;\n\n  constructor(key: string) {\n    super(`${key} is required but was not provided`);\n    this.key = key;\n  }\n\n  static is(value: unknown): value is MissingDependencyError {\n    return value instanceof MissingDependencyError;\n  }\n}\n\n/** Binding failure when the same dependency token is provided more than once. */\nexport class DuplicateDependencyError extends Error {\n  override readonly name = \"DuplicateDependencyError\";\n  readonly _tag = \"DuplicateDependencyError\";\n  readonly key: string;\n\n  constructor(key: string) {\n    super(`${key} was provided more than once`);\n    this.key = key;\n  }\n\n  static is(value: unknown): value is DuplicateDependencyError {\n    return value instanceof DuplicateDependencyError;\n  }\n}\n\nexport const DI_TOKEN = Symbol(\"prodkit.op.di.dependency\");\nexport const DI_TAG = \"DI\";\nexport const DI_SINGLETON_BINDING: unique symbol = Symbol(\"prodkit.op.di.singleton-binding\");\nexport const DI_LAZY_BINDING: unique symbol = Symbol(\"prodkit.op.di.lazy-binding\");\n\nexport type AnyDependency = Dependency<unknown, string>;\n\nexport interface DependencyCtor<Name extends string> {\n  readonly _tag: typeof DI_TAG;\n  readonly key: Name;\n  readonly [DI_TOKEN]: never;\n\n  new <T>(): Dependency<T, Name>;\n}\n\nexport type DependencyValue<C, V = unknown> = C extends abstract new (\n  ...args: never[]\n) => Dependency<infer T, string>\n  ? T & V\n  : C extends Dependency<infer T, string>\n    ? T & V\n    : never;\n\nexport type SingletonBinding<C extends AnyDependency, V = unknown> = {\n  readonly [DI_SINGLETON_BINDING]: true;\n  readonly dependency: C;\n  readonly value: DependencyValue<C, V>;\n};\nexport type AnySingletonBinding = SingletonBinding<AnyDependency>;\n\nexport type LazyResolveFn<C extends AnyDependency> = (\n  signal: AbortSignal,\n) => DependencyValue<C> | PromiseLike<DependencyValue<C>>;\n\nexport type LazyBinding<C extends AnyDependency> = {\n  readonly [DI_LAZY_BINDING]: true;\n  readonly dependency: C;\n  readonly resolve: LazyResolveFn<C>;\n};\nexport type AnyLazyBinding = LazyBinding<AnyDependency>;\n\nexport type WithDIMeta<M, R> = [R] extends [never]\n  ? NormalizeMeta<Omit<StripEmpty<M>, \"deps\">>\n  : Simplify<Omit<StripEmpty<M>, \"deps\"> & { deps: Blocking<R> }>;\n\nexport type RequiredDepsOfMeta<M> = M extends { deps: Blocking<infer Required> } ? Required : never;\n\n/** Unsatisfied dependency tokens blocking `.run()` on an op. */\nexport type RequiredDeps<C> =\n  C extends Op<infer _T, infer _E, infer _A, infer M> ? RequiredDepsOfMeta<M> : never;\n\nexport type Deps<C> = C extends abstract new (...args: never[]) => infer I ? I : C;\n\nexport type AnyBinding = AnySingletonBinding | AnyLazyBinding;\n\nexport type DepsOf<P extends AnyBinding> =\n  P extends SingletonBinding<infer C> ? Deps<C> : P extends LazyBinding<infer C> ? Deps<C> : never;\n\nexport type RemainingRequiredDeps<Entries extends readonly AnyBinding[], R> = Exclude<\n  R,\n  DepsOf<Entries[number]>\n>;\n\ntype ExcessProvidedDeps<Entries extends readonly AnyBinding[], R> = Exclude<\n  DepsOf<Entries[number]>,\n  R\n>;\n\nexport type ValidProvideBindings<Bindings extends readonly AnyBinding[], R> = [\n  ExcessProvidedDeps<Bindings, R>,\n] extends [never]\n  ? Bindings\n  : never;\n\ntype UpdateProvidedMeta<M, R> = [R] extends [never]\n  ? NormalizeMeta<Omit<StripEmpty<M>, \"deps\">>\n  : Simplify<Omit<StripEmpty<M>, \"deps\"> & { deps: Blocking<R> }>;\n\nexport type ProvidedMeta<M, Entries extends readonly AnyBinding[]> = UpdateProvidedMeta<\n  M,\n  RemainingRequiredDeps<Entries, RequiredDepsOfMeta<M>>\n>;\n","import { createRunContext, type RunContext } from \"../execution/runtime.js\";\nimport { Settlement } from \"../execution/settlement.js\";\nimport { isPromiseLike, keyIs } from \"@prodkit/shared/runtime\";\nimport {\n  DI_LAZY_BINDING,\n  DI_SINGLETON_BINDING,\n  DuplicateDependencyError,\n  type AnyBinding,\n  type AnyDependency,\n  type AnyLazyBinding,\n  type DependencyValue,\n} from \"./types.js\";\n\nexport const DI_ENV_EXTENSION = Symbol(\"prodkit.op.di.env\");\nexport const MISSING_DEPENDENCY = Symbol(\"prodkit.op.di.missing-dependency\");\n\nexport function isLazyBinding(value: unknown): value is AnyLazyBinding {\n  return keyIs(value, DI_LAZY_BINDING, true);\n}\n\nexport type Env = Map<AnyDependency, DependencyValue<AnyDependency>>;\n\nexport function readEnv(context: RunContext<readonly unknown[]>): Env {\n  const env = context.extensions.get(DI_ENV_EXTENSION);\n  if (env instanceof Map) return env;\n  return new Map();\n}\n\nfunction withProvisionEntry(env: Env, entry: AnyBinding): Env {\n  if (env.has(entry.dependency)) {\n    throw new DuplicateDependencyError(entry.dependency.key);\n  }\n  const value = keyIs(entry, DI_SINGLETON_BINDING, true) ? entry.value : entry;\n  env.set(entry.dependency, value);\n  return env;\n}\n\nexport function resolveInjectedValue(\n  env: Env,\n  dependency: AnyDependency,\n  signal: AbortSignal,\n): unknown | PromiseLike<unknown> {\n  if (!env.has(dependency)) return MISSING_DEPENDENCY;\n\n  const matchedValue = env.get(dependency);\n  if (matchedValue === undefined || !isLazyBinding(matchedValue)) return matchedValue;\n\n  const produced = matchedValue.resolve(signal);\n\n  if (!isPromiseLike(produced)) {\n    env.set(dependency, produced);\n    return produced;\n  }\n\n  const inflight = Settlement.rejecting.awaitWork(produced, signal).then(\n    (resolved) => {\n      env.set(dependency, resolved);\n      return resolved;\n    },\n    (error) => {\n      env.set(dependency, matchedValue);\n      return Promise.reject(error);\n    },\n  );\n\n  env.set(dependency, inflight);\n  return inflight;\n}\n\nexport function extendContextWithBindings(\n  context: RunContext<readonly unknown[]>,\n  bindings: readonly AnyBinding[],\n): RunContext<readonly unknown[]> {\n  const parentEnv = readEnv(context);\n  const env = bindings.reduce(\n    (current, entry) => withProvisionEntry(current, entry),\n    new Map(parentEnv),\n  );\n  const extensions = new Map(context.extensions);\n  extensions.set(DI_ENV_EXTENSION, env);\n  return createRunContext(context.signal, context.args, extensions);\n}\n","import { getPlan } from \"../plan/bridge.js\";\nimport { createUnaryPlan, type Plan } from \"../plan/model.js\";\nimport type { AsArgs } from \"../core/surface.js\";\nimport { makeUnboundPlanOp } from \"../core/shell.js\";\nimport { Settlement } from \"../execution/settlement.js\";\nimport { CUSTOM_INSTRUCTION_META, type CustomInstruction } from \"../execution/instructions.js\";\nimport type { RunContext } from \"../execution/runtime.js\";\nimport { UnhandledException } from \"../errors.js\";\nimport { Result } from \"../result.js\";\nimport { abortReason, NEVER, isPromiseLike, unsafeCoerce } from \"@prodkit/shared/runtime\";\nimport type { EmptyMeta } from \"../core/metadata.js\";\nimport type { Op } from \"../index.js\";\nimport {\n  MISSING_DEPENDENCY,\n  extendContextWithBindings,\n  readEnv,\n  resolveInjectedValue,\n} from \"./env.js\";\nimport {\n  MissingDependencyError,\n  type AnyBinding,\n  type AnyDependency,\n  type ProvidedMeta,\n  type WithDIMeta,\n} from \"./types.js\";\n\nexport class InjectInstruction<T, D> implements CustomInstruction<T, WithDIMeta<EmptyMeta, D>> {\n  readonly _tag = \"InjectInstruction\";\n  readonly [CUSTOM_INSTRUCTION_META]: WithDIMeta<EmptyMeta, D> = NEVER;\n  readonly dependency: AnyDependency;\n\n  constructor(dependency: AnyDependency) {\n    this.dependency = dependency;\n  }\n\n  resolve(context: RunContext<readonly unknown[]>): T | PromiseLike<T> {\n    if (context.signal.aborted) {\n      throw abortReason(context.signal);\n    }\n\n    const env = readEnv(context);\n    const value = resolveInjectedValue(env, this.dependency, context.signal);\n\n    if (value === MISSING_DEPENDENCY) {\n      throw new MissingDependencyError(this.dependency.key);\n    }\n\n    if (isPromiseLike(value)) {\n      return value.then((resolved) =>\n        // SAFETY: env slots are unknown at runtime; InjectInstruction<T> and resolution guarantee the value is T.\n        unsafeCoerce(resolved),\n      );\n    }\n\n    // SAFETY: env slots are unknown at runtime; InjectInstruction<T> and resolution guarantee the value is T.\n    return unsafeCoerce(value);\n  }\n\n  *[Symbol.iterator](): Generator<this, T, unknown> {\n    // SAFETY: generator yield type is unknown; CustomInstruction resolves yield* to the same T as resolve().\n    return unsafeCoerce(yield this);\n  }\n}\n\nexport function providePlan<T, E, M>(\n  source: Plan<T, E, M>,\n  bindings: readonly AnyBinding[],\n): Plan<T, E, M> {\n  const snapshot = bindings.slice();\n\n  return createUnaryPlan(\n    function* () {\n      const result: Result<T, E | UnhandledException> =\n        yield* Settlement.interruptingAndDraining.suspendPlan(source, (context) =>\n          extendContextWithBindings(context, snapshot),\n        );\n\n      if (result.isErr()) return yield* result;\n      return result.value;\n    },\n    source,\n    (inner) => providePlan(inner, snapshot),\n  );\n}\n\nexport function provideOp<T, E, A, M, const Bindings extends readonly AnyBinding[]>(\n  op: Op<T, E, A, M>,\n  bindings: Bindings,\n): Op<T, E, A, ProvidedMeta<M, Bindings>> {\n  const bindProvidePlan = (...args: AsArgs<A>) => providePlan(getPlan(op, args), bindings);\n\n  // SAFETY: makeUnboundPlanOp cannot express ProvidedMeta; bindings only change metadata, not T, E, or runtime behavior.\n  return unsafeCoerce(\n    makeUnboundPlanOp(bindProvidePlan, () =>\n      bindProvidePlan(\n        // SAFETY: yield* iterable is nullary (A=[]); bindProvidePlan expects no runtime args on this surface.\n        ...unsafeCoerce<AsArgs<A>>([]),\n      ),\n    ),\n  );\n}\n","import { NEVER } from \"@prodkit/shared/runtime\";\nimport type { Op } from \"../index.js\";\nimport { InjectInstruction, provideOp } from \"./plan.js\";\nimport {\n  DI_TAG,\n  DI_TOKEN,\n  DI_SINGLETON_BINDING,\n  DI_LAZY_BINDING,\n  MissingDependencyError,\n  DuplicateDependencyError,\n  type AnyDependency,\n  type SingletonBinding,\n  type DependencyCtor,\n  type Deps,\n  type DependencyValue,\n  type LazyBinding,\n  type LazyResolveFn,\n  type AnyBinding,\n  type ValidProvideBindings,\n  type RequiredDepsOfMeta,\n  type ProvidedMeta,\n  type RequiredDeps,\n} from \"./types.js\";\n\n/**\n * Phantom-typed dependency token created with {@link Dependency}.\n * Runtime slot identity is the token **class** passed to {@link inject} and bindings, not the\n * `key` string (see ADR 0010).\n */\nexport interface Dependency<T, Name extends string> {\n  readonly _tag: typeof DI_TAG;\n  readonly key: Name;\n  readonly [DI_TOKEN]: T;\n}\n\n/**\n * Creates a dependency token class for {@link inject} and bindings.\n * `key` is used in binding failure messages; two classes may share a `key` and remain distinct\n * slots.\n */\nexport const Dependency = <const Name extends string>(key: Name): DependencyCtor<Name> => {\n  class DependencyToken<T> {\n    readonly _tag = DI_TAG;\n    readonly key = key;\n    readonly [DI_TOKEN] = NEVER;\n\n    *[Symbol.iterator](): Generator<InjectInstruction<T, this>, T, unknown> {\n      return yield* new InjectInstruction<T, this>(DependencyToken);\n    }\n\n    static readonly _tag = DI_TAG;\n    static readonly key = key;\n    static readonly [DI_TOKEN] = NEVER;\n\n    static *[Symbol.iterator](): Generator<never, never, unknown> {\n      throw new TypeError(\"Use DI.inject(dependency) to inject a dependency binding\");\n    }\n  }\n\n  return DependencyToken;\n};\n\n/** Yields a bound dependency value from the current run context. */\nexport const inject = function* <C extends AnyDependency>(\n  dependency: C,\n): Generator<InjectInstruction<DependencyValue<C>, Deps<C>>, DependencyValue<C>, unknown> {\n  return yield* new InjectInstruction<DependencyValue<C>, Deps<C>>(dependency);\n};\n\n/** Eager singleton binding for {@link provide}. */\nexport const singleton = <C extends AnyDependency, V = unknown>(\n  dependency: C,\n  value: DependencyValue<C, V>,\n): SingletonBinding<C, V> => ({\n  [DI_SINGLETON_BINDING]: true,\n  dependency,\n  value,\n});\n\n/** Per-run lazy binding resolved when first injected. */\nexport const scoped = <C extends AnyDependency>(\n  dependency: C,\n  resolve: LazyResolveFn<C>,\n): LazyBinding<C> => ({\n  [DI_LAZY_BINDING]: true,\n  dependency,\n  resolve,\n});\n\n/**\n * Satisfies dependency requirements on an op before `.run()`.\n * Pass a readonly tuple of `DI.singleton` / `DI.scoped` bindings\n */\nexport const provide = <T, E, A, M, const Bindings extends readonly AnyBinding[]>(\n  op: Op<T, E, A, M>,\n  bindings: ValidProvideBindings<Bindings, RequiredDepsOfMeta<M>>,\n): Op<T, E, A, ProvidedMeta<M, Bindings>> => provideOp(op, bindings);\n\n/** Namespace object for dependency injection helpers. */\nexport const DI = {\n  Dependency,\n  inject,\n  singleton,\n  scoped,\n  provide,\n  /** Error type for a missing binding on `error.cause` after `.run()`. */\n  MissingDependencyError,\n  /** Error type for a duplicate binding on `error.cause` after `.run()`. */\n  DuplicateDependencyError,\n} as const;\n\nexport type { RequiredDeps };\n"],"mappings":";;;;;AAUA,IAAa,yBAAb,MAAa,+BAA+B,MAAM;CAChD,OAAyB;CACzB,OAAgB;CAChB;CAEA,YAAY,KAAa;EACvB,MAAM,GAAG,IAAI,kCAAkC;EAC/C,KAAK,MAAM;CACb;CAEA,OAAO,GAAG,OAAiD;EACzD,OAAO,iBAAiB;CAC1B;AACF;;AAGA,IAAa,2BAAb,MAAa,iCAAiC,MAAM;CAClD,OAAyB;CACzB,OAAgB;CAChB;CAEA,YAAY,KAAa;EACvB,MAAM,GAAG,IAAI,6BAA6B;EAC1C,KAAK,MAAM;CACb;CAEA,OAAO,GAAG,OAAmD;EAC3D,OAAO,iBAAiB;CAC1B;AACF;AAEA,MAAa,WAAW,OAAO,0BAA0B;AAEzD,MAAa,uBAAsC,OAAO,iCAAiC;AAC3F,MAAa,kBAAiC,OAAO,4BAA4B;;;AC/BjF,MAAa,mBAAmB,OAAO,mBAAmB;AAC1D,MAAa,qBAAqB,OAAO,kCAAkC;AAE3E,SAAgB,cAAc,OAAyC;CACrE,OAAO,MAAM,OAAO,iBAAiB,IAAI;AAC3C;AAIA,SAAgB,QAAQ,SAA8C;CACpE,MAAM,MAAM,QAAQ,WAAW,IAAI,gBAAgB;CACnD,IAAI,eAAe,KAAK,OAAO;CAC/B,uBAAO,IAAI,IAAI;AACjB;AAEA,SAAS,mBAAmB,KAAU,OAAwB;CAC5D,IAAI,IAAI,IAAI,MAAM,UAAU,GAC1B,MAAM,IAAI,yBAAyB,MAAM,WAAW,GAAG;CAEzD,MAAM,QAAQ,MAAM,OAAO,sBAAsB,IAAI,IAAI,MAAM,QAAQ;CACvE,IAAI,IAAI,MAAM,YAAY,KAAK;CAC/B,OAAO;AACT;AAEA,SAAgB,qBACd,KACA,YACA,QACgC;CAChC,IAAI,CAAC,IAAI,IAAI,UAAU,GAAG,OAAO;CAEjC,MAAM,eAAe,IAAI,IAAI,UAAU;CACvC,IAAI,iBAAiB,KAAA,KAAa,CAAC,cAAc,YAAY,GAAG,OAAO;CAEvE,MAAM,WAAW,aAAa,QAAQ,MAAM;CAE5C,IAAI,CAAC,cAAc,QAAQ,GAAG;EAC5B,IAAI,IAAI,YAAY,QAAQ;EAC5B,OAAO;CACT;CAEA,MAAM,WAAW,WAAW,UAAU,UAAU,UAAU,MAAM,EAAE,MAC/D,aAAa;EACZ,IAAI,IAAI,YAAY,QAAQ;EAC5B,OAAO;CACT,IACC,UAAU;EACT,IAAI,IAAI,YAAY,YAAY;EAChC,OAAO,QAAQ,OAAO,KAAK;CAC7B,CACF;CAEA,IAAI,IAAI,YAAY,QAAQ;CAC5B,OAAO;AACT;AAEA,SAAgB,0BACd,SACA,UACgC;CAChC,MAAM,YAAY,QAAQ,OAAO;CACjC,MAAM,MAAM,SAAS,QAClB,SAAS,UAAU,mBAAmB,SAAS,KAAK,GACrD,IAAI,IAAI,SAAS,CACnB;CACA,MAAM,aAAa,IAAI,IAAI,QAAQ,UAAU;CAC7C,WAAW,IAAI,kBAAkB,GAAG;CACpC,OAAO,iBAAiB,QAAQ,QAAQ,QAAQ,MAAM,UAAU;AAClE;;;ACvDA,IAAa,oBAAb,MAA+F;CAC7F,OAAgB;CAChB,CAAU,2BAAqD;CAC/D;CAEA,YAAY,YAA2B;EACrC,KAAK,aAAa;CACpB;CAEA,QAAQ,SAA6D;EACnE,IAAI,QAAQ,OAAO,SACjB,MAAM,YAAY,QAAQ,MAAM;EAIlC,MAAM,QAAQ,qBADF,QAAQ,OACiB,GAAG,KAAK,YAAY,QAAQ,MAAM;EAEvE,IAAI,UAAU,oBACZ,MAAM,IAAI,uBAAuB,KAAK,WAAW,GAAG;EAGtD,IAAI,cAAc,KAAK,GACrB,OAAO,MAAM,MAAM,aAEjB,aAAa,QAAQ,CACvB;EAIF,OAAO,aAAa,KAAK;CAC3B;CAEA,EAAE,OAAO,YAAyC;EAEhD,OAAO,aAAa,MAAM,IAAI;CAChC;AACF;AAEA,SAAgB,YACd,QACA,UACe;CACf,MAAM,WAAW,SAAS,MAAM;CAEhC,OAAO,gBACL,aAAa;EACX,MAAM,SACJ,OAAO,WAAW,wBAAwB,YAAY,SAAS,YAC7D,0BAA0B,SAAS,QAAQ,CAC7C;EAEF,IAAI,OAAO,MAAM,GAAG,OAAO,OAAO;EAClC,OAAO,OAAO;CAChB,GACA,SACC,UAAU,YAAY,OAAO,QAAQ,CACxC;AACF;AAEA,SAAgB,UACd,IACA,UACwC;CACxC,MAAM,mBAAmB,GAAG,SAAoB,YAAY,QAAQ,IAAI,IAAI,GAAG,QAAQ;CAGvF,OAAO,aACL,kBAAkB,uBAChB,gBAEE,GAAG,aAAwB,CAAC,CAAC,CAC/B,CACF,CACF;AACF;;;;;;;;AC5DA,MAAa,cAAyC,QAAoC;CACxF,MAAM,gBAAmB;EACvB,OAAS;EACT,MAAe;EACf,CAAU,YAAY;EAEtB,EAAE,OAAO,YAA+D;GACtE,OAAO,OAAO,IAAI,kBAA2B,eAAe;EAC9D;EAEA,OAAgB,OAAA;EAChB,OAAgB,MAAM;EACtB,QAAiB,YAAY;EAE7B,SAAS,OAAO,YAA8C;GAC5D,MAAM,IAAI,UAAU,0DAA0D;EAChF;CACF;CAEA,OAAO;AACT;;AAGA,MAAa,SAAS,WACpB,YACwF;CACxF,OAAO,OAAO,IAAI,kBAA+C,UAAU;AAC7E;;AAGA,MAAa,aACX,YACA,WAC4B;EAC3B,uBAAuB;CACxB;CACA;AACF;;AAGA,MAAa,UACX,YACA,aACoB;EACnB,kBAAkB;CACnB;CACA;AACF;;;;;AAMA,MAAa,WACX,IACA,aAC2C,UAAU,IAAI,QAAQ;;AAGnE,MAAa,KAAK;CAChB;CACA;CACA;CACA;CACA;;CAEA;;CAEA;AACF"}