better-effect 0.8.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +47 -0
  2. package/dist/adapters/iti.d.mts +3 -3
  3. package/dist/adapters/iti.mjs +2 -1
  4. package/dist/adapters/iti.mjs.map +1 -1
  5. package/dist/{internal-identity-Cm4-KIUj.mjs → errors-Dnjhzbt0.mjs} +2 -25
  6. package/dist/errors-Dnjhzbt0.mjs.map +1 -0
  7. package/dist/{index-BFgG9zZC.d.mts → index-1NLNdkJy.d.mts} +2 -2
  8. package/dist/{index-BFgG9zZC.d.mts.map → index-1NLNdkJy.d.mts.map} +1 -1
  9. package/dist/index-BJFBEsm5.d.mts +406 -0
  10. package/dist/index-BJFBEsm5.d.mts.map +1 -0
  11. package/dist/{index-fUyY0eNJ.d.mts → index-CYAgpM_5.d.mts} +28 -14
  12. package/dist/index-CYAgpM_5.d.mts.map +1 -0
  13. package/dist/index.d.mts +5 -320
  14. package/dist/index.mjs +142 -277
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/internal-identity-DmUpBeeL.mjs +27 -0
  17. package/dist/internal-identity-DmUpBeeL.mjs.map +1 -0
  18. package/dist/{map-layer-backend-CGibcwkc.d.mts → map-layer-backend-DMJauecV.d.mts} +2 -2
  19. package/dist/{map-layer-backend-CGibcwkc.d.mts.map → map-layer-backend-DMJauecV.d.mts.map} +1 -1
  20. package/dist/{map-layer-backend-BodcEeNA.mjs → map-layer-backend-gal-mcRv.mjs} +3 -2
  21. package/dist/{map-layer-backend-BodcEeNA.mjs.map → map-layer-backend-gal-mcRv.mjs.map} +1 -1
  22. package/dist/runtime/explicit.d.mts +1 -1
  23. package/dist/runtime/node.d.mts +1 -1
  24. package/dist/signal-Cl9tqGyX.mjs +270 -0
  25. package/dist/signal-Cl9tqGyX.mjs.map +1 -0
  26. package/dist/standard-services.d.mts +116 -0
  27. package/dist/standard-services.d.mts.map +1 -0
  28. package/dist/standard-services.mjs +180 -0
  29. package/dist/standard-services.mjs.map +1 -0
  30. package/dist/testing.d.mts +1 -1
  31. package/dist/testing.mjs +1 -1
  32. package/package.json +6 -2
  33. package/dist/index-fUyY0eNJ.d.mts.map +0 -1
  34. package/dist/index.d.mts.map +0 -1
  35. package/dist/internal-identity-Cm4-KIUj.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-identity-DmUpBeeL.mjs","names":[],"sources":["../src/layer/internal-identity.ts"],"sourcesContent":["import type { AnyServiceToken } from '../service'\n\nimport { ServiceTagCollisionError } from './errors'\n\nimport type { LayerRegistration } from './types'\n\ntype LayerAcquiredValue = Awaited<ReturnType<LayerRegistration['acquire']>>\n\nconst serviceMemberNames = (token: AnyServiceToken): readonly (string | symbol)[] => {\n const names = new Set<string | symbol>()\n let prototype = token.prototype\n\n while (prototype && prototype !== Object.prototype) {\n for (const name of Object.getOwnPropertyNames(prototype)) {\n if (name !== 'constructor') {\n names.add(name)\n }\n }\n\n for (const symbol of Object.getOwnPropertySymbols(prototype)) {\n names.add(symbol)\n }\n\n prototype = Object.getPrototypeOf(prototype)\n }\n\n return [...names]\n}\n\n/**\n * Check the runtime portion of a same-tag association before returning it.\n * TypeScript remains authoritative for full structural compatibility; this\n * check catches the common incompatible-method collision after erasure.\n */\nexport const assertServiceCompatibility = (\n requested: AnyServiceToken,\n registered: AnyServiceToken,\n instance: LayerAcquiredValue\n): void => {\n if (requested === registered || requested.serviceTag !== registered.serviceTag) {\n return\n }\n\n const candidate = Object(instance)\n\n // SAFETY: Service providers are object instances; Object() lets this runtime boundary reject rogue primitive values without trusting their static type.\n if (candidate !== instance) {\n throw new ServiceTagCollisionError(registered, requested)\n }\n\n for (const name of serviceMemberNames(requested)) {\n if (!(name in candidate)) {\n throw new ServiceTagCollisionError(registered, requested)\n }\n }\n}\n"],"mappings":";;AAQA,MAAM,sBAAsB,UAAyD;CACnF,MAAM,wBAAQ,IAAI,IAAqB;CACvC,IAAI,YAAY,MAAM;CAEtB,OAAO,aAAa,cAAc,OAAO,WAAW;EAClD,KAAK,MAAM,QAAQ,OAAO,oBAAoB,SAAS,GACrD,IAAI,SAAS,eACX,MAAM,IAAI,IAAI;EAIlB,KAAK,MAAM,UAAU,OAAO,sBAAsB,SAAS,GACzD,MAAM,IAAI,MAAM;EAGlB,YAAY,OAAO,eAAe,SAAS;CAC7C;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB;;;;;;AAOA,MAAa,8BACX,WACA,YACA,aACS;CACT,IAAI,cAAc,cAAc,UAAU,eAAe,WAAW,YAClE;CAGF,MAAM,YAAY,OAAO,QAAQ;CAGjC,IAAI,cAAc,UAChB,MAAM,IAAI,yBAAyB,YAAY,SAAS;CAG1D,KAAK,MAAM,QAAQ,mBAAmB,SAAS,GAC7C,IAAI,EAAE,QAAQ,YACZ,MAAM,IAAI,yBAAyB,YAAY,SAAS;AAG9D"}
@@ -1,4 +1,4 @@
1
- import { F as ServiceContract, N as AnyServiceToken, O as InferYieldRequirements, P as ServiceClass, R as ServiceRequirements, a as ServiceResolver, j as ServiceRequirement } from "./index-BFgG9zZC.mjs";
1
+ import { F as ServiceContract, N as AnyServiceToken, O as InferYieldRequirements, P as ServiceClass, a as ServiceResolver, j as ServiceRequirement, z as ServiceRequirements } from "./index-1NLNdkJy.mjs";
2
2
  //#region src/utils/types.d.ts
3
3
  type MaybePromise<T> = T | PromiseLike<T>;
4
4
  //#endregion
@@ -39,4 +39,4 @@ declare class MapLayerBackend implements LayerBackend {
39
39
  }
40
40
  //#endregion
41
41
  export { LayerRegistration as a, LayerGeneratorRequirements as i, LayerBackend as n, MaybePromise as o, LayerGenerator as r, MapLayerBackend as t };
42
- //# sourceMappingURL=map-layer-backend-CGibcwkc.d.mts.map
42
+ //# sourceMappingURL=map-layer-backend-DMJauecV.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-layer-backend-CGibcwkc.d.mts","names":[],"sources":["../src/utils/types.ts","../src/layer/types.ts","../src/layer/backend.ts","../src/layer/map-layer-backend.ts"],"mappings":";;KAAY,aAAa,KAAK,IAAI,YAAY;;;;UCK7B;;WAEN,SAAS;;WAGT,eAAe;;;KAId,eACV,UAAU,wBACV,cAAc,8BAA8B,qCACpC,eAAe,OAAO,gBAAgB,aAAa;;KAGjD,2BACV,UAAU,wBACV,cAAc,+BACZ,oBAAoB,aAAa,MAAM,uBAAuB;;;;UCjBjD,qBAAqB;;EAEpC,SAAS,cAAc,oBAAoB;;EAG3C,cAAc;;;;;cCCH,2BAA2B;mBACrB;mBAEA;mBAEA;;EAGjB,SAAS,cAAc;;EAgBjB,QAAQ,UAAU,iBAAiB,OAAO,IAAI,QAAQ,aAAa;;EA6CnE,cAAc"}
1
+ {"version":3,"file":"map-layer-backend-DMJauecV.d.mts","names":[],"sources":["../src/utils/types.ts","../src/layer/types.ts","../src/layer/backend.ts","../src/layer/map-layer-backend.ts"],"mappings":";;KAAY,aAAa,KAAK,IAAI,YAAY;;;;UCK7B;;WAEN,SAAS;;WAGT,eAAe;;;KAId,eACV,UAAU,wBACV,cAAc,8BAA8B,qCACpC,eAAe,OAAO,gBAAgB,aAAa;;KAGjD,2BACV,UAAU,wBACV,cAAc,+BACZ,oBAAoB,aAAa,MAAM,uBAAuB;;;;UCjBjD,qBAAqB;;EAEpC,SAAS,cAAc,oBAAoB;;EAG3C,cAAc;;;;;cCCH,2BAA2B;mBACrB;mBAEA;mBAEA;;EAGjB,SAAS,cAAc;;EAgBjB,QAAQ,UAAU,iBAAiB,OAAO,IAAI,QAAQ,aAAa;;EA6CnE,cAAc"}
@@ -1,4 +1,5 @@
1
- import { l as ServiceNotFoundError, n as DuplicateServiceError, o as ServiceTagCollisionError, t as assertServiceCompatibility } from "./internal-identity-Cm4-KIUj.mjs";
1
+ import { a as ServiceTagCollisionError, c as ServiceNotFoundError, t as DuplicateServiceError } from "./errors-Dnjhzbt0.mjs";
2
+ import { t as assertServiceCompatibility } from "./internal-identity-DmUpBeeL.mjs";
2
3
  //#region src/layer/map-layer-backend.ts
3
4
  /** Native map-backed Layer backend used by Runtime when no adapter is supplied. */
4
5
  var MapLayerBackend = class {
@@ -49,4 +50,4 @@ var MapLayerBackend = class {
49
50
  //#endregion
50
51
  export { MapLayerBackend as t };
51
52
 
52
- //# sourceMappingURL=map-layer-backend-BodcEeNA.mjs.map
53
+ //# sourceMappingURL=map-layer-backend-gal-mcRv.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-layer-backend-BodcEeNA.mjs","names":[],"sources":["../src/layer/map-layer-backend.ts"],"sourcesContent":["import { assertServiceCompatibility } from './internal-identity'\n\nimport { DuplicateServiceError, ServiceTagCollisionError } from './errors'\n\nimport type { LayerBackend } from './backend'\nimport type { LayerRegistration } from './types'\n\nimport { ServiceNotFoundError, type AnyServiceToken } from '../service'\n\ntype LayerAcquiredValue = Awaited<ReturnType<LayerRegistration['acquire']>>\n\n/** Native map-backed Layer backend used by Runtime when no adapter is supplied. */\nexport class MapLayerBackend implements LayerBackend {\n private readonly providers = new Map<string, LayerRegistration>()\n\n private readonly instances = new Map<string, LayerAcquiredValue>()\n\n private readonly pending = new Map<string, Promise<LayerAcquiredValue>>()\n\n /** Register a provider, rejecting duplicate or colliding Service tags. */\n register(registration: LayerRegistration): void {\n const tag = registration.service.serviceTag\n const existing = this.providers.get(tag)\n\n if (existing) {\n if (existing.service !== registration.service) {\n throw new ServiceTagCollisionError(existing.service, registration.service)\n }\n\n throw new DuplicateServiceError(registration.service)\n }\n\n this.providers.set(tag, registration)\n }\n\n /** Resolve and cache a provider instance by Service tag. */\n async resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>> {\n const tag = token.serviceTag\n const provider = this.providers.get(tag)\n\n if (!provider) {\n throw new ServiceNotFoundError(token)\n }\n\n const validate = (instance: LayerAcquiredValue): InstanceType<T> => {\n assertServiceCompatibility(token, provider.service, instance)\n\n // SAFETY: The provider and requested token share a tag, and compatibility checks verify the registered members before restoring the token-specific instance type.\n return instance as InstanceType<T>\n }\n\n const cached = this.instances.get(tag)\n\n if (cached !== undefined) {\n return validate(cached)\n }\n\n const pending = this.pending.get(tag)\n\n if (pending) {\n return validate(await pending)\n }\n\n const acquisition = Promise.resolve()\n .then(() => provider.acquire())\n .then((instance) => {\n validate(instance)\n this.instances.set(tag, instance)\n\n return instance\n })\n .finally(() => {\n this.pending.delete(tag)\n })\n\n this.pending.set(tag, acquisition)\n\n return validate(await acquisition)\n }\n\n /** Clear pending acquisitions, cached instances, and provider registrations. */\n async disposeAll(): Promise<void> {\n if (this.pending.size > 0) {\n await Promise.allSettled(this.pending.values())\n }\n\n this.instances.clear()\n this.pending.clear()\n this.providers.clear()\n }\n}\n"],"mappings":";;;AAYA,IAAa,kBAAb,MAAqD;CACnD,4BAA6B,IAAI,IAA+B;CAEhE,4BAA6B,IAAI,IAAgC;CAEjE,0BAA2B,IAAI,IAAyC;;CAGxE,SAAS,cAAuC;EAC9C,MAAM,MAAM,aAAa,QAAQ;EACjC,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;EAEvC,IAAI,UAAU;GACZ,IAAI,SAAS,YAAY,aAAa,SACpC,MAAM,IAAI,yBAAyB,SAAS,SAAS,aAAa,OAAO;GAG3E,MAAM,IAAI,sBAAsB,aAAa,OAAO;EACtD;EAEA,KAAK,UAAU,IAAI,KAAK,YAAY;CACtC;;CAGA,MAAM,QAAmC,OAAoC;EAC3E,MAAM,MAAM,MAAM;EAClB,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;EAEvC,IAAI,CAAC,UACH,MAAM,IAAI,qBAAqB,KAAK;EAGtC,MAAM,YAAY,aAAkD;GAClE,2BAA2B,OAAO,SAAS,SAAS,QAAQ;GAG5D,OAAO;EACT;EAEA,MAAM,SAAS,KAAK,UAAU,IAAI,GAAG;EAErC,IAAI,WAAW,KAAA,GACb,OAAO,SAAS,MAAM;EAGxB,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;EAEpC,IAAI,SACF,OAAO,SAAS,MAAM,OAAO;EAG/B,MAAM,cAAc,QAAQ,QAAQ,CAAC,CAClC,WAAW,SAAS,QAAQ,CAAC,CAAC,CAC9B,MAAM,aAAa;GAClB,SAAS,QAAQ;GACjB,KAAK,UAAU,IAAI,KAAK,QAAQ;GAEhC,OAAO;EACT,CAAC,CAAC,CACD,cAAc;GACb,KAAK,QAAQ,OAAO,GAAG;EACzB,CAAC;EAEH,KAAK,QAAQ,IAAI,KAAK,WAAW;EAEjC,OAAO,SAAS,MAAM,WAAW;CACnC;;CAGA,MAAM,aAA4B;EAChC,IAAI,KAAK,QAAQ,OAAO,GACtB,MAAM,QAAQ,WAAW,KAAK,QAAQ,OAAO,CAAC;EAGhD,KAAK,UAAU,MAAM;EACrB,KAAK,QAAQ,MAAM;EACnB,KAAK,UAAU,MAAM;CACvB;AACF"}
1
+ {"version":3,"file":"map-layer-backend-gal-mcRv.mjs","names":[],"sources":["../src/layer/map-layer-backend.ts"],"sourcesContent":["import { assertServiceCompatibility } from './internal-identity'\n\nimport { DuplicateServiceError, ServiceTagCollisionError } from './errors'\n\nimport type { LayerBackend } from './backend'\nimport type { LayerRegistration } from './types'\n\nimport { ServiceNotFoundError, type AnyServiceToken } from '../service'\n\ntype LayerAcquiredValue = Awaited<ReturnType<LayerRegistration['acquire']>>\n\n/** Native map-backed Layer backend used by Runtime when no adapter is supplied. */\nexport class MapLayerBackend implements LayerBackend {\n private readonly providers = new Map<string, LayerRegistration>()\n\n private readonly instances = new Map<string, LayerAcquiredValue>()\n\n private readonly pending = new Map<string, Promise<LayerAcquiredValue>>()\n\n /** Register a provider, rejecting duplicate or colliding Service tags. */\n register(registration: LayerRegistration): void {\n const tag = registration.service.serviceTag\n const existing = this.providers.get(tag)\n\n if (existing) {\n if (existing.service !== registration.service) {\n throw new ServiceTagCollisionError(existing.service, registration.service)\n }\n\n throw new DuplicateServiceError(registration.service)\n }\n\n this.providers.set(tag, registration)\n }\n\n /** Resolve and cache a provider instance by Service tag. */\n async resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>> {\n const tag = token.serviceTag\n const provider = this.providers.get(tag)\n\n if (!provider) {\n throw new ServiceNotFoundError(token)\n }\n\n const validate = (instance: LayerAcquiredValue): InstanceType<T> => {\n assertServiceCompatibility(token, provider.service, instance)\n\n // SAFETY: The provider and requested token share a tag, and compatibility checks verify the registered members before restoring the token-specific instance type.\n return instance as InstanceType<T>\n }\n\n const cached = this.instances.get(tag)\n\n if (cached !== undefined) {\n return validate(cached)\n }\n\n const pending = this.pending.get(tag)\n\n if (pending) {\n return validate(await pending)\n }\n\n const acquisition = Promise.resolve()\n .then(() => provider.acquire())\n .then((instance) => {\n validate(instance)\n this.instances.set(tag, instance)\n\n return instance\n })\n .finally(() => {\n this.pending.delete(tag)\n })\n\n this.pending.set(tag, acquisition)\n\n return validate(await acquisition)\n }\n\n /** Clear pending acquisitions, cached instances, and provider registrations. */\n async disposeAll(): Promise<void> {\n if (this.pending.size > 0) {\n await Promise.allSettled(this.pending.values())\n }\n\n this.instances.clear()\n this.pending.clear()\n this.providers.clear()\n }\n}\n"],"mappings":";;;;AAYA,IAAa,kBAAb,MAAqD;CACnD,4BAA6B,IAAI,IAA+B;CAEhE,4BAA6B,IAAI,IAAgC;CAEjE,0BAA2B,IAAI,IAAyC;;CAGxE,SAAS,cAAuC;EAC9C,MAAM,MAAM,aAAa,QAAQ;EACjC,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;EAEvC,IAAI,UAAU;GACZ,IAAI,SAAS,YAAY,aAAa,SACpC,MAAM,IAAI,yBAAyB,SAAS,SAAS,aAAa,OAAO;GAG3E,MAAM,IAAI,sBAAsB,aAAa,OAAO;EACtD;EAEA,KAAK,UAAU,IAAI,KAAK,YAAY;CACtC;;CAGA,MAAM,QAAmC,OAAoC;EAC3E,MAAM,MAAM,MAAM;EAClB,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;EAEvC,IAAI,CAAC,UACH,MAAM,IAAI,qBAAqB,KAAK;EAGtC,MAAM,YAAY,aAAkD;GAClE,2BAA2B,OAAO,SAAS,SAAS,QAAQ;GAG5D,OAAO;EACT;EAEA,MAAM,SAAS,KAAK,UAAU,IAAI,GAAG;EAErC,IAAI,WAAW,KAAA,GACb,OAAO,SAAS,MAAM;EAGxB,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;EAEpC,IAAI,SACF,OAAO,SAAS,MAAM,OAAO;EAG/B,MAAM,cAAc,QAAQ,QAAQ,CAAC,CAClC,WAAW,SAAS,QAAQ,CAAC,CAAC,CAC9B,MAAM,aAAa;GAClB,SAAS,QAAQ;GACjB,KAAK,UAAU,IAAI,KAAK,QAAQ;GAEhC,OAAO;EACT,CAAC,CAAC,CACD,cAAc;GACb,KAAK,QAAQ,OAAO,GAAG;EACzB,CAAC;EAEH,KAAK,QAAQ,IAAI,KAAK,WAAW;EAEjC,OAAO,SAAS,MAAM,WAAW;CACnC;;CAGA,MAAM,aAA4B;EAChC,IAAI,KAAK,QAAQ,OAAO,GACtB,MAAM,QAAQ,WAAW,KAAK,QAAQ,OAAO,CAAC;EAGhD,KAAK,UAAU,MAAM;EACrB,KAAK,QAAQ,MAAM;EACnB,KAAK,UAAU,MAAM;CACvB;AACF"}
@@ -1,4 +1,4 @@
1
- import { c as RuntimeContextStorage, s as RuntimeContext } from "../index-BFgG9zZC.mjs";
1
+ import { c as RuntimeContextStorage, s as RuntimeContext } from "../index-1NLNdkJy.mjs";
2
2
  import { t as RuntimeContextNotConfiguredError } from "../errors-BXKc7juX.mjs";
3
3
  //#region src/runtime/explicit.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { c as RuntimeContextStorage, s as RuntimeContext } from "../index-BFgG9zZC.mjs";
1
+ import { c as RuntimeContextStorage, s as RuntimeContext } from "../index-1NLNdkJy.mjs";
2
2
  import { t as RuntimeContextNotConfiguredError } from "../errors-BXKc7juX.mjs";
3
3
  //#region src/runtime/node.d.ts
4
4
  /** RuntimeContextStorage backed by Node/Bun async context propagation. */
@@ -0,0 +1,270 @@
1
+ import { a as ServiceTagCollisionError, l as ServiceRuntimeNotConfiguredError, r as LayerGeneratorYieldError, t as DuplicateServiceError } from "./errors-Dnjhzbt0.mjs";
2
+ import { a as runRuntimeContext, i as makeRuntimeContext, n as currentRuntimeContext, o as setDefaultRuntimeContextStorage, r as getRuntimeContext } from "./context-B4yO5LaH.mjs";
3
+ import { nodeRuntimeContextStorage } from "./runtime/node.mjs";
4
+ //#region src/runtime/default.ts
5
+ /** The Node/Bun storage used by the main Runtime entrypoint. */
6
+ const defaultRuntimeContextStorage = nodeRuntimeContextStorage;
7
+ setDefaultRuntimeContextStorage(defaultRuntimeContextStorage);
8
+ //#endregion
9
+ //#region src/service/runtime.ts
10
+ /** Provides the resolver context used by Service tokens during execution. */
11
+ var ServiceRuntime = class ServiceRuntime {
12
+ /**
13
+ * Run a callback with a resolver available to `yield* Service` expressions.
14
+ *
15
+ * The context is scoped to the callback and is restored afterward.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const value = ServiceRuntime.run(resolver, () => {
20
+ * return ServiceRuntime.resolve(Database)
21
+ * })
22
+ * ```
23
+ */
24
+ static run(resolver, program, storage = defaultRuntimeContextStorage) {
25
+ const current = getRuntimeContext(storage);
26
+ const context = makeRuntimeContext(resolver, current?.scope, current?.resolver === resolver ? current.resolutionPath : [], current?.signal);
27
+ return runRuntimeContext(storage, context, program);
28
+ }
29
+ /** Return the resolver active in the current execution context. */
30
+ static current() {
31
+ let context;
32
+ try {
33
+ context = currentRuntimeContext();
34
+ } catch {
35
+ throw new ServiceRuntimeNotConfiguredError();
36
+ }
37
+ if (!context.resolver) throw new ServiceRuntimeNotConfiguredError();
38
+ return context.resolver;
39
+ }
40
+ /** Resolve a Service token using the active resolver. */
41
+ static async resolve(token) {
42
+ return await ServiceRuntime.current().resolve(token);
43
+ }
44
+ };
45
+ //#endregion
46
+ //#region src/service/service.ts
47
+ /**
48
+ * Declare a class-backed Service with a stable string-literal identity.
49
+ *
50
+ * The returned class is simultaneously the implementation type, the runtime
51
+ * dependency token, and the value yielded by `yield*` in an Effect generator.
52
+ * The explicit self type preserves exact instance inference, while the second
53
+ * call captures the tag as a literal for Layer composition and diagnostics.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * class Database extends Service<Database>()('Database') {
58
+ * query(): string {
59
+ * return 'ok'
60
+ * }
61
+ * }
62
+ *
63
+ * const database = yield* Database
64
+ * database.query()
65
+ * ```
66
+ *
67
+ * @typeParam Self The instance type implemented by the declared Service.
68
+ */
69
+ function Service() {
70
+ return function(tag) {
71
+ if (tag.length === 0) throw new TypeError("Service tags must not be empty");
72
+ class BaseService {
73
+ /** The stable logical identity used by Layers and resolver backends. */
74
+ static serviceTag = tag;
75
+ /**
76
+ * Type-check a structural implementation of this Service.
77
+ *
78
+ * This is an identity helper. It returns the supplied value unchanged
79
+ * and does not invoke a constructor or modify its prototype.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * class Database extends Service<Database>()('Database') {
84
+ * query(sql: string): string {
85
+ * return sql
86
+ * }
87
+ * }
88
+ *
89
+ * const database = Database.of({
90
+ * query: (sql) => `Result: ${sql}`
91
+ * })
92
+ *
93
+ * database.query('SELECT 1')
94
+ * // 'Result: SELECT 1'
95
+ * // database is the original object, not an instance of Database
96
+ * ```
97
+ */
98
+ static of(implementation) {
99
+ return implementation;
100
+ }
101
+ /** Resolve this Service from the resolver active in the current runtime. */
102
+ static async *[Symbol.asyncIterator]() {
103
+ return await ServiceRuntime.resolve(this);
104
+ }
105
+ }
106
+ return BaseService;
107
+ };
108
+ }
109
+ //#endregion
110
+ //#region src/layer/internal.ts
111
+ const runLayerGenerator = async (service, factory) => {
112
+ const iterator = factory();
113
+ const state = await iterator.next();
114
+ if (!state.done) try {
115
+ await iterator.return(void 0);
116
+ } finally {
117
+ throw new LayerGeneratorYieldError(service);
118
+ }
119
+ return state.value;
120
+ };
121
+ //#endregion
122
+ //#region src/layer/layer.ts
123
+ /**
124
+ * Declarative collection of Service providers.
125
+ *
126
+ * A Layer describes how to acquire implementations; it does not execute
127
+ * providers until a `Runtime` is created. Use `merge` to compose distinct
128
+ * providers and `override` when replacing an existing provider intentionally.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * const AppLive = Layer.merge(
133
+ * Layer.succeed(Database, database),
134
+ * Layer.make(UserRepository)
135
+ * )
136
+ *
137
+ * const runtime = await Runtime.make(AppLive, backend)
138
+ * ```
139
+ */
140
+ var Layer = class Layer {
141
+ /** The provider registrations retained by this Layer. */
142
+ providers;
143
+ constructor(providers) {
144
+ this.providers = Object.freeze([...providers]);
145
+ }
146
+ static make(service, acquire) {
147
+ const defaultAcquire = () => {
148
+ return new service();
149
+ };
150
+ const normalizedAcquire = normalizeAcquire(acquire ?? defaultAcquire);
151
+ return new Layer([{
152
+ service,
153
+ acquire: normalizedAcquire
154
+ }]);
155
+ }
156
+ /** Create a Layer from an already-constructed Service instance. */
157
+ static succeed(service, instance) {
158
+ const normalizedAcquire = normalizeAcquire(() => instance);
159
+ return new Layer([{
160
+ service,
161
+ acquire: normalizedAcquire
162
+ }]);
163
+ }
164
+ /** Define a provider with Runtime-root cleanup. */
165
+ static scoped(service, acquire, release) {
166
+ return new Layer([{
167
+ service,
168
+ acquire: normalizeAcquire(acquire),
169
+ release: (instance, outcome) => {
170
+ return release(instance, outcome);
171
+ }
172
+ }]);
173
+ }
174
+ /** Define a provider whose acquisition can yield contextual Services. */
175
+ static scopedGen(service, factory, release) {
176
+ return new Layer([{
177
+ service,
178
+ acquire: () => runLayerGenerator(service, factory),
179
+ release: (instance, outcome) => {
180
+ return release(instance, outcome);
181
+ }
182
+ }]);
183
+ }
184
+ /** Define a provider whose acquisition can yield contextual Services. */
185
+ static gen(service, factory) {
186
+ return new Layer([{
187
+ service,
188
+ acquire: () => runLayerGenerator(service, factory)
189
+ }]);
190
+ }
191
+ /** Compose Layers without replacing providers. */
192
+ static merge(...layers) {
193
+ const providers = /* @__PURE__ */ new Map();
194
+ for (const layer of layers) for (const provider of layer.providers) {
195
+ const service = provider.service;
196
+ const existing = providers.get(service.serviceTag);
197
+ if (existing) {
198
+ if (existing.service !== service) throw new ServiceTagCollisionError(existing.service, service);
199
+ throw new DuplicateServiceError(service);
200
+ }
201
+ providers.set(service.serviceTag, provider);
202
+ }
203
+ return new Layer([...providers.values()]);
204
+ }
205
+ /** Mark a Layer composition root as complete without changing its runtime value. */
206
+ static complete(layer) {
207
+ return layer;
208
+ }
209
+ static override(base, ...overrides) {
210
+ const providers = /* @__PURE__ */ new Map();
211
+ for (const provider of base.providers) providers.set(provider.service.serviceTag, provider);
212
+ for (const layer of overrides) for (const provider of layer.providers) providers.set(provider.service.serviceTag, provider);
213
+ return new Layer([...providers.values()]);
214
+ }
215
+ };
216
+ const normalizeAcquire = (acquire) => () => {
217
+ return acquire();
218
+ };
219
+ //#endregion
220
+ //#region src/runtime/signal.ts
221
+ const neverAbortedSignal = new AbortController().signal;
222
+ /** Link caller, Runtime and shutdown signals without owning the caller's controller. */
223
+ const linkAbortSignals = (...signals) => {
224
+ const active = signals.filter((signal) => signal !== void 0);
225
+ if (active.length === 0) return {
226
+ signal: neverAbortedSignal,
227
+ dispose: () => {}
228
+ };
229
+ if (active.length === 1) return {
230
+ signal: active[0],
231
+ dispose: () => {}
232
+ };
233
+ const controller = new AbortController();
234
+ const listeners = [];
235
+ let disposed = false;
236
+ const dispose = () => {
237
+ if (disposed) return;
238
+ disposed = true;
239
+ for (const [source, listener] of listeners) source.removeEventListener("abort", listener);
240
+ listeners.length = 0;
241
+ };
242
+ const abortFrom = (source) => {
243
+ if (controller.signal.aborted) return;
244
+ controller.abort(source.reason);
245
+ dispose();
246
+ };
247
+ for (const source of active) {
248
+ if (source.aborted) {
249
+ abortFrom(source);
250
+ break;
251
+ }
252
+ const listener = () => abortFrom(source);
253
+ listeners.push([source, listener]);
254
+ source.addEventListener("abort", listener, { once: true });
255
+ }
256
+ return {
257
+ signal: controller.signal,
258
+ dispose
259
+ };
260
+ };
261
+ /** Return the current cooperative-cancellation signal. */
262
+ const currentAbortSignal = () => currentRuntimeContext().signal ?? neverAbortedSignal;
263
+ /** Yieldable access to the signal of the current Runtime execution. */
264
+ const CurrentAbortSignal = { *[Symbol.iterator]() {
265
+ return currentAbortSignal();
266
+ } };
267
+ //#endregion
268
+ export { ServiceRuntime as a, Service as i, linkAbortSignals as n, defaultRuntimeContextStorage as o, Layer as r, CurrentAbortSignal as t };
269
+
270
+ //# sourceMappingURL=signal-Cl9tqGyX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-Cl9tqGyX.mjs","names":["Constructor"],"sources":["../src/runtime/default.ts","../src/service/runtime.ts","../src/service/service.ts","../src/layer/internal.ts","../src/layer/layer.ts","../src/runtime/signal.ts"],"sourcesContent":["import { nodeRuntimeContextStorage } from './node'\n\nimport { setDefaultRuntimeContextStorage } from './context'\n\n/** The Node/Bun storage used by the main Runtime entrypoint. */\nexport const defaultRuntimeContextStorage = nodeRuntimeContextStorage\n\nsetDefaultRuntimeContextStorage(defaultRuntimeContextStorage)\n","import { ServiceRuntimeNotConfiguredError } from './errors'\n\nimport {\n currentRuntimeContext,\n getRuntimeContext,\n makeRuntimeContext,\n runRuntimeContext\n} from '../runtime/context'\n\nimport { defaultRuntimeContextStorage } from '../runtime/default'\n\nimport type { AnyServiceToken } from './types'\n\nimport type { RuntimeContextStorage } from '../runtime/context'\n\n/** Resolves class-backed Service tokens for a runtime execution. */\nexport interface ServiceResolver {\n /** Resolve a token to its corresponding Service instance. */\n resolve<T extends AnyServiceToken>(token: T): InstanceType<T> | PromiseLike<InstanceType<T>>\n}\n\n/** Provides the resolver context used by Service tokens during execution. */\nexport class ServiceRuntime {\n /**\n * Run a callback with a resolver available to `yield* Service` expressions.\n *\n * The context is scoped to the callback and is restored afterward.\n *\n * @example\n * ```ts\n * const value = ServiceRuntime.run(resolver, () => {\n * return ServiceRuntime.resolve(Database)\n * })\n * ```\n */\n static run<A>(\n resolver: ServiceResolver,\n program: () => A,\n storage: RuntimeContextStorage = defaultRuntimeContextStorage\n ): A {\n const current = getRuntimeContext(storage)\n const context = makeRuntimeContext(\n resolver,\n current?.scope,\n current?.resolver === resolver ? current.resolutionPath : [],\n current?.signal\n )\n\n return runRuntimeContext(storage, context, program)\n }\n\n /** Return the resolver active in the current execution context. */\n static current(): ServiceResolver {\n let context\n\n try {\n context = currentRuntimeContext()\n } catch {\n throw new ServiceRuntimeNotConfiguredError()\n }\n\n if (!context.resolver) {\n throw new ServiceRuntimeNotConfiguredError()\n }\n\n return context.resolver\n }\n\n /** Resolve a Service token using the active resolver. */\n static async resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>> {\n const resolver = ServiceRuntime.current()\n\n return await resolver.resolve(token)\n }\n}\n","import { ServiceRuntime } from './runtime'\n\nimport type { ServiceRequirement } from '../effect/types'\n\nimport type {\n AnyService,\n AnyServiceToken,\n ServiceClass,\n ServiceContract,\n ServiceIdentity,\n ServiceIdentityTypeId,\n ServiceInstance,\n ServiceRequirements,\n ServiceTag,\n ServiceToken,\n ServiceTokenOf\n} from './types'\n\ntype ServiceTagLiteral<Tag extends string> = string extends Tag\n ? never\n : Tag extends ''\n ? never\n : Tag\n\ninterface ServiceFactory<Self> {\n <const Tag extends string>(\n tag: ServiceTagLiteral<Tag>\n ): (abstract new () => ServiceIdentity<Tag>) & {\n readonly name: string\n readonly serviceTag: Tag\n } & {\n readonly of: Service.FactoryOf<Self, Tag>\n readonly [Symbol.asyncIterator]: (\n this: ServiceToken<Tag, Self & ServiceIdentity<Tag>>\n ) => AsyncGenerator<ServiceRequirement<Self>, Self, unknown>\n }\n}\n\n/**\n * Declare a class-backed Service with a stable string-literal identity.\n *\n * The returned class is simultaneously the implementation type, the runtime\n * dependency token, and the value yielded by `yield*` in an Effect generator.\n * The explicit self type preserves exact instance inference, while the second\n * call captures the tag as a literal for Layer composition and diagnostics.\n *\n * @example\n * ```ts\n * class Database extends Service<Database>()('Database') {\n * query(): string {\n * return 'ok'\n * }\n * }\n *\n * const database = yield* Database\n * database.query()\n * ```\n *\n * @typeParam Self The instance type implemented by the declared Service.\n */\nexport function Service<Self>(): ServiceFactory<Self> {\n return function <const Tag extends string>(tag: ServiceTagLiteral<Tag>) {\n if (tag.length === 0) {\n throw new TypeError('Service tags must not be empty')\n }\n\n abstract class BaseService implements ServiceIdentity<Tag> {\n /** The stable logical identity used by Layers and resolver backends. */\n static readonly serviceTag: Tag = tag\n declare readonly [ServiceIdentityTypeId]: Tag\n\n /**\n * Type-check a structural implementation of this Service.\n *\n * This is an identity helper. It returns the supplied value unchanged\n * and does not invoke a constructor or modify its prototype.\n *\n * @example\n * ```ts\n * class Database extends Service<Database>()('Database') {\n * query(sql: string): string {\n * return sql\n * }\n * }\n *\n * const database = Database.of({\n * query: (sql) => `Result: ${sql}`\n * })\n *\n * database.query('SELECT 1')\n * // 'Result: SELECT 1'\n * // database is the original object, not an instance of Database\n * ```\n */\n static of(this: void, implementation: ServiceContract<Self & ServiceIdentity<Tag>>): Self {\n // SAFETY: ServiceContract removes only the phantom marker; this boundary restores Self.\n return implementation as Self\n }\n\n /** Resolve this Service from the resolver active in the current runtime. */\n // oxlint-disable-next-line require-yield\n static async *[Symbol.asyncIterator](\n this: ServiceToken<Tag, Self & ServiceIdentity<Tag>>\n ): AsyncGenerator<ServiceRequirement<Self>, Self, unknown> {\n return await ServiceRuntime.resolve(this)\n }\n }\n\n return BaseService\n }\n}\n\n/** Type-level aliases for Service tokens and their instance contracts. */\nexport declare namespace Service {\n /** The widened Service instance constraint. */\n export type Any = AnyService\n\n /** A class-backed Service token with a stable tag and instance contract. */\n export type Token<Tag extends string = string, Instance extends AnyService = any> = ServiceToken<\n Tag,\n Instance\n >\n\n /** A constructible Service class with a stable tag and instance contract. */\n export type Class<\n Tag extends string = string,\n Instance extends AnyService = AnyService\n > = ServiceClass<Tag, Instance>\n\n /** Extract the instance represented by a Service token. */\n export type Instance<T extends AnyServiceToken> = ServiceInstance<T>\n\n /** Extract the stable tag represented by a Service instance. */\n export type Tag<S extends AnyService> = ServiceTag<S>\n\n /** A branded Service instance identity with a stable tag. */\n export type Identity<Tag extends string = string> = ServiceIdentity<Tag>\n\n /** Remove the internal identity marker from a Service implementation contract. */\n export type Contract<S extends AnyService> = ServiceContract<S>\n\n /** Extract the Service token represented by a branded Service instance. */\n export type TokenOf<S extends AnyService> = ServiceTokenOf<S>\n\n /** Declaration bridge for the recursive structural `Service.of` signature. */\n export type FactoryOf<Self, Tag extends string> = (\n this: void,\n implementation: ServiceContract<Self & ServiceIdentity<Tag>>\n ) => Self\n\n /** Extract Effect Service requirements from a Service instance. */\n export type Requirements<S extends AnyService> = ServiceRequirements<S>\n}\n","import { LayerGeneratorYieldError } from './errors'\n\nimport type { ServiceRequirement } from '../effect/types'\nimport type { ServiceClass } from '../service'\n\nimport type { LayerGenerator } from './types'\n\nexport const runLayerGenerator = async <\n S extends ServiceClass<any, any>,\n Yield extends ServiceRequirement<unknown>\n>(\n service: S,\n factory: LayerGenerator<S, Yield>\n): Promise<InstanceType<S>> => {\n const iterator = factory()\n\n const state = await iterator.next()\n\n if (!state.done) {\n try {\n // SAFETY: The iterator is closed only to discard an invalid yield; its return value is ignored.\n await iterator.return(undefined as never)\n } finally {\n // oxlint-disable-next-line no-unsafe-finally\n throw new LayerGeneratorYieldError(service)\n }\n }\n\n // SAFETY: The public generator boundary accepts only the requested Service contract.\n return state.value as InstanceType<S>\n}\n","import type { ServiceRequirement } from '../effect/types'\nimport type { AnyService, ServiceClass, ServiceContract, ServiceRequirements } from '../service'\nimport type { ScopeOutcome } from '../scope'\nimport type { Covariant, Invariant } from '../internal/variance'\nimport type { MaybePromise } from '../utils/types'\n\nimport { DuplicateServiceError, ServiceTagCollisionError } from './errors'\nimport { runLayerGenerator } from './internal'\n\nimport type {\n LayerInput,\n CompleteInput,\n LayerResult,\n MergeResult,\n OverrideLayerResult,\n ValidateLayerInput,\n ValidateLayerTuple,\n ValidateOverrides,\n ProvidedEnvironment,\n RequiredEnvironment\n} from './inference'\nimport type { ProviderEntry } from './metadata'\nimport type { LayerGenerator, LayerGeneratorRequirements, LayerRegistration } from './types'\n\ndeclare const LayerTypeId: unique symbol\n\ninterface LayerVariance<in out Provided, out Required> {\n readonly _Provided: Invariant<Provided>\n readonly _Required: Covariant<Required>\n}\n\ninterface LayerProvider extends LayerRegistration {\n /** Provider storage deliberately erases the concrete instance type. */\n // oxlint-disable-next-line anti-slop/no-unknown-parameters\n readonly release?: (instance: unknown, outcome: ScopeOutcome) => MaybePromise<void>\n}\n\n/** A Service class whose constructor can be called without arguments. */\ntype DefaultConstructibleServiceClass<\n Tag extends string = string,\n Instance extends AnyService = AnyService\n> = ServiceClass<Tag, Instance> & (new () => Instance)\n\n/**\n * Declarative collection of Service providers.\n *\n * A Layer describes how to acquire implementations; it does not execute\n * providers until a `Runtime` is created. Use `merge` to compose distinct\n * providers and `override` when replacing an existing provider intentionally.\n *\n * @example\n * ```ts\n * const AppLive = Layer.merge(\n * Layer.succeed(Database, database),\n * Layer.make(UserRepository)\n * )\n *\n * const runtime = await Runtime.make(AppLive, backend)\n * ```\n */\nexport class Layer<\n in out Provided extends AnyService = AnyService,\n out Required extends AnyService = AnyService\n> {\n declare readonly [LayerTypeId]: LayerVariance<Provided, Required>\n\n /** The provider registrations retained by this Layer. */\n readonly providers: readonly LayerProvider[]\n\n private constructor(providers: readonly LayerProvider[]) {\n this.providers = Object.freeze([...providers])\n }\n\n /** Create a Layer that lazily acquires a Service instance. */\n static make<S extends DefaultConstructibleServiceClass<any, any>>(\n service: S\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n\n static make<S extends ServiceClass<any, any>>(\n service: S,\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>>>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n\n static make<S extends ServiceClass<any, any>>(\n service: S,\n acquire?: () => MaybePromise<ServiceContract<InstanceType<S>>>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>> {\n const defaultAcquire = (): InstanceType<S> => {\n // SAFETY: The no-argument overload constrains `service` to a default constructible class.\n const Constructor = service as new () => InstanceType<S>\n\n return new Constructor()\n }\n\n const normalizedAcquire = normalizeAcquire<S>(acquire ?? defaultAcquire)\n\n // SAFETY: Runtime storage erases only the concrete provider metadata; the public constructor result restores its typed provenance.\n return new Layer([\n {\n service,\n acquire: normalizedAcquire\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n }\n\n /** Create a Layer from an already-constructed Service instance. */\n static succeed<S extends ServiceClass<any, any>>(\n service: S,\n instance: ServiceContract<InstanceType<S>>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>> {\n const normalizedAcquire = normalizeAcquire<S>(() => instance)\n\n // SAFETY: The structural instance has been checked against the requested Service contract.\n return new Layer([\n {\n service,\n acquire: normalizedAcquire\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n }\n\n /** Define a provider with Runtime-root cleanup. */\n static scoped<S extends ServiceClass<any, any>>(\n service: S,\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>>>,\n release: (instance: InstanceType<S>, outcome: ScopeOutcome) => MaybePromise<void>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>> {\n // SAFETY: The public callbacks constrain acquisition and release to the requested Service.\n return new Layer([\n {\n service,\n acquire: normalizeAcquire<S>(acquire),\n release: (instance, outcome) => {\n // SAFETY: The backend invokes release with the instance acquired for this token.\n return release(instance as InstanceType<S>, outcome)\n }\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n }\n\n /** Define a provider whose acquisition can yield contextual Services. */\n static scopedGen<S extends ServiceClass<any, any>, Yield extends ServiceRequirement<unknown>>(\n service: S,\n factory: LayerGenerator<S, Yield>,\n release: (instance: InstanceType<S>, outcome: ScopeOutcome) => MaybePromise<void>\n ): LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>> {\n // SAFETY: The generator and release callback are checked against the requested Service.\n return new Layer([\n {\n service,\n acquire: () => runLayerGenerator(service, factory),\n release: (instance, outcome) => {\n // SAFETY: The backend invokes release with the instance acquired for this token.\n return release(instance as InstanceType<S>, outcome)\n }\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>>\n }\n\n /** Define a provider whose acquisition can yield contextual Services. */\n static gen<S extends ServiceClass<any, any>, Yield extends ServiceRequirement<unknown>>(\n service: S,\n factory: LayerGenerator<S, Yield>\n ): LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>> {\n // SAFETY: The generator result is normalized to the requested Service at the runtime boundary.\n return new Layer([\n {\n service,\n acquire: () => runLayerGenerator(service, factory)\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>>\n }\n\n /** Compose Layers without replacing providers. */\n static merge<const Layers extends readonly LayerInput[]>(\n ...layers: Layers & ValidateLayerTuple<Layers>\n ): MergeResult<Layers> {\n const providers = new Map<string, LayerProvider>()\n\n for (const layer of layers) {\n for (const provider of layer.providers) {\n const service = provider.service\n const existing = providers.get(service.serviceTag)\n\n if (existing) {\n if (existing.service !== service) {\n throw new ServiceTagCollisionError(existing.service, service)\n }\n\n throw new DuplicateServiceError(service)\n }\n\n providers.set(service.serviceTag, provider)\n }\n }\n\n // SAFETY: The heterogeneous provider list is erased only at this internal storage boundary.\n return new Layer([...providers.values()]) as MergeResult<Layers>\n }\n\n /** Mark a Layer composition root as complete without changing its runtime value. */\n static complete<L extends LayerInput>(layer: L & CompleteInput<L>): L {\n return layer\n }\n\n /** Replace providers in a base Layer, using tag identity and compatible contracts. */\n static override<Base extends LayerInput>(\n base: Base & ValidateLayerInput<Base>\n ): OverrideLayerResult<Base, readonly []>\n\n static override<\n Base extends LayerInput,\n const Overrides extends readonly [LayerInput, ...LayerInput[]]\n >(\n base: Base & ValidateLayerInput<Base>,\n ...overrides: Overrides & ValidateOverrides<Base, Overrides>\n ): OverrideLayerResult<Base, Overrides>\n\n static override<Base extends LayerInput, const Overrides extends readonly LayerInput[]>(\n base: Base & ValidateLayerInput<Base>,\n ...overrides: Overrides extends readonly [LayerInput, ...LayerInput[]]\n ? never\n : Overrides & ValidateOverrides<Base, Overrides>\n ): OverrideLayerResult<Base, Overrides>\n\n static override(base: LayerInput, ...overrides: readonly LayerInput[]): Layer<any, any> {\n const providers = new Map<string, LayerProvider>()\n\n for (const provider of base.providers) {\n providers.set(provider.service.serviceTag, provider)\n }\n\n for (const layer of overrides) {\n for (const provider of layer.providers) {\n providers.set(provider.service.serviceTag, provider)\n }\n }\n\n // SAFETY: Runtime provider replacement preserves the computed override metadata.\n return new Layer([...providers.values()]) as Layer<any, any>\n }\n}\n\nconst normalizeAcquire =\n <S extends ServiceClass<any, any>>(\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>>>\n ): (() => MaybePromise<InstanceType<S>>) =>\n () => {\n // SAFETY: ServiceContract removes only the declaration-only identity; runtime values are unchanged.\n return acquire() as MaybePromise<InstanceType<S>>\n }\n\n/** Type-level aliases for inspecting Layer environments and completeness. */\nexport declare namespace Layer {\n /** The widened Layer shape accepted by generic Layer infrastructure. */\n export type Any = LayerInput\n\n /** Extract the branded Service instances provided by a Layer. */\n export type Provided<L extends LayerInput> = ProvidedEnvironment<L>\n\n /** Extract the external Service requirements of a Layer. */\n export type Required<L extends LayerInput> = RequiredEnvironment<L>\n\n /** Extract the Services still missing from a Layer composition. */\n export type Missing<L extends LayerInput> = RequiredEnvironment<L>\n\n /** Validate a Layer's requirements and input shape. */\n export type Complete<L extends LayerInput> = CompleteInput<L>\n}\n","import { currentRuntimeContext } from './context'\n\nconst neverAbortedSignal = new AbortController().signal\n\ntype SignalListener = readonly [AbortSignal, () => void]\n\nexport type AbortSignalLink = {\n readonly signal: AbortSignal\n readonly dispose: () => void\n}\n\n/** Link caller, Runtime and shutdown signals without owning the caller's controller. */\nexport const linkAbortSignals = (\n ...signals: readonly (AbortSignal | undefined)[]\n): AbortSignalLink => {\n const active = signals.filter((signal): signal is AbortSignal => signal !== undefined)\n\n if (active.length === 0) {\n return { signal: neverAbortedSignal, dispose: () => {} }\n }\n\n if (active.length === 1) {\n return { signal: active[0]!, dispose: () => {} }\n }\n\n const controller = new AbortController()\n const listeners: SignalListener[] = []\n let disposed = false\n\n const dispose = (): void => {\n if (disposed) {\n return\n }\n\n disposed = true\n\n for (const [source, listener] of listeners) {\n source.removeEventListener('abort', listener)\n }\n\n listeners.length = 0\n }\n\n const abortFrom = (source: AbortSignal): void => {\n if (controller.signal.aborted) {\n return\n }\n\n controller.abort(source.reason)\n dispose()\n }\n\n for (const source of active) {\n if (source.aborted) {\n abortFrom(source)\n break\n }\n\n const listener = (): void => abortFrom(source)\n listeners.push([source, listener])\n source.addEventListener('abort', listener, { once: true })\n }\n\n return { signal: controller.signal, dispose }\n}\n\n/** Return the current cooperative-cancellation signal. */\nexport const currentAbortSignal = (): AbortSignal =>\n currentRuntimeContext().signal ?? neverAbortedSignal\n\n/** Yieldable access to the signal of the current Runtime execution. */\nexport const CurrentAbortSignal = {\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, AbortSignal, unknown> {\n return currentAbortSignal()\n }\n} as const\n"],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ import { H as ServiceToken, I as ServiceIdentity, b as Service, j as ServiceRequirement } from "./index-1NLNdkJy.mjs";
2
+ import { S as LayerResult, w as ProviderEntry } from "./index-CYAgpM_5.mjs";
3
+ import { t as CurrentAbortSignal } from "./index-BJFBEsm5.mjs";
4
+ //#region src/standard-services/index.d.ts
5
+ declare const Clock_base: (abstract new () => ServiceIdentity<"Clock">) & {
6
+ readonly name: string;
7
+ readonly serviceTag: "Clock";
8
+ } & {
9
+ readonly of: Service.FactoryOf<Clock, "Clock">;
10
+ readonly [Symbol.asyncIterator]: (this: ServiceToken<"Clock", Clock & ServiceIdentity<"Clock">>) => AsyncGenerator<ServiceRequirement<Clock>, Clock, unknown>;
11
+ };
12
+ /** Host-backed time and waiting service. */
13
+ declare class Clock extends Clock_base {
14
+ now(): Date;
15
+ sleep(milliseconds: number): Promise<void>;
16
+ }
17
+ /** The default host Clock provider. */
18
+ declare const ClockLive: LayerResult<ProviderEntry<Clock, never>>;
19
+ /** Deterministic Clock implementation for tests. */
20
+ declare class ClockTest implements Service.Contract<Clock> {
21
+ private currentTime;
22
+ private readonly waiters;
23
+ constructor(initial?: Date | number);
24
+ now(): Date;
25
+ setTime(value: Date | number): void;
26
+ advance(milliseconds: number): void;
27
+ sleep(milliseconds: number): Promise<void>;
28
+ static layer(initial?: Date | number): LayerResult<ProviderEntry<Clock, never>>;
29
+ private flushWaiters;
30
+ }
31
+ declare const ClockTestLayer: (initial?: Date | number) => LayerResult<ProviderEntry<Clock, never>>;
32
+ declare const Random_base: (abstract new () => ServiceIdentity<"Random">) & {
33
+ readonly name: string;
34
+ readonly serviceTag: "Random";
35
+ } & {
36
+ readonly of: Service.FactoryOf<Random, "Random">;
37
+ readonly [Symbol.asyncIterator]: (this: ServiceToken<"Random", Random & ServiceIdentity<"Random">>) => AsyncGenerator<ServiceRequirement<Random>, Random, unknown>;
38
+ };
39
+ /** Host-backed pseudo-random number service. */
40
+ declare class Random extends Random_base {
41
+ next(): number;
42
+ nextInt(maxExclusive: number): number;
43
+ }
44
+ /** The default host Random provider. */
45
+ declare const RandomLive: LayerResult<ProviderEntry<Random, never>>;
46
+ /** Reproducible pseudo-random implementation with isolated mutable state. */
47
+ declare class RandomSeeded implements Service.Contract<Random> {
48
+ private state;
49
+ constructor(seed: number);
50
+ next(): number;
51
+ nextInt(maxExclusive: number): number;
52
+ static layer(seed: number): LayerResult<ProviderEntry<Random, never>>;
53
+ }
54
+ declare const RandomSeededLayer: (seed: number) => LayerResult<ProviderEntry<Random, never>>;
55
+ type LoggerLevel = 'debug' | 'info' | 'warn' | 'error';
56
+ type LoggerEvent = {
57
+ level: LoggerLevel;
58
+ message: string;
59
+ data?: LoggerData;
60
+ };
61
+ type LoggerData = string | number | boolean | bigint | null | readonly LoggerData[] | {
62
+ readonly [key: string]: LoggerData;
63
+ };
64
+ declare const Logger_base: (abstract new () => ServiceIdentity<"Logger">) & {
65
+ readonly name: string;
66
+ readonly serviceTag: "Logger";
67
+ } & {
68
+ readonly of: Service.FactoryOf<Logger, "Logger">;
69
+ readonly [Symbol.asyncIterator]: (this: ServiceToken<"Logger", Logger & ServiceIdentity<"Logger">>) => AsyncGenerator<ServiceRequirement<Logger>, Logger, unknown>;
70
+ };
71
+ /** Structured host logger bridge. */
72
+ declare class Logger extends Logger_base {
73
+ log(event: LoggerEvent): void;
74
+ log(level: LoggerLevel, message: string, data?: LoggerData): void;
75
+ debug(message: string, data?: LoggerData): void;
76
+ info(message: string, data?: LoggerData): void;
77
+ warn(message: string, data?: LoggerData): void;
78
+ error(message: string, data?: LoggerData): void;
79
+ }
80
+ /** The default host Logger provider. */
81
+ declare const LoggerLive: LayerResult<ProviderEntry<Logger, never>>;
82
+ /** Ordered in-memory Logger implementation for tests. */
83
+ declare class LoggerTest implements Service.Contract<Logger> {
84
+ readonly events: LoggerEvent[];
85
+ log(event: LoggerEvent): void;
86
+ log(level: LoggerLevel, message: string, data?: LoggerData): void;
87
+ debug(message: string, data?: LoggerData): void;
88
+ info(message: string, data?: LoggerData): void;
89
+ warn(message: string, data?: LoggerData): void;
90
+ error(message: string, data?: LoggerData): void;
91
+ clear(): void;
92
+ static make(): {
93
+ logger: LoggerTest;
94
+ layer: LayerResult<ProviderEntry<Logger, never>>;
95
+ };
96
+ static layer(logger?: LoggerTest): LayerResult<ProviderEntry<Logger, never>>;
97
+ }
98
+ declare const LoggerTestLayer: () => LayerResult<ProviderEntry<Logger, never>>;
99
+ declare const CurrentRequest_base: (abstract new () => ServiceIdentity<"CurrentRequest">) & {
100
+ readonly name: string;
101
+ readonly serviceTag: "CurrentRequest";
102
+ } & {
103
+ readonly of: Service.FactoryOf<CurrentRequest, "CurrentRequest">;
104
+ readonly [Symbol.asyncIterator]: (this: ServiceToken<"CurrentRequest", CurrentRequest & ServiceIdentity<"CurrentRequest">>) => AsyncGenerator<ServiceRequirement<CurrentRequest>, CurrentRequest, unknown>;
105
+ };
106
+ /** Execution-local request value carried by a normal Service provider. */
107
+ declare class CurrentRequest extends CurrentRequest_base {
108
+ readonly value: unknown;
109
+ readonly request: unknown;
110
+ constructor(value: unknown);
111
+ static layer(value: unknown): LayerResult<ProviderEntry<CurrentRequest, never>>;
112
+ }
113
+ declare const CurrentRequestLayer: (value: unknown) => LayerResult<ProviderEntry<CurrentRequest, never>>;
114
+ //#endregion
115
+ export { Clock, ClockLive, ClockTest, ClockTestLayer, CurrentAbortSignal, CurrentRequest, CurrentRequestLayer, Logger, LoggerData, LoggerEvent, LoggerLevel, LoggerLive, LoggerTest, LoggerTestLayer, Random, RandomLive, RandomSeeded, RandomSeededLayer };
116
+ //# sourceMappingURL=standard-services.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-services.d.mts","names":[],"sources":["../src/standard-services/index.ts"],"mappings":";;;;;;;;;;;;cAaa,cAAc;EACzB,OAAO;EAIP,MAAM,uBAAuB;;;cAOlB,WAAS,YAAA,cAAA;;cAQT,qBAAqB,QAAQ,SAAS;UACzC;mBAES;EAEL,YAAA,UAAS;EAQrB,OAAO;EAIP,QAAQ,OAAO;EAWf,QAAQ;EAMR,MAAM,uBAAuB;SAStB,MAAM,UAAS,gBAAiB,YAAA,cAAA;UAI/B;;cAYG,iBAAkB,UAAS,kBAAiB,YAAA,cAAA;;;;;;;;;cAG5C,eAAe;EAC1B;EAIA,QAAQ;;;cAUG,YAAU,YAAA,cAAA;;cAGV,wBAAwB,QAAQ,SAAS;UAC5C;EAEI,YAAA;EAQZ;EAKA,QAAQ;SAQD,MAAM,eAAY,YAAA,cAAA;;cAKd,oBAAqB,iBAAY,YAAA,cAAA;KAElC;KAEA;EACV,OAAO;EACP;EACA,OAAO;;KAGG,kEAMC;YACG,cAAc;;;;;;;;;;cAqBjB,eAAe;EAC1B,IAAI,OAAO;EACX,IAAI,OAAO,aAAa,iBAAiB,OAAO;EAahD,MAAM,iBAAiB,OAAO;EAI9B,KAAK,iBAAiB,OAAO;EAI7B,KAAK,iBAAiB,OAAO;EAI7B,MAAM,iBAAiB,OAAO;;;cAMnB,YAAU,YAAA,cAAA;;cAGV,sBAAsB,QAAQ,SAAS;WACzC,QAAQ;EAEjB,IAAI,OAAO;EACX,IAAI,OAAO,aAAa,iBAAiB,OAAO;EAOhD,MAAM,iBAAiB,OAAO;EAI9B,KAAK,iBAAiB,OAAO;EAI7B,KAAK,iBAAiB,OAAO;EAI7B,MAAM,iBAAiB,OAAO;EAI9B;SAIO;;;;SAKA,MAAM,SAAQ,aAA6B,YAAA,cAAA;;cAKvC,uBAAe,YAAA,cAAA;;;;;;;;;cAGf,uBAAuB;WAIb;WAHZ;EAGY,YAAA;SAMd,MAAM,iBAAc,YAAA,cAAA;;cAMhB,sBAAuB,mBAAc,YAAA,cAAA"}