better-effect 0.10.0 → 0.12.0
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.
- package/README.md +464 -11
- package/dist/adapters/iti.d.mts +4 -4
- package/dist/adapters/iti.d.mts.map +1 -1
- package/dist/adapters/iti.mjs +20 -14
- package/dist/adapters/iti.mjs.map +1 -1
- package/dist/effect-CK4YZaX0.mjs +559 -0
- package/dist/effect-CK4YZaX0.mjs.map +1 -0
- package/dist/hono.d.mts +18 -13
- package/dist/hono.d.mts.map +1 -1
- package/dist/hono.mjs +9 -5
- package/dist/hono.mjs.map +1 -1
- package/dist/{index-DklNCz7w.d.mts → index-B1nH4luq.d.mts} +74 -7
- package/dist/index-B1nH4luq.d.mts.map +1 -0
- package/dist/index-BMdU_Z72.d.mts +18 -0
- package/dist/index-BMdU_Z72.d.mts.map +1 -0
- package/dist/{index-BafDna0B.d.mts → index-CX6iAoCB.d.mts} +168 -174
- package/dist/index-CX6iAoCB.d.mts.map +1 -0
- package/dist/index-GYJ4qm9K.d.mts +179 -0
- package/dist/index-GYJ4qm9K.d.mts.map +1 -0
- package/dist/{index-CULgSzUw.d.mts → index-heuaRmXR.d.mts} +5 -5
- package/dist/{index-CULgSzUw.d.mts.map → index-heuaRmXR.d.mts.map} +1 -1
- package/dist/index.d.mts +6 -5
- package/dist/index.mjs +9 -539
- package/dist/index.mjs.map +1 -1
- package/dist/{internal-identity-DmUpBeeL.mjs → internal-identity-CbXoZIfw.mjs} +3 -3
- package/dist/internal-identity-CbXoZIfw.mjs.map +1 -0
- package/dist/{signal-C1bagvrO.mjs → layer-D56fRdLt.mjs} +62 -64
- package/dist/layer-D56fRdLt.mjs.map +1 -0
- package/dist/node-context-DWsCUBRa.d.mts +12 -0
- package/dist/node-context-DWsCUBRa.d.mts.map +1 -0
- package/dist/node-context-lggRF4bR.mjs +25 -0
- package/dist/node-context-lggRF4bR.mjs.map +1 -0
- package/dist/node.d.mts +51 -0
- package/dist/node.d.mts.map +1 -0
- package/dist/node.mjs +233 -0
- package/dist/node.mjs.map +1 -0
- package/dist/{index-C7KX5rAP.d.mts → outcome-CB43bnFW.d.mts} +140 -27
- package/dist/outcome-CB43bnFW.d.mts.map +1 -0
- package/dist/program-metadata-DhQCCirO.mjs +260 -0
- package/dist/program-metadata-DhQCCirO.mjs.map +1 -0
- package/dist/registration-drnZk0SY.mjs +182 -0
- package/dist/registration-drnZk0SY.mjs.map +1 -0
- package/dist/runtime/explicit.d.mts +1 -1
- package/dist/runtime/node.d.mts +3 -12
- package/dist/runtime/node.mjs +2 -24
- package/dist/runtime-CBMrX8Wl.mjs +776 -0
- package/dist/runtime-CBMrX8Wl.mjs.map +1 -0
- package/dist/signal-D2UTcaaG.mjs +105 -0
- package/dist/signal-D2UTcaaG.mjs.map +1 -0
- package/dist/{standard-services-DW-i4UuA.mjs → standard-services-GBZ32tll.mjs} +200 -16
- package/dist/standard-services-GBZ32tll.mjs.map +1 -0
- package/dist/standard-services.d.mts +3 -3
- package/dist/standard-services.mjs +3 -3
- package/dist/testing.d.mts +257 -2
- package/dist/testing.d.mts.map +1 -0
- package/dist/testing.mjs +1159 -2
- package/dist/testing.mjs.map +1 -0
- package/package.json +8 -3
- package/dist/effect-DAMqvegy.mjs +0 -544
- package/dist/effect-DAMqvegy.mjs.map +0 -1
- package/dist/errors-Dnjhzbt0.mjs +0 -99
- package/dist/errors-Dnjhzbt0.mjs.map +0 -1
- package/dist/index-BafDna0B.d.mts.map +0 -1
- package/dist/index-C7KX5rAP.d.mts.map +0 -1
- package/dist/index-DklNCz7w.d.mts.map +0 -1
- package/dist/internal-identity-DmUpBeeL.mjs.map +0 -1
- package/dist/map-layer-backend-gal-mcRv.mjs +0 -53
- package/dist/map-layer-backend-gal-mcRv.mjs.map +0 -1
- package/dist/map-layer-backend-rNwfH0Bz.d.mts +0 -42
- package/dist/map-layer-backend-rNwfH0Bz.d.mts.map +0 -1
- package/dist/runtime/node.d.mts.map +0 -1
- package/dist/runtime/node.mjs.map +0 -1
- package/dist/signal-C1bagvrO.mjs.map +0 -1
- package/dist/standard-services-DW-i4UuA.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standard-services-GBZ32tll.mjs","names":[],"sources":["../src/standard-services/config.ts","../src/standard-services/id-generator.ts","../src/standard-services/index.ts"],"sourcesContent":["import {\n Result,\n TaggedError,\n type Err,\n type Result as ResultType,\n type StandardSchemaV1,\n type UnhandledException\n} from 'better-result'\n\nimport type { ServiceRequirement } from '../effect/types'\nimport { Layer } from '../layer'\nimport { Service } from '../service'\n\n/** Raw string values supplied to a configuration schema. */\nexport type ConfigSource = Readonly<Record<string, string | undefined>>\n\n/** Optional sources used by environment-backed configuration values. */\nexport type ConfigSourceOptions = {\n readonly dotEnvPath?: string\n readonly envSource?: ConfigSource\n}\n\n/** Options for the one-call schema-bound configuration API. */\nexport type ConfigFromEnvOptions<Schema extends StandardSchemaV1> = ConfigSourceOptions & {\n readonly schema: Schema\n}\n\n/** The decoded value produced by a Standard Schema. */\nexport type ConfigOutput<Schema extends StandardSchemaV1> = StandardSchemaV1.InferOutput<Schema>\n\n/** The raw input type described by a Standard Schema. */\nexport type ConfigInput<Schema extends StandardSchemaV1> = StandardSchemaV1.InferInput<Schema>\n\n/** A safe validation issue exposed by a configuration failure. */\nexport type ConfigIssue = StandardSchemaV1.Issue\n\n/** A schema validation failure. Raw source values are intentionally omitted. */\nexport class ConfigValidationError extends TaggedError('ConfigValidationError')<{\n readonly issues: ReadonlyArray<ConfigIssue>\n readonly message: string\n}> {}\n\n/** A dotenv or host-source loading failure. Raw source values are intentionally omitted. */\nexport class ConfigSourceError extends TaggedError('ConfigSourceError')<{\n readonly cause: unknown\n readonly message: string\n readonly path?: string\n}> {}\n\n/** Errors that may be returned while loading or validating configuration. */\nexport type ConfigError = ConfigValidationError | ConfigSourceError | UnhandledException\n\ntype ConfigYield<Requirements extends Service.Any, Error> =\n | Err<never, Error>\n | ServiceRequirement<Requirements>\n\n/** A reusable, async-yieldable Standard Schema configuration descriptor. */\nexport type ConfigValue<\n Schema extends StandardSchemaV1,\n Requirements extends Service.Any = never,\n Error = ConfigError\n> = {\n [Symbol.asyncIterator](): AsyncGenerator<\n ConfigYield<Requirements, Error>,\n ConfigOutput<Schema>,\n unknown\n >\n}\n\ntype RuntimeConfigYield = Err<never, ConfigError> | ServiceRequirement<Service.Any>\n\ntype ConfigValueSpec<Schema extends StandardSchemaV1> = {\n readonly schema: Schema\n readonly source: 'bound' | 'provider'\n readonly sourceOptions?: ConfigSourceOptions\n}\n\ntype MutableConfigSourceOptions = {\n dotEnvPath?: string\n envSource?: ConfigSource\n}\n\ntype RuntimeGlobal = typeof globalThis & {\n readonly process?: { readonly env?: ConfigSource }\n readonly Bun?: {\n readonly env?: ConfigSource\n readonly file?: (path: string) => { text(): Promise<string> }\n }\n}\n\n// SAFETY: Hosts may expose process/Bun globals at runtime without declaring them on globalThis.\nconst runtimeGlobal = globalThis as RuntimeGlobal\n\nconst hostEnvironment = (): ConfigSource => {\n const processEnvironment = runtimeGlobal.process?.env\n\n if (processEnvironment !== undefined) {\n return processEnvironment\n }\n\n return runtimeGlobal.Bun?.env ?? {}\n}\n\nconst readText = async (path: string): Promise<string> => {\n const file = runtimeGlobal.Bun?.file\n\n if (file !== undefined) {\n return await file(path).text()\n }\n\n const { readFile } = await import('node:fs/promises')\n\n return await readFile(path, 'utf8')\n}\n\nconst parseDotEnv = (text: string) => {\n const values = new Map<string, string>()\n\n for (const [lineIndex, rawLine] of text\n .replace(/^\\uFEFF/, '')\n .split(/\\r?\\n/u)\n .entries()) {\n let line = rawLine.trim()\n\n if (line === '' || line.startsWith('#')) {\n continue\n }\n\n if (/^export\\s/u.test(line)) {\n line = line.replace(/^export\\s+/u, '')\n }\n\n const separator = line.indexOf('=')\n\n if (separator <= 0) {\n throw new Error(`Invalid dotenv entry at line ${lineIndex + 1}`)\n }\n\n const key = line.slice(0, separator).trim()\n\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(key)) {\n throw new Error(`Invalid dotenv key at line ${lineIndex + 1}`)\n }\n\n let value = line.slice(separator + 1).trim()\n const quote = value[0]\n\n if (quote === '\"' || quote === \"'\") {\n const closingQuote = value.indexOf(quote, 1)\n const trailing = closingQuote < 0 ? '' : value.slice(closingQuote + 1).trim()\n\n if (closingQuote < 0 || (trailing !== '' && !trailing.startsWith('#'))) {\n throw new Error(`Unterminated dotenv value at line ${lineIndex + 1}`)\n }\n\n value = value.slice(1, closingQuote)\n } else {\n const comment = value.search(/\\s+#/u)\n\n if (comment >= 0) {\n value = value.slice(0, comment).trimEnd()\n }\n }\n\n values.set(key, value)\n }\n\n return Object.fromEntries(values)\n}\n\nconst loadSource = async (options: ConfigSourceOptions = {}): Promise<ConfigSource> => {\n const dotenv =\n options.dotEnvPath === undefined ? {} : parseDotEnv(await readText(options.dotEnvPath))\n const explicit = options.envSource ?? hostEnvironment()\n\n return {\n ...dotenv,\n ...explicit\n }\n}\n\nconst sourceError = (path: string | undefined, cause: unknown): ConfigSourceError => {\n const message =\n path === undefined\n ? 'Failed to load configuration source'\n : `Failed to load configuration source at ${path}`\n\n if (path === undefined) {\n return new ConfigSourceError({ cause, message })\n }\n\n return new ConfigSourceError({ cause, message, path })\n}\n\nconst validate = async <Schema extends StandardSchemaV1>(\n schema: Schema,\n source: ConfigSource\n): Promise<ResultType<ConfigOutput<Schema>, ConfigValidationError | UnhandledException>> => {\n const checked = await Result.tryPromise(() =>\n Promise.resolve(schema['~standard'].validate(source))\n )\n\n if (checked.status === 'error') {\n return checked\n }\n\n if (checked.value.issues !== undefined) {\n return Result.err(\n new ConfigValidationError({\n issues: Object.freeze([...checked.value.issues]),\n message: 'Configuration validation failed'\n })\n )\n }\n\n // SAFETY: A successful Standard Schema result carries its declared output type.\n return Result.ok(checked.value.value as ConfigOutput<Schema>)\n}\n\nconst evaluate = async <Schema extends StandardSchemaV1>(\n spec: ConfigValueSpec<Schema>,\n provider?: Config\n): Promise<ResultType<ConfigOutput<Schema>, ConfigError>> => {\n const loaded = await Result.tryPromise({\n try: async () => {\n if (spec.source === 'provider') {\n const base = provider?.source\n\n if (base === undefined) {\n throw new Error('Config provider did not expose a source')\n }\n\n if (spec.sourceOptions === undefined) {\n return base\n }\n\n return {\n ...base,\n ...(await loadSource(spec.sourceOptions))\n }\n }\n\n return await loadSource(spec.sourceOptions)\n },\n catch: (cause) => sourceError(spec.sourceOptions?.dotEnvPath, cause)\n })\n\n if (loaded.status === 'error') {\n return loaded\n }\n\n return await validate(spec.schema, loaded.value)\n}\n\nconst makeConfigValue = <Schema extends StandardSchemaV1, Requirements extends Service.Any>(\n spec: ConfigValueSpec<Schema>\n): ConfigValue<Schema, Requirements> => {\n const value = {\n ...spec,\n async *[Symbol.asyncIterator](): AsyncGenerator<\n RuntimeConfigYield,\n ConfigOutput<Schema>,\n unknown\n > {\n let provider: Config | undefined\n\n if (spec.source === 'provider') {\n provider = yield* Config\n }\n\n return yield* Result.await(evaluate(spec, provider))\n }\n }\n\n // SAFETY: The runtime iterator only yields Result errors and Service values; the public cast restores the phantom requirement.\n return value as ConfigValue<Schema, Requirements>\n}\n\n/** Host-backed raw configuration source and provider token. */\nexport class Config extends Service<Config>()('Config') {\n constructor(readonly source: ConfigSource) {\n super()\n }\n\n /** Read one raw value from the configured source. */\n get(key: string): string | undefined {\n return this.source[key]\n }\n\n /** Create a provider from an already-loaded source. */\n static layer(source: ConfigSource) {\n return Layer.succeed(Config, new Config(source))\n }\n\n /** Create a provider whose source is loaded from dotenv and the host environment. */\n static layerFromEnv(options: ConfigSourceOptions = {}) {\n return Layer.make(Config, async () => {\n try {\n return new Config(await loadSource(options))\n } catch (cause) {\n throw sourceError(options.dotEnvPath, cause)\n }\n })\n }\n\n /** Describe a configuration read from the contextual Config provider. */\n static schema<Schema extends StandardSchemaV1>(schema: Schema): ConfigValue<Schema, Config> {\n return makeConfigValue({ schema, source: 'provider' })\n }\n\n /** Describe a reusable configuration loaded from dotenv and the host environment. */\n static fromEnv<Schema extends StandardSchemaV1>(\n options: ConfigFromEnvOptions<Schema>\n ): ConfigValue<Schema> {\n const sourceOptions: MutableConfigSourceOptions = {}\n\n if (options.dotEnvPath !== undefined) {\n sourceOptions.dotEnvPath = options.dotEnvPath\n }\n\n if (options.envSource !== undefined) {\n sourceOptions.envSource = options.envSource\n }\n\n return makeConfigValue({\n schema: options.schema,\n source: 'bound',\n sourceOptions\n })\n }\n\n /** Add an environment source to a provider-backed descriptor for functional `pipe` composition. */\n static withEnv(options: ConfigSourceOptions) {\n return <Schema extends StandardSchemaV1, Requirements extends Service.Any, Error = ConfigError>(\n value: ConfigValue<Schema, Requirements, Error>\n ): ConfigValue<Schema, Requirements, Error> => {\n // SAFETY: Values produced by this module retain their schema/source descriptor fields; custom iterables pass through unchanged.\n const internal = value as ConfigValue<Schema, Requirements> & ConfigValueSpec<Schema>\n\n if (!('schema' in internal)) {\n return value\n }\n\n // SAFETY: The internal descriptor preserves the original schema and requirement phantom.\n return makeConfigValue({\n schema: internal.schema,\n source: internal.source,\n sourceOptions: options\n }) as ConfigValue<Schema, Requirements, Error>\n }\n }\n}\n\n/** The default lazy host-environment Config provider. */\nexport const ConfigLive = Config.layerFromEnv()\n\nexport type { StandardSchemaV1 }\n","import { Layer } from '../layer'\nimport { Service } from '../service'\n\ntype HostCrypto = {\n readonly randomUUID?: () => string\n}\n\nconst hostCrypto = (): HostCrypto | undefined => {\n // SAFETY: Supported hosts expose crypto on globalThis, but the optional property models older or restricted hosts.\n return (globalThis as { readonly crypto?: HostCrypto }).crypto\n}\n\n/** Thrown when the host does not expose the supported Web Crypto UUID API. */\nexport class IdGeneratorUnavailableError extends Error {\n constructor() {\n super('IdGenerator requires a host crypto.randomUUID implementation')\n\n this.name = 'IdGeneratorUnavailableError'\n }\n}\n\n/** Thrown when an {@link IdGeneratorTest} queue has no IDs left. */\nexport class IdGeneratorExhaustedError extends Error {\n constructor(readonly generated: number) {\n super(\n `IdGeneratorTest queue exhausted after ${generated} generated ID${generated === 1 ? '' : 's'}`\n )\n\n this.name = 'IdGeneratorExhaustedError'\n }\n}\n\n/** Host-backed UUID string ID service. */\nexport class IdGenerator extends Service<IdGenerator>()('IdGenerator') {\n /** Generate a cryptographically strong UUID string using the host Web Crypto API. */\n next(): string {\n const crypto = hostCrypto()\n\n // oxlint-disable-next-line anti-slop/no-runtime-typeof -- host feature detection must verify the callable Web Crypto method.\n if (crypto === undefined || typeof crypto.randomUUID !== 'function') {\n throw new IdGeneratorUnavailableError()\n }\n\n return crypto.randomUUID()\n }\n}\n\n/** The default host IdGenerator provider. */\nexport const IdGeneratorLive = Layer.make(IdGenerator)\n\ntype IdFactory = (index: number) => string\n\n// oxlint-disable-next-line anti-slop/no-unknown-parameters -- runtime validation protects the public string-ID boundary.\nconst validateId = (value: unknown, source: string): string => {\n // oxlint-disable-next-line anti-slop/no-runtime-typeof -- runtime validation rejects unsafe test doubles.\n if (typeof value !== 'string') {\n throw new TypeError(`${source} must return a string ID`)\n }\n\n return value\n}\n\n/** Deterministic queue- or factory-backed IdGenerator implementation for tests. */\nexport class IdGeneratorTest implements Service.Contract<IdGenerator> {\n private readonly queue: string[]\n\n private factory: IdFactory | undefined\n\n private generatedCount = 0\n\n constructor(ids: readonly string[] = []) {\n this.queue = ids.map((id) => validateId(id, 'IdGeneratorTest queue values'))\n }\n\n /** Number of IDs successfully returned by this test generator. */\n get generated(): number {\n return this.generatedCount\n }\n\n /** Number of queued IDs still available, or Infinity for a factory. */\n get remaining(): number {\n return this.factory === undefined ? this.queue.length : Infinity\n }\n\n /** Return the next queued or factory-generated string ID. */\n next(): string {\n if (this.factory === undefined) {\n const value = this.queue.shift()\n\n if (value === undefined) {\n throw new IdGeneratorExhaustedError(this.generatedCount)\n }\n\n this.generatedCount += 1\n return value\n }\n\n const value = validateId(this.factory(this.generatedCount), 'IdGeneratorTest factory')\n this.generatedCount += 1\n return value\n }\n\n /**\n * Create a factory-backed generator. The factory receives a monotonic\n * zero-based index: the first call receives 0, then 1, and so on.\n */\n static from(factory: IdFactory): IdGeneratorTest {\n // oxlint-disable-next-line anti-slop/no-runtime-typeof -- runtime validation rejects an invalid factory at the API boundary.\n if (typeof factory !== 'function') {\n throw new TypeError('IdGeneratorTest.from requires a factory function')\n }\n\n const generator = new IdGeneratorTest()\n generator.factory = factory\n return generator\n }\n\n /** Create a Layer for this generator, allocating a fresh empty queue by default. */\n static layer(generator: IdGeneratorTest = new IdGeneratorTest()) {\n return Layer.succeed(IdGenerator, generator)\n }\n}\n\n/** Compatible functional shorthand for {@link IdGeneratorTest.layer}. */\nexport const IdGeneratorTestLayer = (generator?: IdGeneratorTest) =>\n IdGeneratorTest.layer(generator)\n","import { CurrentAbortSignal } from '../runtime'\nimport { Layer } from '../layer'\nimport { Service } from '../service'\n\nexport { CurrentAbortSignal }\n\nexport { Config, ConfigLive, ConfigSourceError, ConfigValidationError } from './config'\n\nexport type {\n ConfigError,\n ConfigFromEnvOptions,\n ConfigInput,\n ConfigIssue,\n ConfigOutput,\n ConfigSource,\n ConfigSourceOptions,\n ConfigValue,\n StandardSchemaV1\n} from './config'\n\nexport {\n IdGenerator,\n IdGeneratorExhaustedError,\n IdGeneratorLive,\n IdGeneratorTest,\n IdGeneratorTestLayer,\n IdGeneratorUnavailableError\n} from './id-generator'\n\nconst assertDelay = (milliseconds: number): void => {\n if (!Number.isFinite(milliseconds) || milliseconds < 0) {\n throw new RangeError('Delay must be a finite non-negative number')\n }\n}\n\nconst abortError = (): DOMException => new DOMException('The operation was aborted', 'AbortError')\n\nconst abortReason = (signal: AbortSignal): AbortSignal['reason'] =>\n signal.reason === undefined ? abortError() : signal.reason\n\n/** Optional cooperative cancellation for a host or test Clock sleep. */\nexport type ClockSleepOptions = {\n readonly signal?: AbortSignal\n}\n\n/** Host-backed time and waiting service. */\nexport class Clock extends Service<Clock>()('Clock') {\n now(): Date {\n return new Date()\n }\n\n /** Rejects with the signal reason, or an AbortError-compatible fallback. */\n sleep(milliseconds: number, options?: ClockSleepOptions): Promise<void> {\n assertDelay(milliseconds)\n const signal = options?.signal\n\n if (signal?.aborted) {\n return Promise.reject(abortReason(signal))\n }\n\n return new Promise<void>((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout> | undefined\n let settled = false\n\n function cleanup(): void {\n if (timer !== undefined) {\n clearTimeout(timer)\n timer = undefined\n }\n\n signal?.removeEventListener('abort', onAbort)\n }\n\n function settle(callback: () => void): void {\n if (settled) {\n return\n }\n\n settled = true\n cleanup()\n callback()\n }\n\n function onAbort(): void {\n if (signal !== undefined) {\n settle(() => reject(abortReason(signal)))\n }\n }\n\n try {\n signal?.addEventListener('abort', onAbort, { once: true })\n\n if (signal?.aborted) {\n onAbort()\n return\n }\n\n const handle = setTimeout(() => settle(resolve), milliseconds)\n\n if (settled) {\n clearTimeout(handle)\n } else {\n timer = handle\n }\n } catch (cause) {\n settle(() => reject(cause))\n }\n })\n }\n}\n\n/** The default host Clock provider. */\nexport const ClockLive = Layer.make(Clock)\n\ntype ClockWaiter = {\n readonly at: number\n readonly resolve: () => void\n readonly reject: (cause?: unknown) => void\n readonly signal: AbortSignal | undefined\n readonly onAbort: () => void\n settled: boolean\n}\n\n/** Limits deadline advances performed by `ClockTest.runAll`. */\nexport type ClockTestRunAllOptions = {\n readonly maxSteps?: number\n}\n\nconst defaultClockTestMaxSteps = 1_000\n\n/** Deterministic Clock implementation for tests. */\nexport class ClockTest implements Service.Contract<Clock> {\n private currentTime: number\n\n private readonly waiters: ClockWaiter[] = []\n\n constructor(initial: Date | number = 0) {\n this.currentTime = initial instanceof Date ? initial.getTime() : initial\n\n if (!Number.isFinite(this.currentTime)) {\n throw new RangeError('ClockTest time must be finite')\n }\n }\n\n /** Number of sleeps that have not been settled or cancelled. */\n get pendingSleeps(): number {\n return this.waiters.length\n }\n\n now(): Date {\n return new Date(this.currentTime)\n }\n\n /** Set an absolute time; moving backward leaves existing absolute deadlines unchanged. */\n setTime(value: Date | number): void {\n const next = value instanceof Date ? value.getTime() : value\n\n if (!Number.isFinite(next)) {\n throw new RangeError('ClockTest time must be finite')\n }\n\n this.currentTime = next\n this.flushWaiters()\n }\n\n advance(milliseconds: number): void {\n assertDelay(milliseconds)\n this.currentTime += milliseconds\n this.flushWaiters()\n }\n\n sleep(milliseconds: number, options?: ClockSleepOptions): Promise<void> {\n assertDelay(milliseconds)\n const signal = options?.signal\n\n if (signal?.aborted) {\n return Promise.reject(abortReason(signal))\n }\n\n return new Promise<void>((resolve, reject) => {\n let waiter!: ClockWaiter\n const onAbort = (): void => {\n if (signal !== undefined) {\n this.cancelWaiter(waiter, abortReason(signal))\n }\n }\n\n waiter = {\n at: this.currentTime + milliseconds,\n resolve,\n reject,\n signal,\n onAbort,\n settled: false\n }\n this.enqueueWaiter(waiter)\n\n try {\n signal?.addEventListener('abort', onAbort, { once: true })\n\n if (signal?.aborted) {\n this.cancelWaiter(waiter, abortReason(signal))\n return\n }\n } catch (cause) {\n this.cancelWaiter(waiter, cause)\n return\n }\n\n this.flushWaiters()\n })\n }\n\n /** Advance synchronously; due Promise continuations run after this method returns. */\n advanceToNext(): boolean {\n const next = this.waiters[0]\n\n if (next === undefined) {\n return false\n }\n\n this.currentTime = next.at\n this.flushWaiters()\n return true\n }\n\n /** Advance all pending deadlines, guarding at 1,000 steps by default. */\n async runAll(options?: ClockTestRunAllOptions): Promise<number> {\n const maxSteps = getMaxSteps(options)\n let steps = 0\n\n while (this.pendingSleeps > 0) {\n if (steps >= maxSteps) {\n throw new RangeError(`ClockTest.runAll exceeded maxSteps (${maxSteps})`)\n }\n\n this.advanceToNext()\n steps += 1\n await Promise.resolve()\n }\n\n return steps\n }\n\n static layer(initial: Date | number = 0) {\n return Layer.succeed(Clock, new ClockTest(initial))\n }\n\n private enqueueWaiter(waiter: ClockWaiter): void {\n const index = this.waiters.findIndex((pending) => pending.at > waiter.at)\n\n if (index === -1) {\n this.waiters.push(waiter)\n } else {\n this.waiters.splice(index, 0, waiter)\n }\n }\n\n private cancelWaiter(waiter: ClockWaiter, cause: unknown): void {\n const index = this.waiters.indexOf(waiter)\n\n if (index !== -1) {\n this.waiters.splice(index, 1)\n }\n\n this.finishWaiter(waiter, () => waiter.reject(cause))\n }\n\n private flushWaiters(): void {\n while (true) {\n const waiter = this.waiters[0]\n\n if (waiter === undefined || waiter.at > this.currentTime) {\n return\n }\n\n this.waiters.shift()\n this.finishWaiter(waiter, waiter.resolve)\n }\n }\n\n private finishWaiter(waiter: ClockWaiter, finish: () => void): void {\n if (waiter.settled) {\n return\n }\n\n waiter.settled = true\n waiter.signal?.removeEventListener('abort', waiter.onAbort)\n finish()\n }\n}\n\nconst getMaxSteps = (options?: ClockTestRunAllOptions): number => {\n const maxSteps = options?.maxSteps ?? defaultClockTestMaxSteps\n\n if (!Number.isInteger(maxSteps) || maxSteps < 0) {\n throw new RangeError('ClockTest.runAll maxSteps must be a finite non-negative integer')\n }\n\n return maxSteps\n}\n\nexport const ClockTestLayer = (initial: Date | number = 0) => ClockTest.layer(initial)\n\n/** Host-backed pseudo-random number service. */\nexport class Random extends Service<Random>()('Random') {\n next(): number {\n return Math.random()\n }\n\n nextInt(maxExclusive: number): number {\n if (!Number.isInteger(maxExclusive) || maxExclusive <= 0) {\n throw new RangeError('Random.nextInt maxExclusive must be a positive integer')\n }\n\n return Math.floor(this.next() * maxExclusive)\n }\n}\n\n/** The default host Random provider. */\nexport const RandomLive = Layer.make(Random)\n\n/** Reproducible pseudo-random implementation with isolated mutable state. */\nexport class RandomSeeded implements Service.Contract<Random> {\n private state: number\n\n constructor(seed: number) {\n if (!Number.isFinite(seed)) {\n throw new RangeError('RandomSeeded seed must be finite')\n }\n\n this.state = seed >>> 0\n }\n\n next(): number {\n this.state = (1664525 * this.state + 1013904223) >>> 0\n return this.state / 0x1_0000_0000\n }\n\n nextInt(maxExclusive: number): number {\n if (!Number.isInteger(maxExclusive) || maxExclusive <= 0) {\n throw new RangeError('RandomSeeded.nextInt maxExclusive must be a positive integer')\n }\n\n return Math.floor(this.next() * maxExclusive)\n }\n\n static layer(seed: number) {\n return Layer.succeed(Random, new RandomSeeded(seed))\n }\n}\n\nexport const RandomSeededLayer = (seed: number) => RandomSeeded.layer(seed)\n\nexport type LoggerLevel = 'debug' | 'info' | 'warn' | 'error'\n\nexport type LoggerEvent = {\n level: LoggerLevel\n message: string\n data?: LoggerData\n}\n\nexport type LoggerData =\n | string\n | number\n | boolean\n | bigint\n | null\n | readonly LoggerData[]\n | { readonly [key: string]: LoggerData }\ntype LoggerInput = LoggerEvent | LoggerLevel\n\nconst isLoggerLevel = (value: LoggerInput): value is LoggerLevel =>\n value === 'debug' || value === 'info' || value === 'warn' || value === 'error'\n\nconst toLoggerEvent = (input: LoggerInput, message?: string, data?: LoggerData): LoggerEvent => {\n if (!isLoggerLevel(input)) {\n return input\n }\n\n const event: LoggerEvent = { level: input, message: message ?? '' }\n\n if (data !== undefined) {\n event.data = data\n }\n\n return event\n}\n\n/** Structured host logger bridge. */\nexport class Logger extends Service<Logger>()('Logger') {\n log(event: LoggerEvent): void\n log(level: LoggerLevel, message: string, data?: LoggerData): void\n log(first: LoggerInput, message?: string, data?: LoggerData): void {\n const event = toLoggerEvent(first, message, data)\n\n const write = console[event.level]\n\n if (event.data === undefined) {\n write.call(console, event.message)\n } else {\n write.call(console, event.message, event.data)\n }\n }\n\n debug(message: string, data?: LoggerData): void {\n this.log('debug', message, data)\n }\n\n info(message: string, data?: LoggerData): void {\n this.log('info', message, data)\n }\n\n warn(message: string, data?: LoggerData): void {\n this.log('warn', message, data)\n }\n\n error(message: string, data?: LoggerData): void {\n this.log('error', message, data)\n }\n}\n\n/** The default host Logger provider. */\nexport const LoggerLive = Layer.make(Logger)\n\n/** Ordered in-memory Logger implementation for tests. */\nexport class LoggerTest implements Service.Contract<Logger> {\n readonly events: LoggerEvent[] = []\n\n log(event: LoggerEvent): void\n log(level: LoggerLevel, message: string, data?: LoggerData): void\n log(first: LoggerInput, message?: string, data?: LoggerData): void {\n const event = toLoggerEvent(first, message, data)\n\n this.events.push(event)\n }\n\n debug(message: string, data?: LoggerData): void {\n this.log('debug', message, data)\n }\n\n info(message: string, data?: LoggerData): void {\n this.log('info', message, data)\n }\n\n warn(message: string, data?: LoggerData): void {\n this.log('warn', message, data)\n }\n\n error(message: string, data?: LoggerData): void {\n this.log('error', message, data)\n }\n\n clear(): void {\n this.events.length = 0\n }\n\n static make() {\n const logger = new LoggerTest()\n return { logger, layer: Layer.succeed(Logger, logger) }\n }\n\n static layer(logger: LoggerTest = new LoggerTest()) {\n return Layer.succeed(Logger, logger)\n }\n}\n\nexport const LoggerTestLayer = () => LoggerTest.layer()\n\n/** Execution-local request value carried by a normal Service provider. */\nexport class CurrentRequest extends Service<CurrentRequest>()('CurrentRequest') {\n readonly request: unknown\n\n // oxlint-disable-next-line anti-slop/no-unknown-parameters\n constructor(readonly value: unknown) {\n super()\n this.request = value\n }\n\n // oxlint-disable-next-line anti-slop/no-unknown-parameters\n static layer(value: unknown) {\n return Layer.succeed(CurrentRequest, new CurrentRequest(value))\n }\n}\n\n// oxlint-disable-next-line anti-slop/no-unknown-parameters\nexport const CurrentRequestLayer = (value: unknown) => CurrentRequest.layer(value)\n"],"mappings":";;;;AAqCA,IAAa,wBAAb,cAA2C,YAAY,uBAAuB,CAAC,CAG5E,CAAC;;AAGJ,IAAa,oBAAb,cAAuC,YAAY,mBAAmB,CAAC,CAIpE,CAAC;AA4CJ,MAAM,gBAAgB;AAEtB,MAAM,wBAAsC;CAC1C,MAAM,qBAAqB,cAAc,SAAS;CAElD,IAAI,uBAAuB,KAAA,GACzB,OAAO;CAGT,OAAO,cAAc,KAAK,OAAO,CAAC;AACpC;AAEA,MAAM,WAAW,OAAO,SAAkC;CACxD,MAAM,OAAO,cAAc,KAAK;CAEhC,IAAI,SAAS,KAAA,GACX,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,KAAK;CAG/B,MAAM,EAAE,aAAa,MAAM,OAAO;CAElC,OAAO,MAAM,SAAS,MAAM,MAAM;AACpC;AAEA,MAAM,eAAe,SAAiB;CACpC,MAAM,yBAAS,IAAI,IAAoB;CAEvC,KAAK,MAAM,CAAC,WAAW,YAAY,KAChC,QAAQ,WAAW,EAAE,CAAC,CACtB,MAAM,QAAQ,CAAC,CACf,QAAQ,GAAG;EACZ,IAAI,OAAO,QAAQ,KAAK;EAExB,IAAI,SAAS,MAAM,KAAK,WAAW,GAAG,GACpC;EAGF,IAAI,aAAa,KAAK,IAAI,GACxB,OAAO,KAAK,QAAQ,eAAe,EAAE;EAGvC,MAAM,YAAY,KAAK,QAAQ,GAAG;EAElC,IAAI,aAAa,GACf,MAAM,IAAI,MAAM,gCAAgC,YAAY,GAAG;EAGjE,MAAM,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK;EAE1C,IAAI,CAAC,4BAA4B,KAAK,GAAG,GACvC,MAAM,IAAI,MAAM,8BAA8B,YAAY,GAAG;EAG/D,IAAI,QAAQ,KAAK,MAAM,YAAY,CAAC,CAAC,CAAC,KAAK;EAC3C,MAAM,QAAQ,MAAM;EAEpB,IAAI,UAAU,QAAO,UAAU,KAAK;GAClC,MAAM,eAAe,MAAM,QAAQ,OAAO,CAAC;GAC3C,MAAM,WAAW,eAAe,IAAI,KAAK,MAAM,MAAM,eAAe,CAAC,CAAC,CAAC,KAAK;GAE5E,IAAI,eAAe,KAAM,aAAa,MAAM,CAAC,SAAS,WAAW,GAAG,GAClE,MAAM,IAAI,MAAM,qCAAqC,YAAY,GAAG;GAGtE,QAAQ,MAAM,MAAM,GAAG,YAAY;EACrC,OAAO;GACL,MAAM,UAAU,MAAM,OAAO,OAAO;GAEpC,IAAI,WAAW,GACb,QAAQ,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,QAAQ;EAE5C;EAEA,OAAO,IAAI,KAAK,KAAK;CACvB;CAEA,OAAO,OAAO,YAAY,MAAM;AAClC;AAEA,MAAM,aAAa,OAAO,UAA+B,CAAC,MAA6B;CACrF,MAAM,SACJ,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAI,YAAY,MAAM,SAAS,QAAQ,UAAU,CAAC;CACxF,MAAM,WAAW,QAAQ,aAAa,gBAAgB;CAEtD,OAAO;EACL,GAAG;EACH,GAAG;CACL;AACF;AAEA,MAAM,eAAe,MAA0B,UAAsC;CACnF,MAAM,UACJ,SAAS,KAAA,IACL,wCACA,0CAA0C;CAEhD,IAAI,SAAS,KAAA,GACX,OAAO,IAAI,kBAAkB;EAAE;EAAO;CAAQ,CAAC;CAGjD,OAAO,IAAI,kBAAkB;EAAE;EAAO;EAAS;CAAK,CAAC;AACvD;AAEA,MAAM,WAAW,OACf,QACA,WAC0F;CAC1F,MAAM,UAAU,MAAM,OAAO,iBAC3B,QAAQ,QAAQ,OAAO,YAAY,CAAC,SAAS,MAAM,CAAC,CACtD;CAEA,IAAI,QAAQ,WAAW,SACrB,OAAO;CAGT,IAAI,QAAQ,MAAM,WAAW,KAAA,GAC3B,OAAO,OAAO,IACZ,IAAI,sBAAsB;EACxB,QAAQ,OAAO,OAAO,CAAC,GAAG,QAAQ,MAAM,MAAM,CAAC;EAC/C,SAAS;CACX,CAAC,CACH;CAIF,OAAO,OAAO,GAAG,QAAQ,MAAM,KAA6B;AAC9D;AAEA,MAAM,WAAW,OACf,MACA,aAC2D;CAC3D,MAAM,SAAS,MAAM,OAAO,WAAW;EACrC,KAAK,YAAY;GACf,IAAI,KAAK,WAAW,YAAY;IAC9B,MAAM,OAAO,UAAU;IAEvB,IAAI,SAAS,KAAA,GACX,MAAM,IAAI,MAAM,yCAAyC;IAG3D,IAAI,KAAK,kBAAkB,KAAA,GACzB,OAAO;IAGT,OAAO;KACL,GAAG;KACH,GAAI,MAAM,WAAW,KAAK,aAAa;IACzC;GACF;GAEA,OAAO,MAAM,WAAW,KAAK,aAAa;EAC5C;EACA,QAAQ,UAAU,YAAY,KAAK,eAAe,YAAY,KAAK;CACrE,CAAC;CAED,IAAI,OAAO,WAAW,SACpB,OAAO;CAGT,OAAO,MAAM,SAAS,KAAK,QAAQ,OAAO,KAAK;AACjD;AAEA,MAAM,mBACJ,SACsC;CAmBtC,OAAO;EAjBL,GAAG;EACH,QAAQ,OAAO,iBAIb;GACA,IAAI;GAEJ,IAAI,KAAK,WAAW,YAClB,WAAW,OAAO;GAGpB,OAAO,OAAO,OAAO,MAAM,SAAS,MAAM,QAAQ,CAAC;EACrD;CAIS;AACb;;AAGA,IAAa,SAAb,MAAa,eAAe,QAAgB,CAAC,CAAC,QAAQ,CAAC,CAAC;CACjC;CAArB,YAAY,QAA+B;EACzC,MAAM;EADa,KAAA,SAAA;CAErB;;CAGA,IAAI,KAAiC;EACnC,OAAO,KAAK,OAAO;CACrB;;CAGA,OAAO,MAAM,QAAsB;EACjC,OAAO,MAAM,QAAQ,QAAQ,IAAI,OAAO,MAAM,CAAC;CACjD;;CAGA,OAAO,aAAa,UAA+B,CAAC,GAAG;EACrD,OAAO,MAAM,KAAK,QAAQ,YAAY;GACpC,IAAI;IACF,OAAO,IAAI,OAAO,MAAM,WAAW,OAAO,CAAC;GAC7C,SAAS,OAAO;IACd,MAAM,YAAY,QAAQ,YAAY,KAAK;GAC7C;EACF,CAAC;CACH;;CAGA,OAAO,OAAwC,QAA6C;EAC1F,OAAO,gBAAgB;GAAE;GAAQ,QAAQ;EAAW,CAAC;CACvD;;CAGA,OAAO,QACL,SACqB;EACrB,MAAM,gBAA4C,CAAC;EAEnD,IAAI,QAAQ,eAAe,KAAA,GACzB,cAAc,aAAa,QAAQ;EAGrC,IAAI,QAAQ,cAAc,KAAA,GACxB,cAAc,YAAY,QAAQ;EAGpC,OAAO,gBAAgB;GACrB,QAAQ,QAAQ;GAChB,QAAQ;GACR;EACF,CAAC;CACH;;CAGA,OAAO,QAAQ,SAA8B;EAC3C,QACE,UAC6C;GAE7C,MAAM,WAAW;GAEjB,IAAI,EAAE,YAAY,WAChB,OAAO;GAIT,OAAO,gBAAgB;IACrB,QAAQ,SAAS;IACjB,QAAQ,SAAS;IACjB,eAAe;GACjB,CAAC;EACH;CACF;AACF;;AAGA,MAAa,aAAa,OAAO,aAAa;;;AC3V9C,MAAM,mBAA2C;CAE/C,OAAQ,WAAgD;AAC1D;;AAGA,IAAa,8BAAb,cAAiD,MAAM;CACrD,cAAc;EACZ,MAAM,8DAA8D;EAEpE,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,4BAAb,cAA+C,MAAM;CAC9B;CAArB,YAAY,WAA4B;EACtC,MACE,yCAAyC,UAAU,eAAe,cAAc,IAAI,KAAK,KAC3F;EAHmB,KAAA,YAAA;EAKnB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,cAAb,cAAiC,QAAqB,CAAC,CAAC,aAAa,CAAC,CAAC;;CAErE,OAAe;EACb,MAAM,SAAS,WAAW;EAG1B,IAAI,WAAW,KAAA,KAAa,OAAO,OAAO,eAAe,YACvD,MAAM,IAAI,4BAA4B;EAGxC,OAAO,OAAO,WAAW;CAC3B;AACF;;AAGA,MAAa,kBAAkB,MAAM,KAAK,WAAW;AAKrD,MAAM,cAAc,OAAgB,WAA2B;CAE7D,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,UAAU,GAAG,OAAO,yBAAyB;CAGzD,OAAO;AACT;;AAGA,IAAa,kBAAb,MAAa,gBAAyD;CACpE;CAEA;CAEA,iBAAyB;CAEzB,YAAY,MAAyB,CAAC,GAAG;EACvC,KAAK,QAAQ,IAAI,KAAK,OAAO,WAAW,IAAI,8BAA8B,CAAC;CAC7E;;CAGA,IAAI,YAAoB;EACtB,OAAO,KAAK;CACd;;CAGA,IAAI,YAAoB;EACtB,OAAO,KAAK,YAAY,KAAA,IAAY,KAAK,MAAM,SAAS;CAC1D;;CAGA,OAAe;EACb,IAAI,KAAK,YAAY,KAAA,GAAW;GAC9B,MAAM,QAAQ,KAAK,MAAM,MAAM;GAE/B,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,0BAA0B,KAAK,cAAc;GAGzD,KAAK,kBAAkB;GACvB,OAAO;EACT;EAEA,MAAM,QAAQ,WAAW,KAAK,QAAQ,KAAK,cAAc,GAAG,yBAAyB;EACrF,KAAK,kBAAkB;EACvB,OAAO;CACT;;;;;CAMA,OAAO,KAAK,SAAqC;EAE/C,IAAI,OAAO,YAAY,YACrB,MAAM,IAAI,UAAU,kDAAkD;EAGxE,MAAM,YAAY,IAAI,gBAAgB;EACtC,UAAU,UAAU;EACpB,OAAO;CACT;;CAGA,OAAO,MAAM,YAA6B,IAAI,gBAAgB,GAAG;EAC/D,OAAO,MAAM,QAAQ,aAAa,SAAS;CAC7C;AACF;;AAGA,MAAa,wBAAwB,cACnC,gBAAgB,MAAM,SAAS;;;AChGjC,MAAM,eAAe,iBAA+B;CAClD,IAAI,CAAC,OAAO,SAAS,YAAY,KAAK,eAAe,GACnD,MAAM,IAAI,WAAW,4CAA4C;AAErE;AAEA,MAAM,mBAAiC,IAAI,aAAa,6BAA6B,YAAY;AAEjG,MAAM,eAAe,WACnB,OAAO,WAAW,KAAA,IAAY,WAAW,IAAI,OAAO;;AAQtD,IAAa,QAAb,cAA2B,QAAe,CAAC,CAAC,OAAO,CAAC,CAAC;CACnD,MAAY;EACV,uBAAO,IAAI,KAAK;CAClB;;CAGA,MAAM,cAAsB,SAA4C;EACtE,YAAY,YAAY;EACxB,MAAM,SAAS,SAAS;EAExB,IAAI,QAAQ,SACV,OAAO,QAAQ,OAAO,YAAY,MAAM,CAAC;EAG3C,OAAO,IAAI,SAAe,SAAS,WAAW;GAC5C,IAAI;GACJ,IAAI,UAAU;GAEd,SAAS,UAAgB;IACvB,IAAI,UAAU,KAAA,GAAW;KACvB,aAAa,KAAK;KAClB,QAAQ,KAAA;IACV;IAEA,QAAQ,oBAAoB,SAAS,OAAO;GAC9C;GAEA,SAAS,OAAO,UAA4B;IAC1C,IAAI,SACF;IAGF,UAAU;IACV,QAAQ;IACR,SAAS;GACX;GAEA,SAAS,UAAgB;IACvB,IAAI,WAAW,KAAA,GACb,aAAa,OAAO,YAAY,MAAM,CAAC,CAAC;GAE5C;GAEA,IAAI;IACF,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;IAEzD,IAAI,QAAQ,SAAS;KACnB,QAAQ;KACR;IACF;IAEA,MAAM,SAAS,iBAAiB,OAAO,OAAO,GAAG,YAAY;IAE7D,IAAI,SACF,aAAa,MAAM;SAEnB,QAAQ;GAEZ,SAAS,OAAO;IACd,aAAa,OAAO,KAAK,CAAC;GAC5B;EACF,CAAC;CACH;AACF;;AAGA,MAAa,YAAY,MAAM,KAAK,KAAK;AAgBzC,MAAM,2BAA2B;;AAGjC,IAAa,YAAb,MAAa,UAA6C;CACxD;CAEA,UAA0C,CAAC;CAE3C,YAAY,UAAyB,GAAG;EACtC,KAAK,cAAc,mBAAmB,OAAO,QAAQ,QAAQ,IAAI;EAEjE,IAAI,CAAC,OAAO,SAAS,KAAK,WAAW,GACnC,MAAM,IAAI,WAAW,+BAA+B;CAExD;;CAGA,IAAI,gBAAwB;EAC1B,OAAO,KAAK,QAAQ;CACtB;CAEA,MAAY;EACV,OAAO,IAAI,KAAK,KAAK,WAAW;CAClC;;CAGA,QAAQ,OAA4B;EAClC,MAAM,OAAO,iBAAiB,OAAO,MAAM,QAAQ,IAAI;EAEvD,IAAI,CAAC,OAAO,SAAS,IAAI,GACvB,MAAM,IAAI,WAAW,+BAA+B;EAGtD,KAAK,cAAc;EACnB,KAAK,aAAa;CACpB;CAEA,QAAQ,cAA4B;EAClC,YAAY,YAAY;EACxB,KAAK,eAAe;EACpB,KAAK,aAAa;CACpB;CAEA,MAAM,cAAsB,SAA4C;EACtE,YAAY,YAAY;EACxB,MAAM,SAAS,SAAS;EAExB,IAAI,QAAQ,SACV,OAAO,QAAQ,OAAO,YAAY,MAAM,CAAC;EAG3C,OAAO,IAAI,SAAe,SAAS,WAAW;GAC5C,IAAI;GACJ,MAAM,gBAAsB;IAC1B,IAAI,WAAW,KAAA,GACb,KAAK,aAAa,QAAQ,YAAY,MAAM,CAAC;GAEjD;GAEA,SAAS;IACP,IAAI,KAAK,cAAc;IACvB;IACA;IACA;IACA;IACA,SAAS;GACX;GACA,KAAK,cAAc,MAAM;GAEzB,IAAI;IACF,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;IAEzD,IAAI,QAAQ,SAAS;KACnB,KAAK,aAAa,QAAQ,YAAY,MAAM,CAAC;KAC7C;IACF;GACF,SAAS,OAAO;IACd,KAAK,aAAa,QAAQ,KAAK;IAC/B;GACF;GAEA,KAAK,aAAa;EACpB,CAAC;CACH;;CAGA,gBAAyB;EACvB,MAAM,OAAO,KAAK,QAAQ;EAE1B,IAAI,SAAS,KAAA,GACX,OAAO;EAGT,KAAK,cAAc,KAAK;EACxB,KAAK,aAAa;EAClB,OAAO;CACT;;CAGA,MAAM,OAAO,SAAmD;EAC9D,MAAM,WAAW,YAAY,OAAO;EACpC,IAAI,QAAQ;EAEZ,OAAO,KAAK,gBAAgB,GAAG;GAC7B,IAAI,SAAS,UACX,MAAM,IAAI,WAAW,uCAAuC,SAAS,EAAE;GAGzE,KAAK,cAAc;GACnB,SAAS;GACT,MAAM,QAAQ,QAAQ;EACxB;EAEA,OAAO;CACT;CAEA,OAAO,MAAM,UAAyB,GAAG;EACvC,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,OAAO,CAAC;CACpD;CAEA,cAAsB,QAA2B;EAC/C,MAAM,QAAQ,KAAK,QAAQ,WAAW,YAAY,QAAQ,KAAK,OAAO,EAAE;EAExE,IAAI,UAAU,IACZ,KAAK,QAAQ,KAAK,MAAM;OAExB,KAAK,QAAQ,OAAO,OAAO,GAAG,MAAM;CAExC;CAEA,aAAqB,QAAqB,OAAsB;EAC9D,MAAM,QAAQ,KAAK,QAAQ,QAAQ,MAAM;EAEzC,IAAI,UAAU,IACZ,KAAK,QAAQ,OAAO,OAAO,CAAC;EAG9B,KAAK,aAAa,cAAc,OAAO,OAAO,KAAK,CAAC;CACtD;CAEA,eAA6B;EAC3B,OAAO,MAAM;GACX,MAAM,SAAS,KAAK,QAAQ;GAE5B,IAAI,WAAW,KAAA,KAAa,OAAO,KAAK,KAAK,aAC3C;GAGF,KAAK,QAAQ,MAAM;GACnB,KAAK,aAAa,QAAQ,OAAO,OAAO;EAC1C;CACF;CAEA,aAAqB,QAAqB,QAA0B;EAClE,IAAI,OAAO,SACT;EAGF,OAAO,UAAU;EACjB,OAAO,QAAQ,oBAAoB,SAAS,OAAO,OAAO;EAC1D,OAAO;CACT;AACF;AAEA,MAAM,eAAe,YAA6C;CAChE,MAAM,WAAW,SAAS,YAAY;CAEtC,IAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,WAAW,GAC5C,MAAM,IAAI,WAAW,iEAAiE;CAGxF,OAAO;AACT;AAEA,MAAa,kBAAkB,UAAyB,MAAM,UAAU,MAAM,OAAO;;AAGrF,IAAa,SAAb,cAA4B,QAAgB,CAAC,CAAC,QAAQ,CAAC,CAAC;CACtD,OAAe;EACb,OAAO,KAAK,OAAO;CACrB;CAEA,QAAQ,cAA8B;EACpC,IAAI,CAAC,OAAO,UAAU,YAAY,KAAK,gBAAgB,GACrD,MAAM,IAAI,WAAW,wDAAwD;EAG/E,OAAO,KAAK,MAAM,KAAK,KAAK,IAAI,YAAY;CAC9C;AACF;;AAGA,MAAa,aAAa,MAAM,KAAK,MAAM;;AAG3C,IAAa,eAAb,MAAa,aAAiD;CAC5D;CAEA,YAAY,MAAc;EACxB,IAAI,CAAC,OAAO,SAAS,IAAI,GACvB,MAAM,IAAI,WAAW,kCAAkC;EAGzD,KAAK,QAAQ,SAAS;CACxB;CAEA,OAAe;EACb,KAAK,QAAS,UAAU,KAAK,QAAQ,eAAgB;EACrD,OAAO,KAAK,QAAQ;CACtB;CAEA,QAAQ,cAA8B;EACpC,IAAI,CAAC,OAAO,UAAU,YAAY,KAAK,gBAAgB,GACrD,MAAM,IAAI,WAAW,8DAA8D;EAGrF,OAAO,KAAK,MAAM,KAAK,KAAK,IAAI,YAAY;CAC9C;CAEA,OAAO,MAAM,MAAc;EACzB,OAAO,MAAM,QAAQ,QAAQ,IAAI,aAAa,IAAI,CAAC;CACrD;AACF;AAEA,MAAa,qBAAqB,SAAiB,aAAa,MAAM,IAAI;AAoB1E,MAAM,iBAAiB,UACrB,UAAU,WAAW,UAAU,UAAU,UAAU,UAAU,UAAU;AAEzE,MAAM,iBAAiB,OAAoB,SAAkB,SAAmC;CAC9F,IAAI,CAAC,cAAc,KAAK,GACtB,OAAO;CAGT,MAAM,QAAqB;EAAE,OAAO;EAAO,SAAS,WAAW;CAAG;CAElE,IAAI,SAAS,KAAA,GACX,MAAM,OAAO;CAGf,OAAO;AACT;;AAGA,IAAa,SAAb,cAA4B,QAAgB,CAAC,CAAC,QAAQ,CAAC,CAAC;CAGtD,IAAI,OAAoB,SAAkB,MAAyB;EACjE,MAAM,QAAQ,cAAc,OAAO,SAAS,IAAI;EAEhD,MAAM,QAAQ,QAAQ,MAAM;EAE5B,IAAI,MAAM,SAAS,KAAA,GACjB,MAAM,KAAK,SAAS,MAAM,OAAO;OAEjC,MAAM,KAAK,SAAS,MAAM,SAAS,MAAM,IAAI;CAEjD;CAEA,MAAM,SAAiB,MAAyB;EAC9C,KAAK,IAAI,SAAS,SAAS,IAAI;CACjC;CAEA,KAAK,SAAiB,MAAyB;EAC7C,KAAK,IAAI,QAAQ,SAAS,IAAI;CAChC;CAEA,KAAK,SAAiB,MAAyB;EAC7C,KAAK,IAAI,QAAQ,SAAS,IAAI;CAChC;CAEA,MAAM,SAAiB,MAAyB;EAC9C,KAAK,IAAI,SAAS,SAAS,IAAI;CACjC;AACF;;AAGA,MAAa,aAAa,MAAM,KAAK,MAAM;;AAG3C,IAAa,aAAb,MAAa,WAA+C;CAC1D,SAAiC,CAAC;CAIlC,IAAI,OAAoB,SAAkB,MAAyB;EACjE,MAAM,QAAQ,cAAc,OAAO,SAAS,IAAI;EAEhD,KAAK,OAAO,KAAK,KAAK;CACxB;CAEA,MAAM,SAAiB,MAAyB;EAC9C,KAAK,IAAI,SAAS,SAAS,IAAI;CACjC;CAEA,KAAK,SAAiB,MAAyB;EAC7C,KAAK,IAAI,QAAQ,SAAS,IAAI;CAChC;CAEA,KAAK,SAAiB,MAAyB;EAC7C,KAAK,IAAI,QAAQ,SAAS,IAAI;CAChC;CAEA,MAAM,SAAiB,MAAyB;EAC9C,KAAK,IAAI,SAAS,SAAS,IAAI;CACjC;CAEA,QAAc;EACZ,KAAK,OAAO,SAAS;CACvB;CAEA,OAAO,OAAO;EACZ,MAAM,SAAS,IAAI,WAAW;EAC9B,OAAO;GAAE;GAAQ,OAAO,MAAM,QAAQ,QAAQ,MAAM;EAAE;CACxD;CAEA,OAAO,MAAM,SAAqB,IAAI,WAAW,GAAG;EAClD,OAAO,MAAM,QAAQ,QAAQ,MAAM;CACrC;AACF;AAEA,MAAa,wBAAwB,WAAW,MAAM;;AAGtD,IAAa,iBAAb,MAAa,uBAAuB,QAAwB,CAAC,CAAC,gBAAgB,CAAC,CAAC;CAIzD;CAHrB;CAGA,YAAY,OAAyB;EACnC,MAAM;EADa,KAAA,QAAA;EAEnB,KAAK,UAAU;CACjB;CAGA,OAAO,MAAM,OAAgB;EAC3B,OAAO,MAAM,QAAQ,gBAAgB,IAAI,eAAe,KAAK,CAAC;CAChE;AACF;AAGA,MAAa,uBAAuB,UAAmB,eAAe,MAAM,KAAK"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { A as
|
|
3
|
-
export { Clock, ClockLive, ClockTest, ClockTestLayer, Config, type ConfigError, type ConfigFromEnvOptions, type ConfigInput, type ConfigIssue, ConfigLive, type ConfigOutput, type ConfigSource, ConfigSourceError, type ConfigSourceOptions, ConfigValidationError, type ConfigValue, CurrentAbortSignal, CurrentRequest, CurrentRequestLayer, Logger, LoggerData, LoggerEvent, LoggerLevel, LoggerLive, LoggerTest, LoggerTestLayer, Random, RandomLive, RandomSeeded, RandomSeededLayer, type StandardSchemaV1 };
|
|
1
|
+
import { c as CurrentAbortSignal } from "./index-GYJ4qm9K.mjs";
|
|
2
|
+
import { A as ConfigIssue, C as IdGeneratorTest, D as ConfigError, E as Config, F as ConfigSourceOptions, I as ConfigValidationError, L as ConfigValue, M as ConfigOutput, N as ConfigSource, O as ConfigFromEnvOptions, P as ConfigSourceError, R as StandardSchemaV1, S as IdGeneratorLive, T as IdGeneratorUnavailableError, _ as RandomLive, a as ClockTestLayer, b as IdGenerator, c as CurrentRequestLayer, d as LoggerEvent, f as LoggerLevel, g as Random, h as LoggerTestLayer, i as ClockTest, j as ConfigLive, k as ConfigInput, l as Logger, m as LoggerTest, n as ClockLive, o as ClockTestRunAllOptions, p as LoggerLive, r as ClockSleepOptions, s as CurrentRequest, t as Clock, u as LoggerData, v as RandomSeeded, w as IdGeneratorTestLayer, x as IdGeneratorExhaustedError, y as RandomSeededLayer } from "./index-B1nH4luq.mjs";
|
|
3
|
+
export { Clock, ClockLive, ClockSleepOptions, ClockTest, ClockTestLayer, ClockTestRunAllOptions, Config, type ConfigError, type ConfigFromEnvOptions, type ConfigInput, type ConfigIssue, ConfigLive, type ConfigOutput, type ConfigSource, ConfigSourceError, type ConfigSourceOptions, ConfigValidationError, type ConfigValue, CurrentAbortSignal, CurrentRequest, CurrentRequestLayer, IdGenerator, IdGeneratorExhaustedError, IdGeneratorLive, IdGeneratorTest, IdGeneratorTestLayer, IdGeneratorUnavailableError, Logger, LoggerData, LoggerEvent, LoggerLevel, LoggerLive, LoggerTest, LoggerTestLayer, Random, RandomLive, RandomSeeded, RandomSeededLayer, type StandardSchemaV1 };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as CurrentAbortSignal } from "./signal-
|
|
2
|
-
import {
|
|
3
|
-
export { Clock, ClockLive, ClockTest, ClockTestLayer, Config, ConfigLive, ConfigSourceError, ConfigValidationError, CurrentAbortSignal, CurrentRequest, CurrentRequestLayer, Logger, LoggerLive, LoggerTest, LoggerTestLayer, Random, RandomLive, RandomSeeded, RandomSeededLayer };
|
|
1
|
+
import { t as CurrentAbortSignal } from "./signal-D2UTcaaG.mjs";
|
|
2
|
+
import { C as ConfigSourceError, S as ConfigLive, _ as IdGeneratorLive, a as CurrentRequest, b as IdGeneratorUnavailableError, c as LoggerLive, d as Random, f as RandomLive, g as IdGeneratorExhaustedError, h as IdGenerator, i as ClockTestLayer, l as LoggerTest, m as RandomSeededLayer, n as ClockLive, o as CurrentRequestLayer, p as RandomSeeded, r as ClockTest, s as Logger, t as Clock, u as LoggerTestLayer, v as IdGeneratorTest, w as ConfigValidationError, x as Config, y as IdGeneratorTestLayer } from "./standard-services-GBZ32tll.mjs";
|
|
3
|
+
export { Clock, ClockLive, ClockTest, ClockTestLayer, Config, ConfigLive, ConfigSourceError, ConfigValidationError, CurrentAbortSignal, CurrentRequest, CurrentRequestLayer, IdGenerator, IdGeneratorExhaustedError, IdGeneratorLive, IdGeneratorTest, IdGeneratorTestLayer, IdGeneratorUnavailableError, Logger, LoggerLive, LoggerTest, LoggerTestLayer, Random, RandomLive, RandomSeeded, RandomSeededLayer };
|
package/dist/testing.d.mts
CHANGED
|
@@ -1,2 +1,257 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { M as AnyService, c as RuntimeContextStorage } from "./index-heuaRmXR.mjs";
|
|
2
|
+
import { C as CompleteExecution, D as LayerInput, I as ValidateOverrides, L as ValidateOverridesWitness, M as ProvidedEnvironment, N as RequiredEnvironment, O as LayerInputState, P as ValidateLayerInput, d as RuntimeResourceReleaseEvent, f as RuntimeServiceAcquireEvent, i as RuntimeRunOptions, j as OverrideLayerResult, l as RuntimeExecutionStartEvent, n as RuntimeDisposeOptions, p as RuntimeServiceResolveEvent, r as RuntimeOptions, s as RuntimeExecutionEndEvent, u as RuntimeObserver, w as CompleteExecutionLayer, y as LayerBackend, z as MissingDependencies } from "./outcome-CB43bnFW.mjs";
|
|
3
|
+
import { t as MapLayerBackend } from "./index-BMdU_Z72.mjs";
|
|
4
|
+
import { l as Runtime } from "./index-GYJ4qm9K.mjs";
|
|
5
|
+
import { C as IdGeneratorTest, i as ClockTest, m as LoggerTest, v as RandomSeeded } from "./index-B1nH4luq.mjs";
|
|
6
|
+
//#region src/testing/contracts.d.ts
|
|
7
|
+
/** One runner-neutral conformance scenario. */
|
|
8
|
+
interface ContractScenario {
|
|
9
|
+
/** Stable human-readable scenario name for test-runner registration. */
|
|
10
|
+
readonly name: string;
|
|
11
|
+
/** Execute the scenario and reject with a diagnostic when its contract is violated. */
|
|
12
|
+
readonly run: () => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/** Thrown by a conformance scenario when an adapter violates its contract. */
|
|
15
|
+
declare class ConformanceError extends Error {
|
|
16
|
+
readonly scenario: string;
|
|
17
|
+
constructor(scenario: string, detail: string, cause?: unknown);
|
|
18
|
+
}
|
|
19
|
+
/** Declared behavior for a backend after a provider acquisition fails. */
|
|
20
|
+
type LayerBackendAcquisitionFailure = 'retry' | 'sticky';
|
|
21
|
+
/** Configuration for the LayerBackend conformance scenarios. */
|
|
22
|
+
interface LayerBackendContractOptions {
|
|
23
|
+
/** Create a new, isolated backend for every scenario. */
|
|
24
|
+
readonly makeBackend: () => LayerBackend | PromiseLike<LayerBackend>;
|
|
25
|
+
/** Declare whether failed acquisitions retry or remain cached until disposal. */
|
|
26
|
+
readonly acquisitionFailure: LayerBackendAcquisitionFailure;
|
|
27
|
+
/** Run adapter-specific cleanup after every scenario, including failed assertions. */
|
|
28
|
+
readonly cleanup?: (backend: LayerBackend) => void | PromiseLike<void>;
|
|
29
|
+
}
|
|
30
|
+
/** Supported overlap behavior for RuntimeContextStorage implementations. */
|
|
31
|
+
type ContextConcurrency = 'concurrent' | 'sequential';
|
|
32
|
+
/** Configuration for the RuntimeContextStorage conformance scenarios. */
|
|
33
|
+
interface RuntimeContextStorageContractOptions {
|
|
34
|
+
/** Create a new, isolated storage instance for every scenario. */
|
|
35
|
+
readonly makeStorage: () => RuntimeContextStorage;
|
|
36
|
+
/** Declare whether one storage instance supports overlapping root contexts. */
|
|
37
|
+
readonly concurrency: ContextConcurrency;
|
|
38
|
+
/** Recognize the implementation's standard missing-context error. */
|
|
39
|
+
readonly isMissingContextError?: (cause: unknown) => boolean;
|
|
40
|
+
/** Recognize the implementation's standard unsupported-overlap error. */
|
|
41
|
+
readonly isOverlapError?: (cause: unknown) => boolean;
|
|
42
|
+
/** Create a storage that should not leak a frame into this storage. */
|
|
43
|
+
readonly makeCompanionStorage?: () => RuntimeContextStorage;
|
|
44
|
+
/** Run adapter-specific cleanup after every scenario, including failed assertions. */
|
|
45
|
+
readonly cleanup?: (storage: RuntimeContextStorage) => void | PromiseLike<void>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Return runner-neutral scenarios for a LayerBackend implementation.
|
|
49
|
+
*
|
|
50
|
+
* Every scenario creates a fresh backend and invokes `cleanup` in `finally`,
|
|
51
|
+
* so consumers can register `scenario.run` directly with their test runner.
|
|
52
|
+
*/
|
|
53
|
+
declare const layerBackendContract: (options: LayerBackendContractOptions) => readonly ContractScenario[];
|
|
54
|
+
/**
|
|
55
|
+
* Return runner-neutral scenarios for a RuntimeContextStorage implementation.
|
|
56
|
+
*
|
|
57
|
+
* Every scenario creates a fresh storage and invokes `cleanup` in `finally`,
|
|
58
|
+
* so consumers can register `scenario.run` directly with their test runner.
|
|
59
|
+
*/
|
|
60
|
+
declare const runtimeContextStorageContract: (options: RuntimeContextStorageContractOptions) => readonly ContractScenario[];
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/testing/recorded-runtime-observer.d.ts
|
|
63
|
+
/** Every event emitted by a Runtime observer hook. */
|
|
64
|
+
type RuntimeObserverEvent = RuntimeServiceResolveEvent | RuntimeServiceAcquireEvent | RuntimeExecutionStartEvent | RuntimeExecutionEndEvent | RuntimeResourceReleaseEvent;
|
|
65
|
+
/** Immutable views of events recorded by a {@link RecordedRuntimeObserver}. */
|
|
66
|
+
type RecordedRuntimeObserverSnapshot = {
|
|
67
|
+
readonly serviceResolutions: readonly RuntimeServiceResolveEvent[];
|
|
68
|
+
readonly serviceAcquisitions: readonly RuntimeServiceAcquireEvent[];
|
|
69
|
+
readonly executionStarts: readonly RuntimeExecutionStartEvent[];
|
|
70
|
+
readonly executionEnds: readonly RuntimeExecutionEndEvent[];
|
|
71
|
+
readonly resourceReleases: readonly RuntimeResourceReleaseEvent[];
|
|
72
|
+
readonly timeline: readonly RuntimeObserverEvent[];
|
|
73
|
+
};
|
|
74
|
+
/** Records Runtime lifecycle events for assertions in tests. */
|
|
75
|
+
declare class RecordedRuntimeObserver implements RuntimeObserver {
|
|
76
|
+
private readonly serviceResolutionEvents;
|
|
77
|
+
private readonly serviceAcquisitionEvents;
|
|
78
|
+
private readonly executionStartEvents;
|
|
79
|
+
private readonly executionEndEvents;
|
|
80
|
+
private readonly resourceReleaseEvents;
|
|
81
|
+
private readonly timelineEvents;
|
|
82
|
+
static make(): RecordedRuntimeObserver;
|
|
83
|
+
readonly onServiceResolve: (event: RuntimeServiceResolveEvent) => void;
|
|
84
|
+
readonly onServiceAcquire: (event: RuntimeServiceAcquireEvent) => void;
|
|
85
|
+
readonly onExecutionStart: (event: RuntimeExecutionStartEvent) => void;
|
|
86
|
+
readonly onExecutionEnd: (event: RuntimeExecutionEndEvent) => void;
|
|
87
|
+
readonly onResourceRelease: (event: RuntimeResourceReleaseEvent) => void;
|
|
88
|
+
get serviceResolutions(): readonly RuntimeServiceResolveEvent[];
|
|
89
|
+
get serviceAcquisitions(): readonly RuntimeServiceAcquireEvent[];
|
|
90
|
+
get executionStarts(): readonly RuntimeExecutionStartEvent[];
|
|
91
|
+
get executionEnds(): readonly RuntimeExecutionEndEvent[];
|
|
92
|
+
get resourceReleases(): readonly RuntimeResourceReleaseEvent[];
|
|
93
|
+
get timeline(): readonly RuntimeObserverEvent[];
|
|
94
|
+
clear(): void;
|
|
95
|
+
snapshot(): RecordedRuntimeObserverSnapshot;
|
|
96
|
+
private record;
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/testing/runtime-graph-observer.d.ts
|
|
100
|
+
/** One logical Service node in a Runtime graph snapshot. */
|
|
101
|
+
type RuntimeGraphNode = {
|
|
102
|
+
readonly tag: string;
|
|
103
|
+
readonly resolutions: number;
|
|
104
|
+
readonly acquisitions: number;
|
|
105
|
+
readonly failures: number;
|
|
106
|
+
};
|
|
107
|
+
/** One observed parent-to-child Service edge in a Runtime graph snapshot. */
|
|
108
|
+
type RuntimeGraphEdge = {
|
|
109
|
+
readonly from: string;
|
|
110
|
+
readonly to: string;
|
|
111
|
+
readonly resolutions: number;
|
|
112
|
+
};
|
|
113
|
+
/** Detached, sorted and immutable Runtime graph data. */
|
|
114
|
+
type RuntimeGraphSnapshot = {
|
|
115
|
+
readonly nodes: readonly RuntimeGraphNode[];
|
|
116
|
+
readonly edges: readonly RuntimeGraphEdge[];
|
|
117
|
+
};
|
|
118
|
+
/** Options for a diagnostic Runtime graph observer. */
|
|
119
|
+
type RuntimeGraphObserverOptions = {
|
|
120
|
+
/** Count failed resolution and acquisition events in each node's failures field. */
|
|
121
|
+
readonly includeFailures?: boolean;
|
|
122
|
+
/** Add this label as a synthetic root in Mermaid output for top-level resolutions. */
|
|
123
|
+
readonly rootLabel?: string;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Observe the public Runtime resolution and acquisition events as a diagnostic graph.
|
|
127
|
+
*
|
|
128
|
+
* The graph is deliberately an observation of paths emitted by Runtime. It does
|
|
129
|
+
* not inspect Layer provenance, retain Service instances, or plan dependencies.
|
|
130
|
+
*/
|
|
131
|
+
declare class RuntimeGraphObserver implements RuntimeObserver {
|
|
132
|
+
private readonly includeFailures;
|
|
133
|
+
private readonly rootLabel;
|
|
134
|
+
private readonly nodes;
|
|
135
|
+
private readonly edges;
|
|
136
|
+
private readonly rootEdges;
|
|
137
|
+
private constructor();
|
|
138
|
+
/** Create an empty Runtime graph observer. */
|
|
139
|
+
static make(options?: RuntimeGraphObserverOptions): RuntimeGraphObserver;
|
|
140
|
+
readonly onServiceResolve: (event: RuntimeServiceResolveEvent) => void;
|
|
141
|
+
readonly onServiceAcquire: (event: RuntimeServiceAcquireEvent) => void;
|
|
142
|
+
/** Return a fresh, deeply detached and sorted graph snapshot. */
|
|
143
|
+
toJSON(): RuntimeGraphSnapshot;
|
|
144
|
+
/** Render the current graph as deterministic Mermaid flowchart source. */
|
|
145
|
+
toMermaid(): string;
|
|
146
|
+
/** Discard all observed graph data while keeping this observer reusable. */
|
|
147
|
+
clear(): void;
|
|
148
|
+
private ensureNode;
|
|
149
|
+
private ensurePath;
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/testing/test-runtime.d.ts
|
|
153
|
+
declare const TestRuntimeOptionsOverridesTypeId: unique symbol;
|
|
154
|
+
type ValidatedTestServiceOption<Base extends LayerInput, Overrides extends readonly LayerInput[], Replacement extends LayerInput, Value> = Value & ValidateOverridesWitness<Base, readonly [...Overrides, Replacement]>;
|
|
155
|
+
/** Options for an isolated TestRuntime. */
|
|
156
|
+
type TestRuntimeOptions<Base extends LayerInput = LayerInput, Overrides extends readonly LayerInput[] = readonly []> = Omit<RuntimeOptions, 'backend' | 'observers'> & {
|
|
157
|
+
/** Explicitly replace or add providers through `Layer.override`. */
|
|
158
|
+
readonly overrides?: Overrides & ValidateOverrides<Base, Overrides>;
|
|
159
|
+
/** Backend used by the underlying Runtime. Defaults to a fresh MapLayerBackend. */
|
|
160
|
+
readonly backend?: LayerBackend;
|
|
161
|
+
/** Deterministic Clock provider to install for this TestRuntime. */
|
|
162
|
+
readonly clock?: ValidatedTestServiceOption<Base, Overrides, ClockTestLayer, ClockTest>;
|
|
163
|
+
/** In-memory Logger provider to install for this TestRuntime. */
|
|
164
|
+
readonly logger?: ValidatedTestServiceOption<Base, Overrides, LoggerTestLayer, LoggerTest>;
|
|
165
|
+
/** Seeded Random provider to install for this TestRuntime. */
|
|
166
|
+
readonly random?: ValidatedTestServiceOption<Base, Overrides, RandomSeededLayer, RandomSeeded>;
|
|
167
|
+
/** Deterministic IdGenerator provider to install for this TestRuntime. */
|
|
168
|
+
readonly idGenerator?: ValidatedTestServiceOption<Base, Overrides, IdGeneratorTestLayer, IdGeneratorTest>;
|
|
169
|
+
/** Additional best-effort observers after the default recorder. */
|
|
170
|
+
readonly observers?: readonly RuntimeObserver[];
|
|
171
|
+
} & {
|
|
172
|
+
readonly [TestRuntimeOptionsOverridesTypeId]?: Overrides;
|
|
173
|
+
};
|
|
174
|
+
type ClockTestLayer = ReturnType<typeof ClockTest.layer>;
|
|
175
|
+
type LoggerTestLayer = ReturnType<typeof LoggerTest.layer>;
|
|
176
|
+
type RandomSeededLayer = ReturnType<typeof RandomSeeded.layer>;
|
|
177
|
+
type IdGeneratorTestLayer = ReturnType<typeof IdGeneratorTest.layer>;
|
|
178
|
+
type TestRuntimeOptionsInput = Omit<RuntimeOptions, 'backend' | 'observers'> & {
|
|
179
|
+
readonly overrides?: readonly LayerInput[];
|
|
180
|
+
readonly backend?: LayerBackend;
|
|
181
|
+
readonly clock?: ClockTest;
|
|
182
|
+
readonly logger?: LoggerTest;
|
|
183
|
+
readonly random?: RandomSeeded;
|
|
184
|
+
readonly idGenerator?: IdGeneratorTest;
|
|
185
|
+
readonly observers?: readonly RuntimeObserver[];
|
|
186
|
+
};
|
|
187
|
+
type ExplicitOverrides<Options extends TestRuntimeOptionsInput> = typeof TestRuntimeOptionsOverridesTypeId extends keyof Options ? Exclude<Options[typeof TestRuntimeOptionsOverridesTypeId], undefined> extends (infer Overrides extends readonly LayerInput[]) ? Overrides : readonly [] : Exclude<Options['overrides'], undefined> extends (infer Overrides extends readonly LayerInput[]) ? Overrides : readonly [];
|
|
188
|
+
type HasDefinedOption<Options, Key extends PropertyKey> = true extends (Options extends unknown ? Key extends keyof Options ? {} extends Pick<Options, Key> ? false : undefined extends Options[Key] ? false : true : false : never) ? true : false;
|
|
189
|
+
type HasPotentialOption<Options, Key extends PropertyKey> = true extends (Options extends unknown ? Key extends keyof Options ? [Exclude<Options[Key], undefined>] extends [never] ? false : true : false : never) ? true : false;
|
|
190
|
+
type HasGuaranteedOption<Options, Key extends PropertyKey> = [Options] extends [never] ? false : false extends (Options extends unknown ? HasDefinedOption<Options, Key> : never) ? false : true;
|
|
191
|
+
type TestRuntimeOptionLayers<Options extends TestRuntimeOptionsInput> = [...ExplicitOverrides<Options>, ...(HasGuaranteedOption<Options, 'clock'> extends true ? [ClockTestLayer] : []), ...(HasGuaranteedOption<Options, 'logger'> extends true ? [LoggerTestLayer] : []), ...(HasGuaranteedOption<Options, 'random'> extends true ? [RandomSeededLayer] : []), ...(HasGuaranteedOption<Options, 'idGenerator'> extends true ? [IdGeneratorTestLayer] : [])];
|
|
192
|
+
type TestRuntimeValidationLayers<Options extends TestRuntimeOptionsInput> = [...ExplicitOverrides<Options>, ...(HasPotentialOption<Options, 'clock'> extends true ? [ClockTestLayer] : []), ...(HasPotentialOption<Options, 'logger'> extends true ? [LoggerTestLayer] : []), ...(HasPotentialOption<Options, 'random'> extends true ? [RandomSeededLayer] : []), ...(HasPotentialOption<Options, 'idGenerator'> extends true ? [IdGeneratorTestLayer] : [])];
|
|
193
|
+
type TestRuntimeLayer<Base extends LayerInput, Options extends TestRuntimeOptionsInput> = OverrideLayerResult<Base, TestRuntimeOptionLayers<Options>>;
|
|
194
|
+
type TestRuntimeOptionsValidation<Base extends LayerInput, Options extends TestRuntimeOptionsInput> = (Options extends {
|
|
195
|
+
readonly overrides?: infer Overrides extends readonly LayerInput[];
|
|
196
|
+
} ? {
|
|
197
|
+
readonly overrides?: Overrides & ValidateOverrides<Base, Overrides>;
|
|
198
|
+
} : unknown) & ValidateOverridesWitness<Base, TestRuntimeValidationLayers<Options>>;
|
|
199
|
+
type CompleteLayerCheck<L extends LayerInput> = ValidateLayerInput<L> & (LayerInputState<L> extends 'typed' ? [RequiredEnvironment<L>] extends [never] ? unknown : MissingDependencies<Extract<RequiredEnvironment<L>, AnyService>> : unknown);
|
|
200
|
+
type ConfiguredService<Options, Key extends PropertyKey, Service> = Options extends unknown ? Key extends keyof Options ? undefined extends Options[Key] ? undefined : Options[Key] extends Service ? Options[Key] : undefined : undefined : never;
|
|
201
|
+
type TestCallback<Provided extends AnyService, A, Options extends object = {}> = (test: TestRuntime<Provided, Options>) => A | PromiseLike<A>;
|
|
202
|
+
/**
|
|
203
|
+
* Thrown when the TestRuntime recorder contains an execution start or end
|
|
204
|
+
* event without its matching event at final disposal.
|
|
205
|
+
*/
|
|
206
|
+
declare class TestRuntimeObserverError extends Error {
|
|
207
|
+
readonly unmatchedStarts: readonly RuntimeExecutionStartEvent[];
|
|
208
|
+
readonly unmatchedEnds: readonly RuntimeExecutionEndEvent[];
|
|
209
|
+
constructor(unmatchedStarts: readonly RuntimeExecutionStartEvent[], unmatchedEnds: readonly RuntimeExecutionEndEvent[]);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* A disposable test boundary backed by the real Layer and Runtime
|
|
213
|
+
* implementations.
|
|
214
|
+
*/
|
|
215
|
+
declare class TestRuntime<Provided extends AnyService = any, Options extends object = {}> {
|
|
216
|
+
/** The real Runtime used by this testing facade. */
|
|
217
|
+
readonly runtime: Runtime<Provided>;
|
|
218
|
+
/** Lifecycle events recorded by this TestRuntime. */
|
|
219
|
+
readonly observer: RecordedRuntimeObserver;
|
|
220
|
+
readonly clock: ConfiguredService<Options, 'clock', ClockTest>;
|
|
221
|
+
readonly logger: ConfiguredService<Options, 'logger', LoggerTest>;
|
|
222
|
+
readonly random: ConfiguredService<Options, 'random', RandomSeeded>;
|
|
223
|
+
readonly idGenerator: ConfiguredService<Options, 'idGenerator', IdGeneratorTest>;
|
|
224
|
+
private disposalPromise;
|
|
225
|
+
private constructor();
|
|
226
|
+
/** Create a TestRuntime with a fresh backend and default lifecycle recorder. */
|
|
227
|
+
static make<L extends LayerInput>(layer: L & CompleteLayerCheck<L>): Promise<TestRuntime<ProvidedEnvironment<L>>>;
|
|
228
|
+
static make<L extends LayerInput, const Options extends TestRuntimeOptionsInput>(layer: L & ValidateLayerInput<L> & CompleteLayerCheck<TestRuntimeLayer<L, NoInfer<Options>>>, options: Options & TestRuntimeOptionsValidation<L, Options>): Promise<TestRuntime<ProvidedEnvironment<TestRuntimeLayer<L, Options>>, Options>>;
|
|
229
|
+
private static makeInternal;
|
|
230
|
+
/** Run a fully typechecked program in the underlying Runtime. */
|
|
231
|
+
run<A>(program: CompleteExecution<Provided, A>, options?: RuntimeRunOptions): Promise<Awaited<A>>;
|
|
232
|
+
/** Run a fully typechecked program with an execution-local Layer. */
|
|
233
|
+
runWith<Request extends LayerInput, A>(layer: Request & CompleteExecutionLayer<Provided, Request>, program: CompleteExecution<Provided | ProvidedEnvironment<Request>, A>, options?: RuntimeRunOptions): Promise<Awaited<A>>;
|
|
234
|
+
/** Dispose the underlying Runtime and perform the final recorder consistency check. */
|
|
235
|
+
dispose(options?: RuntimeDisposeOptions): Promise<void>;
|
|
236
|
+
/** Release this TestRuntime through JavaScript's async disposal protocol. */
|
|
237
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
238
|
+
private disposeWithOutcome;
|
|
239
|
+
private disposeWithInput;
|
|
240
|
+
private assertObserverConsistency;
|
|
241
|
+
private observerConsistencyFailure;
|
|
242
|
+
/** Run a callback and always dispose this TestRuntime with its final outcome. */
|
|
243
|
+
static use<A, L extends LayerInput>(layer: L & CompleteLayerCheck<L>, use: TestCallback<ProvidedEnvironment<L>, A>): Promise<Awaited<A>>;
|
|
244
|
+
static use<A, L extends LayerInput, const Options extends TestRuntimeOptionsInput>(layer: L & ValidateLayerInput<L> & CompleteLayerCheck<TestRuntimeLayer<L, NoInfer<Options>>>, options: Options & TestRuntimeOptionsValidation<L, Options>, use: TestCallback<ProvidedEnvironment<TestRuntimeLayer<L, Options>>, A, Options>): Promise<Awaited<A>>;
|
|
245
|
+
}
|
|
246
|
+
/** Type-level aliases for TestRuntime configuration. */
|
|
247
|
+
declare namespace TestRuntime {
|
|
248
|
+
/** Options accepted by `TestRuntime.make` and `TestRuntime.use`. */
|
|
249
|
+
type Options<Base extends LayerInput = LayerInput, Overrides extends readonly LayerInput[] = readonly []> = TestRuntimeOptions<Base, Overrides>;
|
|
250
|
+
/** Optional signal supplied to one managed TestRuntime execution. */
|
|
251
|
+
type RunOptions = RuntimeRunOptions;
|
|
252
|
+
/** Cooperative shutdown policy for a managed TestRuntime. */
|
|
253
|
+
type DisposeOptions = RuntimeDisposeOptions;
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
256
|
+
export { ClockTest, ConformanceError, type ContextConcurrency, type ContractScenario, IdGeneratorTest, type LayerBackendAcquisitionFailure, type LayerBackendContractOptions, LoggerTest, MapLayerBackend as MemoryLayerBackend, RandomSeeded, RecordedRuntimeObserver, type RecordedRuntimeObserverSnapshot, type RuntimeContextStorageContractOptions, type RuntimeGraphEdge, type RuntimeGraphNode, RuntimeGraphObserver, type RuntimeGraphObserverOptions, type RuntimeGraphSnapshot, RuntimeObserver, type RuntimeObserverEvent, TestRuntime, TestRuntimeObserverError, type TestRuntimeOptions, layerBackendContract, runtimeContextStorageContract };
|
|
257
|
+
//# sourceMappingURL=testing.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.mts","names":[],"sources":["../src/testing/contracts.ts","../src/testing/recorded-runtime-observer.ts","../src/testing/runtime-graph-observer.ts","../src/testing/test-runtime.ts"],"mappings":"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"}
|