@rotorsoft/act 1.36.0 → 1.37.1

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 (34) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/@types/act.d.ts +0 -38
  3. package/dist/@types/act.d.ts.map +1 -1
  4. package/dist/@types/adapters/in-memory-store.d.ts +0 -4
  5. package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
  6. package/dist/@types/builders/act-builder.d.ts.map +1 -1
  7. package/dist/@types/internal/circuit-breaker.d.ts +0 -7
  8. package/dist/@types/internal/circuit-breaker.d.ts.map +1 -1
  9. package/dist/@types/internal/correlate-cycle.d.ts +0 -18
  10. package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
  11. package/dist/@types/internal/drain-cycle.d.ts +0 -14
  12. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  13. package/dist/@types/internal/settle.d.ts +0 -9
  14. package/dist/@types/internal/settle.d.ts.map +1 -1
  15. package/dist/@types/sensitive.d.ts.map +1 -1
  16. package/dist/{chunk-A3XDAB7T.js → chunk-2H5MBVSQ.js} +3 -2
  17. package/dist/{chunk-A3XDAB7T.js.map → chunk-2H5MBVSQ.js.map} +1 -1
  18. package/dist/{chunk-VWUO5CEG.cjs → chunk-5OU5CTJZ.cjs} +19 -19
  19. package/dist/{chunk-VWUO5CEG.cjs.map → chunk-5OU5CTJZ.cjs.map} +1 -1
  20. package/dist/{chunk-NXURHBSB.cjs → chunk-J6G7UKZA.cjs} +4 -3
  21. package/dist/chunk-J6G7UKZA.cjs.map +1 -0
  22. package/dist/{chunk-P7FXHUMP.js → chunk-SIOPY6HT.js} +8 -8
  23. package/dist/chunk-SIOPY6HT.js.map +1 -0
  24. package/dist/index.cjs +233 -230
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.js +91 -88
  27. package/dist/index.js.map +1 -1
  28. package/dist/test/index.cjs +4 -4
  29. package/dist/test/index.js +2 -2
  30. package/dist/types/index.cjs +2 -2
  31. package/dist/types/index.js +1 -1
  32. package/package.json +1 -1
  33. package/dist/chunk-NXURHBSB.cjs.map +0 -1
  34. package/dist/chunk-P7FXHUMP.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/console-logger.ts","../src/internal/lru-map.ts","../src/adapters/in-memory-cache.ts","../src/config.ts","../src/internal/config.ts","../src/utils.ts","../src/adapters/in-memory-store.ts","../src/disposers.ts","../src/scoped.ts","../src/ports.ts"],"sourcesContent":["/**\n * @module adapters/console-logger\n *\n * High-performance console logger inspired by pino's design:\n * - Numeric level comparison for O(1) gating\n * - stdout.write() in production for raw JSON lines (no console overhead)\n * - Colorized single-line output in development\n * - No-op method replacement when level is above threshold\n * - Child logger support with merged bindings\n */\nimport type { Logger } from \"../types/index.js\";\n\nconst LEVEL_VALUES: Record<string, number> = {\n fatal: 60,\n error: 50,\n warn: 40,\n info: 30,\n debug: 20,\n trace: 10,\n};\n\nconst LEVEL_COLORS: Record<string, string> = {\n fatal: \"\\x1b[41m\\x1b[37m\", // white on red bg\n error: \"\\x1b[31m\", // red\n warn: \"\\x1b[33m\", // yellow\n info: \"\\x1b[32m\", // green\n debug: \"\\x1b[36m\", // cyan\n trace: \"\\x1b[90m\", // gray\n};\n\nconst RESET = \"\\x1b[0m\";\n\nconst noop = () => {};\n\n/**\n * Default console logger for the Act framework.\n *\n * Production mode emits newline-delimited JSON (compatible with GCP, AWS\n * CloudWatch, Datadog, and other structured log ingestion systems).\n *\n * Development mode emits colorized, human-readable output.\n */\nexport class ConsoleLogger implements Logger {\n level: string;\n private readonly _pretty: boolean;\n\n readonly fatal: Logger[\"fatal\"];\n readonly error: Logger[\"error\"];\n readonly warn: Logger[\"warn\"];\n readonly info: Logger[\"info\"];\n readonly debug: Logger[\"debug\"];\n readonly trace: Logger[\"trace\"];\n\n constructor(\n options: {\n level?: string;\n pretty?: boolean;\n bindings?: Record<string, unknown>;\n } = {}\n ) {\n const {\n level = \"info\",\n pretty = process.env.NODE_ENV !== \"production\",\n bindings,\n } = options;\n this._pretty = pretty;\n this.level = level;\n\n const threshold = LEVEL_VALUES[level] ?? 30;\n const write = pretty\n ? this._pretty_write.bind(this, bindings)\n : this._json_write.bind(this, bindings);\n\n // Assign methods — noop when level is gated (like pino's level-based replacement)\n this.fatal = write.bind(this, \"fatal\", 60); // fatal is always enabled\n this.error = threshold <= 50 ? write.bind(this, \"error\", 50) : noop;\n this.warn = threshold <= 40 ? write.bind(this, \"warn\", 40) : noop;\n this.info = threshold <= 30 ? write.bind(this, \"info\", 30) : noop;\n this.debug = threshold <= 20 ? write.bind(this, \"debug\", 20) : noop;\n this.trace = threshold <= 10 ? write.bind(this, \"trace\", 10) : noop;\n }\n\n /** No-op — `console.log` has no resources to release. */\n async dispose(): Promise<void> {}\n\n /** @inheritDoc */\n child(bindings: Record<string, unknown>): Logger {\n return new ConsoleLogger({\n level: this.level,\n pretty: this._pretty,\n bindings,\n });\n }\n\n private _json_write(\n bindings: Record<string, unknown> | undefined,\n level: string,\n _num: number,\n obj_or_msg: unknown,\n msg?: string\n ): void {\n let obj: Record<string, unknown>;\n let message: string | undefined;\n\n if (typeof obj_or_msg === \"string\") {\n message = obj_or_msg;\n obj = {};\n } else if (obj_or_msg instanceof Error) {\n // Error instances spread to `{}` — capture the salient fields\n // explicitly so structured log aggregators see them.\n message = msg ?? obj_or_msg.message;\n obj = {\n error: { message: obj_or_msg.message, name: obj_or_msg.name },\n stack: obj_or_msg.stack,\n };\n } else if (obj_or_msg !== null && typeof obj_or_msg === \"object\") {\n message = msg;\n obj = { ...(obj_or_msg as Record<string, unknown>) };\n } else {\n message = msg;\n obj = { value: obj_or_msg };\n }\n\n const entry = Object.assign({ level, time: Date.now() }, bindings, obj);\n if (message) entry.msg = message;\n\n let line: string;\n try {\n line = JSON.stringify(entry);\n } catch {\n // Cyclic or unserializable payload — emit a minimal line rather\n // than crash the log call site.\n line = JSON.stringify({\n level,\n time: entry.time,\n msg: message ?? \"[unserializable]\",\n unserializable: true,\n });\n }\n process.stdout.write(line + \"\\n\");\n }\n\n private _pretty_write(\n bindings: Record<string, unknown> | undefined,\n level: string,\n _num: number,\n obj_or_msg: unknown,\n msg?: string\n ): void {\n const color = LEVEL_COLORS[level];\n const tag = `${color}${level.toUpperCase().padEnd(5)}${RESET}`;\n const ts = new Date().toISOString().slice(11, 23); // HH:mm:ss.SSS\n\n let message: string;\n let data: string | undefined;\n\n if (typeof obj_or_msg === \"string\") {\n message = obj_or_msg;\n } else if (obj_or_msg instanceof Error) {\n // Error instances don't serialize their `message`/`stack` via\n // JSON.stringify — `JSON.stringify(err) === \"{}\"`. Render the\n // message inline and the stack as the data payload so operators\n // see something useful instead of an empty object.\n message = msg ?? obj_or_msg.message;\n data = obj_or_msg.stack;\n } else {\n message = msg ?? \"\";\n if (obj_or_msg !== undefined && obj_or_msg !== null) {\n try {\n data = JSON.stringify(obj_or_msg);\n } catch {\n data = \"[unserializable]\";\n }\n }\n }\n\n const bind_str =\n bindings && Object.keys(bindings).length\n ? ` ${JSON.stringify(bindings)}`\n : \"\";\n\n const parts = [ts, tag, message, data, bind_str].filter(Boolean);\n process.stdout.write(parts.join(\" \") + \"\\n\");\n }\n}\n","/**\n * Tiny bounded LRU map built on insertion-ordered `Map`. Caps memory in\n * long-running orchestrators that mint large numbers of keys:\n *\n * - {@link InMemoryCache}: stream → state checkpoint\n * - correlate's dynamic subscriptions (stream → priority and lane) and its\n * compiled source patterns\n *\n * Apps with millions of dynamic streams (one target per aggregate) can't\n * afford an unbounded map: eviction is required.\n */\n\n/**\n * Bounded LRU map. `get()` promotes; `has()` does not. `set()` always\n * promotes and evicts the oldest entry when at capacity.\n */\nexport class LruMap<K, V> {\n private readonly _entries = new Map<K, V>();\n private readonly _max_size: number;\n\n constructor(maxSize: number) {\n this._max_size = maxSize;\n }\n\n get(key: K): V | undefined {\n const v = this._entries.get(key);\n if (v === undefined) return undefined;\n // promote: delete + re-insert moves to most-recent position\n this._entries.delete(key);\n this._entries.set(key, v);\n return v;\n }\n\n has(key: K): boolean {\n return this._entries.has(key);\n }\n\n set(key: K, value: V): void {\n this._entries.delete(key);\n if (this._entries.size >= this._max_size) {\n // size >= maxSize ≥ 1 → at least one entry exists → next().value\n // is the oldest key (asserted with `!`).\n const oldest = this._entries.keys().next().value!;\n this._entries.delete(oldest);\n }\n this._entries.set(key, value);\n }\n\n delete(key: K): boolean {\n return this._entries.delete(key);\n }\n\n clear(): void {\n this._entries.clear();\n }\n\n get size(): number {\n return this._entries.size;\n }\n}\n","import { LruMap } from \"../internal/lru-map.js\";\nimport type { Cache, CacheEntry, Schema } from \"../types/index.js\";\n\n/**\n * In-memory LRU cache for stream snapshots.\n *\n * Backed by an internal `LruMap` for O(1) get/set with LRU eviction.\n * Configurable `maxSize` bounds memory usage.\n *\n * @example\n * ```typescript\n * import { cache } from \"@rotorsoft/act\";\n * import { InMemoryCache } from \"@rotorsoft/act\";\n *\n * cache(new InMemoryCache({ maxSize: 500 }));\n * ```\n */\nexport class InMemoryCache implements Cache {\n // CacheEntry<any> lets `get<TState>` and `set<TState>` flow without casts:\n // any is bidirectionally compatible with the per-call TState binding, while\n // the public Cache interface still presents a typed surface to callers.\n private readonly _entries: LruMap<string, CacheEntry<any>>;\n\n constructor(options?: { maxSize?: number }) {\n this._entries = new LruMap(options?.maxSize ?? 1000);\n }\n\n /** @inheritDoc */\n async get<TState extends Schema>(\n stream: string\n ): Promise<CacheEntry<TState> | undefined> {\n return this._entries.get(stream);\n }\n\n /** @inheritDoc */\n async set<TState extends Schema>(\n stream: string,\n entry: CacheEntry<TState>\n ): Promise<void> {\n this._entries.set(stream, entry);\n }\n\n /** @inheritDoc */\n async invalidate(stream: string): Promise<void> {\n this._entries.delete(stream);\n }\n\n /** @inheritDoc */\n async clear(): Promise<void> {\n this._entries.clear();\n }\n\n /** @inheritDoc */\n async dispose(): Promise<void> {\n this._entries.clear();\n }\n\n /** Current number of entries held by the LRU. */\n get size(): number {\n return this._entries.size;\n }\n}\n","/**\n * @packageDocumentation\n * Configuration utilities for Act Framework environment, logging, and package metadata.\n *\n * Provides type-safe configuration loading and validation using Zod schemas.\n *\n * @module config\n */\nimport * as fs from \"node:fs\";\nimport { z } from \"zod\";\nimport { resolveAutocloseConfig as resolve_autoclose } from \"./internal/config.js\";\nimport { log } from \"./ports.js\";\nimport {\n type ActOptions,\n type AutocloseConfig,\n type Config,\n type Environment,\n Environments,\n type LogLevel,\n LogLevels,\n type Package,\n} from \"./types/index.js\";\nimport { extend } from \"./utils.js\";\n\n/**\n * Zod schema for the package.json fields {@link config} validates. Published\n * for tooling that reads the same file, not for apps.\n */\nexport const PackageSchema = z.object({\n name: z.string().min(1),\n version: z.string().min(1),\n description: z.string().min(1).optional(),\n author: z\n .object({ name: z.string().min(1), email: z.string().optional() })\n .optional()\n .or(z.string().min(1))\n .optional(),\n license: z.string().min(1).optional(),\n dependencies: z.record(z.string(), z.string()).optional(),\n}) satisfies z.ZodType<Package>;\n\n/**\n * Fallback package metadata when `package.json` can't be read at module\n * load — happens when the framework is consumed from a CWD that doesn't\n * have one (bundled CLIs, Lambda layers, embedded scripts) or when the\n * file exists but is malformed. `name` and `version` also fall back one by\n * one when the file has no valid value for them.\n *\n * The values are deliberately synthetic so callers spot them immediately:\n * `config().name === \"act-fallback\"` is a runtime signal that the framework\n * couldn't load the host project's package.json.\n *\n * @internal\n */\nconst FALLBACK_PACKAGE: Package = {\n name: \"act-fallback\",\n version: \"0.0.0-fallback\",\n description: \"Synthetic fallback — package.json could not be loaded\",\n};\n\n/**\n * Loads the local package.json as a Package object, keeping each field only\n * when it is valid: `npm init -y` writes an empty `description` and\n * `author`, and a bare `{\"type\":\"module\"}` has no name or version. A\n * missing or invalid `name` / `version` falls back to\n * {@link FALLBACK_PACKAGE}. On a read or parse failure, falls back entirely\n * and stashes the error so {@link config} can surface it on first access —\n * we can't call `log()` here because the logger port memoizes on first\n * call and locking it at module load defeats user injection.\n *\n * @internal\n */\nconst get_package = (): Package => {\n try {\n const raw = JSON.parse(fs.readFileSync(\"package.json\").toString());\n const pkg: Record<string, unknown> = {\n name: FALLBACK_PACKAGE.name,\n version: FALLBACK_PACKAGE.version,\n };\n for (const [key, schema] of Object.entries(PackageSchema.shape)) {\n const field = schema.safeParse(raw?.[key]);\n if (field.success && field.data !== undefined) pkg[key] = field.data;\n }\n return pkg as Package;\n } catch (err) {\n pkg_load_error = err;\n return FALLBACK_PACKAGE;\n }\n};\n\n/** Stashed read/parse error from {@link get_package}, surfaced by config(). */\nlet pkg_load_error: unknown;\n\n/**\n * Zod schema for the full Act Framework configuration object.\n * Includes package metadata, environment, logging, and timing options.\n * @internal\n */\nconst BaseSchema = PackageSchema.extend({\n env: z.enum(Environments),\n logLevel: z.enum(LogLevels),\n logSingleLine: z.boolean(),\n sleepMs: z.number().int().min(0).max(5000),\n}) satisfies z.ZodType<Config>;\n\nconst { NODE_ENV, LOG_LEVEL, LOG_SINGLE_LINE, SLEEP_MS } = process.env;\n\nconst env = (NODE_ENV || \"development\") as Environment;\nconst logLevel = (LOG_LEVEL ||\n (NODE_ENV === \"test\"\n ? \"fatal\"\n : NODE_ENV === \"production\"\n ? \"info\"\n : \"trace\")) as LogLevel;\nconst logSingleLine = (LOG_SINGLE_LINE || \"true\") === \"true\";\nconst sleepMs = parseInt(NODE_ENV === \"test\" ? \"0\" : (SLEEP_MS ?? \"100\"), 10);\n\nconst pkg = get_package();\n\n// Lazily validated on first call. Cannot run extend() at module load\n// because of a utils.ts <-> config.ts cycle (utils imports config for\n// sleep()'s default). Inputs are frozen after import, so the cached\n// result is stable for the life of the process.\nlet _validated: Config | undefined;\n\n/**\n * Gets the current Act Framework configuration.\n *\n * Configuration is loaded from package.json and environment variables, providing\n * type-safe access to application metadata and runtime settings.\n *\n * **Environment Variables:**\n * - `NODE_ENV`: \"development\" | \"test\" | \"staging\" | \"production\" (default: \"development\")\n * - `LOG_LEVEL`: \"fatal\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"trace\"\n * - `LOG_SINGLE_LINE`: \"true\" | \"false\" (default: \"true\")\n * - `SLEEP_MS`: Milliseconds for sleep utility (default: 100, 0 for tests)\n *\n * **Defaults by environment:**\n * - test: logLevel=\"error\", sleepMs=0\n * - production: logLevel=\"info\"\n * - development: logLevel=\"trace\"\n *\n * @returns The validated configuration object\n *\n * @example Basic usage\n * ```typescript\n * import { config } from \"@rotorsoft/act\";\n *\n * const cfg = config();\n * console.log(`App: ${cfg.name} v${cfg.version}`);\n * console.log(`Environment: ${cfg.env}`);\n * console.log(`Log level: ${cfg.logLevel}`);\n * ```\n *\n * @see {@link Config} for configuration type\n */\nexport const config = (): Config => {\n if (!_validated) {\n _validated = extend(\n { ...pkg, env, logLevel, logSingleLine, sleepMs },\n BaseSchema\n );\n if (pkg_load_error) {\n // Surface the fallback once, after _validated is set so the\n // recursive log() → config() call short-circuits. log() resolves\n // through the port singleton — respects user injection and level.\n const msg =\n pkg_load_error instanceof Error\n ? pkg_load_error.message\n : typeof pkg_load_error === \"string\"\n ? pkg_load_error\n : \"unknown error\";\n log().warn(\n `[act] Could not read package.json (${msg}); using synthetic ` +\n `name=\"${FALLBACK_PACKAGE.name}\" version=\"${FALLBACK_PACKAGE.version}\".`\n );\n pkg_load_error = undefined;\n }\n }\n return _validated;\n};\n\n/**\n * Validates and defaults the autoclose knobs of `ActOptions`, the way\n * `act().build()` does. Throws `ZodError` on an out-of-range value.\n */\nexport function resolveAutocloseConfig(\n options: ActOptions | undefined\n): AutocloseConfig {\n return resolve_autoclose(options);\n}\n","/**\n * The single home for every builder-facing config bag in act-core: one\n * section per bag, each with its `DEFAULT_*` constants, an internal\n * `<Type>OptionsSchema`, the inferred `<Type>Config` and a\n * `resolve<Type>Config`, so misconfiguration throws a `ZodError` at the\n * entry point. Validation rejects only what is broken (`NaN`, `±Infinity`,\n * nonsensical negatives) and never newly rejects a value that works. The\n * rules are in .claude/rules/config-validation.md.\n */\n\nimport { z } from \"zod\";\nimport type {\n ActOptions,\n AutocloseConfig,\n CircuitBreakerOptions,\n} from \"../types/act.js\";\nimport type {\n ActionOptions,\n BackoffOptions,\n DrainOptions,\n FoldOptions,\n LaneConfig,\n ReactionOptions,\n SettleOptions,\n ShutdownOptions,\n} from \"../types/index.js\";\n\n// Backoff — retry pacing. Nested inside the reaction/action bags below; also\n// resolvable on its own (`resolveBackoffConfig`) for direct callers.\n\n/**\n * Rejects an off-union `strategy`, a non-finite/negative `baseMs`, or a\n * non-finite/non-positive `maxMs`. Zod 4's `z.number()` rejects\n * `NaN`/`±Infinity` by default, so `.min(0)` / `.gt(0)` also close the\n * non-finite gap. No `maxMs >= baseMs` constraint — a sub-`baseMs` cap on\n * `exponential` is documented behavior, not an error.\n */\nconst BackoffOptionsSchema = z.object({\n strategy: z.enum([\"fixed\", \"linear\", \"exponential\"]),\n baseMs: z.number().min(0),\n maxMs: z.number().gt(0).optional(),\n jitter: z.boolean().optional(),\n});\n\n/**\n * Retry pacing for a reaction that declares no backoff, and for projections\n * and failed fetches, which have no options. Ten seconds, like the default\n * lease; the lease itself only keeps two workers off one stream.\n */\nexport const DEFAULT_BACKOFF: BackoffOptions = {\n strategy: \"fixed\",\n baseMs: 10_000,\n};\n\n/** Validate a backoff bag, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveBackoffConfig(\n options: BackoffOptions | undefined\n): BackoffOptions | undefined {\n return options === undefined\n ? undefined\n : BackoffOptionsSchema.parse(options);\n}\n\n// Reaction — `.do(handler, options)`. `maxRetries` gates the poison-quarantine\n// decision (`retry >= maxRetries`), so a `NaN` here silently disables\n// `blockOnError` (a poison message retries forever). Validate the whole bag.\n\n/** Retries a reaction gets before it blocks, unless `.do()` says otherwise. */\nexport const DEFAULT_MAX_RETRIES = 3;\n/** Whether a reaction blocks its stream once retries run out. */\nexport const DEFAULT_BLOCK_ON_ERROR = true;\n\nconst ReactionOptionsSchema = z.object({\n blockOnError: z.boolean(),\n maxRetries: z.number().int().min(0),\n backoff: BackoffOptionsSchema.optional(),\n});\n\n/** Resolved reaction options. */\nexport type ReactionConfig = z.infer<typeof ReactionOptionsSchema>;\n\n/** Validate a fully-defaulted reaction options bag. Throws `ZodError`. */\nexport function resolveReactionConfig(\n options: ReactionOptions\n): ReactionConfig {\n return ReactionOptionsSchema.parse(options);\n}\n\n// Action — `.on(entry, options)`. `maxRetries` gates the command retry loop's\n// exit (`attempt >= maxRetries`), so a `NaN` here can spin the loop forever on\n// a contended stream. All fields optional (the argument itself is optional).\n\nconst ActionOptionsSchema = z.object({\n maxRetries: z.number().int().min(0).optional(),\n backoff: BackoffOptionsSchema.optional(),\n});\n\n/** Resolved action options. */\nexport type ActionConfig = z.infer<typeof ActionOptionsSchema>;\n\n/** Validate an action options bag. Throws `ZodError`. */\nexport function resolveActionConfig(options: ActionOptions): ActionConfig {\n return ActionOptionsSchema.parse(options);\n}\n\n// Lane — `.withLane({...})`. Per-lane overrides of the drain budget. Time\n// knobs (`leaseMillis` / `cycleMs`) accept any non-negative ms; `streamLimit`\n// is an integer count. Reject NaN/Infinity/negative; allow 0 (as today).\n\nconst LaneConfigSchema = z.object({\n name: z.string().min(1),\n leaseMillis: z.number().min(0).optional(),\n streamLimit: z.number().int().min(0).optional(),\n cycleMs: z.number().min(0).optional(),\n});\n\n/** Validate a lane config. Throws `ZodError`. Returns the input shape. */\nexport function resolveLaneConfig<TName extends string>(\n options: LaneConfig<TName>\n): LaneConfig<TName> {\n LaneConfigSchema.parse(options);\n return options;\n}\n\n// Drain / Settle — runtime knobs for `drain(...)` / `settle(...)`. Parsed once\n// per call (cheap). Reject NaN/Infinity/negative; allow 0. `correlate` is a\n// pass-through query filter (validated by the store), so it is not reshaped.\n\n/** Streams a drain claims per cycle. */\nexport const DEFAULT_STREAM_LIMIT = 10;\n/** Events a drain reads per stream per cycle. */\nexport const DEFAULT_EVENT_LIMIT = 10;\n/** How long a drain holds a stream's lease (ms). */\nexport const DEFAULT_LEASE_MILLIS = 10_000;\n\nconst DrainOptionsSchema = z.object({\n streamLimit: z.number().int().min(0).optional(),\n eventLimit: z.number().int().min(0).optional(),\n leaseMillis: z.number().min(0).optional(),\n});\n\n/** Validate drain options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveDrainConfig(\n options: DrainOptions | undefined\n): DrainOptions | undefined {\n if (options === undefined) return undefined;\n DrainOptionsSchema.parse(options);\n return options;\n}\n\nconst SettleOptionsSchema = DrainOptionsSchema.extend({\n debounceMs: z.number().min(0).optional(),\n // `maxPasses` defaults to Infinity (no cap) when omitted; a present value is\n // a non-negative integer — `0` is legal and means \"run no passes\".\n //\n // `Infinity` is accepted explicitly. It is the documented default\n // (`Act.settle`'s doc-comment and `SettleOptions.maxPasses` both name it),\n // and `settle.ts` destructures `maxPasses = Infinity`, so the one value the\n // docs advertise was the one value `z.number().int()` refused — Zod 4\n // rejects `±Infinity`, and an integer check cannot pass it either. Wrapper\n // code normalizing an optional cap (`maxPasses: opts.maxPasses ?? Infinity`)\n // is the natural way to hit it. Accepting it also honors this module's own\n // rule that a value which works today is never newly rejected.\n maxPasses: z\n .union([z.number().int().min(0), z.literal(Number.POSITIVE_INFINITY)])\n .optional(),\n}).loose();\n\n/** Validate settle options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveSettleConfig(\n options: SettleOptions | undefined\n): SettleOptions | undefined {\n if (options === undefined) return undefined;\n SettleOptionsSchema.parse(options);\n return options;\n}\n\n// Shutdown — the grace budget `shutdown(...)` gives in-flight drain cycles.\n\n/**\n * Ceiling on the derived shutdown grace budget. Without a cap, a lane\n * configured with a long lease (minutes, for a genuinely slow integration)\n * would let one parked handler hold a rolling deploy open for that whole\n * lease. 30s is the longest `leaseMillis` the production checklist\n * recommends, so it is the point past which \"graceful\" stops being the\n * operator's intent.\n */\nexport const MAX_SHUTDOWN_GRACE_MS = 30_000;\n\nconst ShutdownOptionsSchema = z\n .object({\n // `0` is legal and is exactly today's behavior: stop scheduling and\n // return without waiting.\n graceMs: z.number().min(0).optional(),\n })\n .loose();\n\n/** Validate shutdown options, or pass `undefined` through. Throws `ZodError`. */\nexport function resolveShutdownConfig(\n options: ShutdownOptions | undefined\n): ShutdownOptions | undefined {\n if (options === undefined) return undefined;\n ShutdownOptionsSchema.parse(options);\n return options;\n}\n\n// Act — the top-level `act().build(options)` scalar knobs. The nested bags\n// (`autocloseWindow`, `circuitBreaker`) are resolved by their own resolvers\n// below; the `scoped`/`correlator` fields are objects/functions passed\n// through untouched (`.loose()`), so only the scalar knobs are checked here.\n\nconst ActOptionsSchema = z\n .object({\n maxSubscribedStreams: z.number().int().min(1).optional(),\n settleDebounceMs: z.number().int().min(0).optional(),\n autoSettle: z.boolean().optional(),\n })\n .loose();\n\n/** Validate the scalar `ActOptions` knobs at build. Throws `ZodError`. */\nexport function resolveActConfig(\n options: ActOptions | undefined\n): ActOptions | undefined {\n if (options === undefined) return undefined;\n ActOptionsSchema.parse(options);\n return options;\n}\n\n// Autoclose — the off-hours window on `ActOptions`.\n// The window *logic* (DST, hour math) stays in `autoclose-window.ts`; only\n// the schema, defaults, and resolver live here.\n\n/** Default IANA zone for `autocloseWindow` when the operator omits one. */\nconst DEFAULT_AUTOCLOSE_WINDOW_TZ = \"UTC\";\n\n/** True when `tz` is a zone the runtime's `Intl` accepts. */\nfunction is_valid_time_zone(tz: string): boolean {\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: tz });\n return true;\n } catch {\n return false;\n }\n}\n\nconst AutocloseWindowSchema = z\n .object({\n start: z\n .number()\n .int()\n .min(0)\n .max(23, { message: \"autocloseWindow.start must be an hour in [0, 23]\" }),\n end: z\n .number()\n .int()\n .min(0)\n .max(23, { message: \"autocloseWindow.end must be an hour in [0, 23]\" }),\n timeZone: z\n .string()\n .refine(is_valid_time_zone, {\n message: \"autocloseWindow.timeZone must be a valid IANA time zone\",\n })\n .default(DEFAULT_AUTOCLOSE_WINDOW_TZ),\n })\n .refine((w) => w.start !== w.end, {\n message:\n \"autocloseWindow.start and end must differ — an empty window disables autoclose\",\n });\n\nconst AutocloseOptionsSchema = z.object({\n autocloseWindow: AutocloseWindowSchema.optional(),\n}) satisfies z.ZodType<AutocloseConfig>;\n\n/** Validate + default the autoclose knobs on `ActOptions`. Throws `ZodError`. */\nexport function resolveAutocloseConfig(\n options: ActOptions | undefined\n): AutocloseConfig {\n return AutocloseOptionsSchema.parse({\n autocloseWindow: options?.autocloseWindow,\n });\n}\n\n// CircuitBreaker — the store-op breaker on `ActOptions`. The `CircuitBreaker`\n// state machine stays in `circuit-breaker.ts` and imports the resolved type.\n\nconst DEFAULT_CIRCUIT_FAILURE_THRESHOLD = 5;\nconst DEFAULT_CIRCUIT_COOLDOWN_MS = 30_000;\n\nconst CircuitBreakerOptionsSchema = z.object({\n failureThreshold: z\n .number()\n .int()\n .min(1)\n .default(DEFAULT_CIRCUIT_FAILURE_THRESHOLD),\n cooldownMs: z\n .number()\n .int()\n .min(100)\n .max(3_600_000)\n .default(DEFAULT_CIRCUIT_COOLDOWN_MS),\n}) satisfies z.ZodType<CircuitBreakerConfig, CircuitBreakerOptions>;\n\n/** Resolved circuit-breaker configuration. */\nexport type CircuitBreakerConfig = Required<CircuitBreakerOptions>;\n\n/** Parse + apply defaults. Throws `ZodError` on out-of-range values. */\nexport const resolveCircuitBreakerConfig = (\n options?: CircuitBreakerOptions\n): CircuitBreakerConfig => CircuitBreakerOptionsSchema.parse(options ?? {});\n\n// Fold — `projection(name).of(state)` batch-fold knobs.\n\nconst DEFAULT_FOLD_FLUSH_EVERY = 1_000;\nconst DEFAULT_MAX_CACHED_STATES = 10_000;\n\nconst FoldOptionsSchema = z.object({\n flushEvery: z.number().int().min(1).default(DEFAULT_FOLD_FLUSH_EVERY),\n maxCachedStates: z.number().int().min(1).default(DEFAULT_MAX_CACHED_STATES),\n});\n\n/** Resolved fold configuration. */\nexport type FoldConfig = z.infer<typeof FoldOptionsSchema>;\n\n/** Validate + default the fold knobs. Throws `ZodError`. */\nexport function resolveFoldConfig(options: FoldOptions): FoldConfig {\n return FoldOptionsSchema.parse(options);\n}\n","import { prettifyError, ZodError, type ZodType } from \"zod\";\nimport { config } from \"./config.js\";\nimport { ValidationError } from \"./types/index.js\";\n\n/**\n * @module utils\n * @category Utilities\n *\n * Small utilities used across the framework:\n * - {@link validate} — parse a payload against a Zod schema, throwing\n * {@link ValidationError} on failure.\n * - {@link extend} — validate a source object and merge into defaults.\n * - {@link sleep} — async delay (default duration from `config().sleepMs`).\n */\n\n/**\n * Parse `payload` against `schema`, returning the validated value or throwing\n * a {@link ValidationError} with prettified Zod details. When `schema` is\n * omitted, returns `payload` unchanged. The framework calls this for every\n * `app.do()` action, every emitted event, and every state init.\n *\n * @example\n * ```typescript\n * const UserSchema = z.object({ email: z.string().email() });\n * const user = validate(\"User\", { email: \"alice@example.com\" }, UserSchema);\n * ```\n *\n * @see {@link ValidationError}\n */\nexport const validate = <S>(\n target: string,\n payload: Readonly<S>,\n schema?: ZodType<S>\n): Readonly<S> => {\n try {\n return schema ? schema.parse(payload) : payload;\n } catch (error) {\n if (error instanceof ZodError) {\n throw new ValidationError(target, payload, prettifyError(error));\n }\n throw new ValidationError(target, payload, error);\n }\n};\n\n/**\n * Validate `source` against `schema` and return a new object that merges\n * `source` over the optional `target` defaults. Used by {@link config} for\n * env-var-overrides-defaults patterns; safe to call elsewhere — it never\n * mutates `target`.\n *\n * @example\n * ```typescript\n * const schema = z.object({ host: z.string(), port: z.number() });\n * const cfg = extend({ port: 8080 }, schema, { host: \"localhost\", port: 80 });\n * // → { host: \"localhost\", port: 8080 }\n * ```\n *\n * @throws {@link ValidationError} if `source` fails the schema.\n */\nexport const extend = <\n S extends Record<string, unknown>,\n T extends Record<string, unknown>,\n>(\n source: Readonly<S>,\n schema: ZodType<S>,\n target?: Readonly<T>\n): Readonly<S & T> => {\n const value = validate(\"config\", source, schema);\n return { ...target, ...value } as Readonly<S & T>;\n};\n\n/**\n * Pause for `ms` milliseconds (or `config().sleepMs` when omitted — `100ms`\n * in dev, `0ms` in tests). Used by adapters to simulate async I/O.\n *\n * @example\n * ```typescript\n * await sleep(); // default delay from config\n * await sleep(500); // explicit 500ms\n * ```\n */\nexport async function sleep(ms?: number) {\n return new Promise((resolve) => setTimeout(resolve, ms ?? config().sleepMs));\n}\n\n/**\n * Regex metacharacters that, when present in a reaction `source`, make it a\n * pattern rather than a literal stream name. A source containing none of\n * these is a bare stream name — the common case — and every claim/fetch\n * site matches it by string equality on the store's stream index. A source\n * containing any of them is compiled as a RegExp and matched against\n * candidate streams with the caller's own anchoring (e.g. `^(A|B)$`).\n */\nconst SOURCE_METACHARACTERS = /[\\^$.*+?()[\\]{}|\\\\]/;\n\n/**\n * True when `source` is a **literal** stream name — it carries no regex\n * metacharacter, so every adapter treats it as an exact match. This is the\n * fast, index-friendly path and covers every autoclose/dynamic-resolver\n * source (bare stream names). A `false` return means the source is a\n * **pattern** (contains `^ $ . * + ? ( ) [ ] { } | \\`) and must be compiled\n * as a RegExp before matching — the shape the calculator's static\n * `source: \"^(A|B)$\"` reaction relies on.\n *\n * The single source of truth for literal-vs-pattern classification across\n * correlate (which decides what a source marks), the drain fetch path, and\n * the SQLite adapter (which rejects a non-portable pattern), so all three\n * agree on which sources take the exact path.\n *\n * @example\n * ```typescript\n * is_literal_source(\"Board\"); // → true (exact lookup)\n * is_literal_source(\"^(A|B)$\"); // → false (compile as RegExp)\n * ```\n */\nexport function is_literal_source(source: string): boolean {\n return !SOURCE_METACHARACTERS.test(source);\n}\n\n/**\n * Matches an ISO-8601 timestamp, the shape `JSON.stringify` produces for a\n * `Date`.\n *\n * @internal\n */\nconst ISO_8601 =\n /^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(\\.\\d+)?(Z|[+-][0-2][0-9]:[0-5][0-9])?$/;\n\n/**\n * Revive ISO-8601-shaped strings into `Date`s during `JSON.parse`.\n *\n * For host applications that parse Act JSON themselves (an export file, a\n * message forwarded by a webhook) and have no event schema at hand. It turns\n * every timestamp-shaped string into a `Date`, including fields declared as\n * `z.string()`. The framework doesn't use it: it converts only the fields an\n * event's schema declares as `z.date()`.\n */\nexport const dateReviver = (_key: string, value: unknown): unknown =>\n typeof value === \"string\" && ISO_8601.test(value) ? new Date(value) : value;\n","/**\n * @packageDocumentation\n * @module act/adapters\n * In-memory event store adapter for development and tests.\n *\n * @category Adapters\n */\n\nimport { ConcurrencyError } from \"../types/errors.js\";\nimport type {\n BlockedLease,\n Committed,\n EventMeta,\n Lease,\n Message,\n Query,\n QueryStatsOptions,\n QueryStreams,\n QueryStreamsResult,\n Schema,\n Schemas,\n Store,\n StreamFilter,\n StreamPosition,\n StreamStats,\n SubscribeInput,\n} from \"../types/index.js\";\nimport { DEFAULT_LANE, SNAP_EVENT, TOMBSTONE_EVENT } from \"../types/index.js\";\nimport { sleep } from \"../utils.js\";\n\n/**\n * One subscription row: watermark, lease, retry and schedule. Its state is\n * private and changes only through the methods below, which carry the\n * row's rules; the store reads it through the getters.\n */\nclass InMemoryStream {\n readonly stream: string;\n readonly source: string | undefined;\n private _at = -1;\n private _retry = -1;\n private _blocked = false;\n private _error = \"\";\n private _leased_by: string | undefined = undefined;\n private _leased_until: Date | undefined = undefined;\n private _priority: number;\n private _lane: string;\n // While in the future, the stream is held out of `claim`.\n private _deferred_at: number | undefined = undefined;\n // Work mark; `undefined` = never correlated, so `claim` skips it.\n private _correlated_at: number | undefined = undefined;\n\n constructor(\n stream: string,\n source: string | undefined,\n priority = 0,\n lane: string = DEFAULT_LANE\n ) {\n this.stream = stream;\n this.source = source;\n this._priority = priority;\n this._lane = lane;\n }\n\n get at() {\n return this._at;\n }\n\n get retry() {\n return this._retry;\n }\n\n get blocked() {\n return this._blocked;\n }\n\n get error() {\n return this._error;\n }\n\n get leased_by() {\n return this._leased_by;\n }\n\n get leased_until() {\n return this._leased_until;\n }\n\n get priority() {\n return this._priority;\n }\n\n get lane() {\n return this._lane;\n }\n\n get deferred_at() {\n return this._deferred_at;\n }\n\n get correlated_at() {\n return this._correlated_at;\n }\n\n get is_available() {\n return (\n !this._blocked &&\n (!this._leased_until || this._leased_until <= new Date()) &&\n (!this._deferred_at || this._deferred_at <= Date.now())\n );\n }\n\n /**\n * A later subscribe of this row keeps the maximum priority, and takes the\n * new lane only at or above the stored priority (compared before the\n * bump), so a lower-priority resolution can't re-lane the stream. The\n * lane is replaced on every qualifying subscribe, so the current config\n * wins on restart.\n */\n resubscribe(priority: number, lane: string) {\n if (priority >= this._priority) this._lane = lane;\n if (priority > this._priority) this._priority = priority;\n }\n\n /** Operator override; ignores the subscribe-time `max()`. */\n prioritize(priority: number) {\n this._priority = priority;\n }\n\n /** A mark never regresses, including at zero and negatives. */\n mark(correlated_at: number) {\n if (\n this._correlated_at === undefined ||\n correlated_at > this._correlated_at\n )\n this._correlated_at = correlated_at;\n }\n\n defer(deferred_at: number) {\n this._deferred_at = deferred_at;\n // A defer is not a failure, so the redelivery is a fresh attempt.\n this._retry = -1;\n }\n\n // The lease this row hands back, at the given watermark.\n private _lease(lease: Lease, at: number) {\n return {\n stream: this.stream,\n source: this.source,\n at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n lane: this._lane,\n };\n }\n\n lease(lease: Lease, millis: number): Lease {\n // The holder is recorded even at zero `millis`: `ack` is gated on it,\n // so a lease with no holder would drop every ack.\n this._leased_by = lease.by;\n this._leased_until = new Date(Date.now() + millis);\n this._retry = this._retry + 1;\n return this._lease(lease, lease.at);\n }\n\n /** Ack, or with `due`, also persist the schedule. See {@link Store.ack}. */\n ack(lease: Lease) {\n if (this._leased_by === lease.by) {\n this._leased_by = undefined;\n this._leased_until = undefined;\n if (lease.due !== undefined) {\n // Advance past the handled prefix and schedule the re-visit with the\n // caller's retry (-1 for a defer, the climbing count for a backoff).\n this._at = lease.at;\n this._retry = lease.retry;\n this._deferred_at = lease.due;\n return undefined;\n }\n this._retry = -1;\n this._at = lease.at;\n this._deferred_at = undefined;\n return this._lease(lease, this._at);\n }\n }\n\n block(lease: Lease, error: string) {\n // Re-blocking is a no-op, like the SQL `AND blocked = false` guard.\n if (this._leased_by === lease.by && !this._blocked) {\n this._blocked = true;\n this._error = error;\n this._deferred_at = undefined;\n return { ...this._lease(lease, this._at), error };\n }\n }\n\n // Clears the block, the lease and the schedule; retry back to -1.\n private _release() {\n this._retry = -1;\n this._blocked = false;\n this._error = \"\";\n this._leased_by = undefined;\n this._leased_until = undefined;\n this._deferred_at = undefined;\n }\n\n /** Retry resets to -1 (released); the next claim makes it 0. */\n reset() {\n this._at = -1;\n this._release();\n }\n\n /** True only when the stream was blocked. */\n unblock(): boolean {\n if (!this._blocked) return false;\n this._release();\n return true;\n }\n}\n\n/**\n * Tests a name against a stream or source filter: exact, or a regex\n * compiled once.\n */\nconst name_test = (\n pattern: string,\n exact?: boolean\n): ((name: string) => boolean) => {\n if (exact) return (name) => name === pattern;\n const re = new RegExp(pattern);\n return (name) => re.test(name);\n};\n\n/**\n * In-memory event store: the default when no other store is injected.\n * For development, tests and examples; all data is lost when the process\n * exits. Use {@link PostgresStore} in production.\n *\n * `Store.notify` is not implemented: a single process has no remote writer\n * to hear from, and local commits already arm the drain.\n *\n * @example Using in tests\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n *\n * describe(\"Counter\", () => {\n * beforeEach(async () => {\n * // Reset store between tests\n * await store().seed();\n * });\n *\n * it(\"increments\", async () => {\n * await app.do(\"increment\", target, { by: 5 });\n * const snapshot = await app.load(Counter, \"counter-1\");\n * expect(snapshot.state.count).toBe(5);\n * });\n * });\n * ```\n *\n * @see {@link Store} for the interface definition\n * @see {@link PostgresStore} for production use\n * @see {@link store} for injecting stores\n *\n * @category Adapters\n */\nexport class InMemoryStore implements Store {\n private _events: Committed<Schemas, keyof Schemas>[] = [];\n // Never reused. Deletions punch holes, so ids are not array indexes.\n private _next_id = 0;\n private _streams: Map<string, InMemoryStream> = new Map();\n // Correlate checkpoint: how far the log has been READ.\n private _correlated_at = -1;\n // Per-correlator checkpoint and lease; keyless callers use `_correlated_at`.\n private _correlators = new Map<\n string,\n { at: number; by: string; until: number }\n >();\n private _stream_versions: Map<string, number> = new Map();\n // stream → (event_id → cloned pii). Two levels so `forget_pii` drops one\n // inner Map. Absence means no PII.\n private _pii: Map<string, Map<number, Record<string, unknown>>> = new Map();\n\n private _reset_indexes() {\n this._events.length = 0;\n this._next_id = 0;\n this._correlated_at = -1;\n this._stream_versions.clear();\n this._pii.clear();\n }\n\n // Stores a cloned copy, so caller-side mutation can't reach it.\n private _put_pii(stream: string, id: number, pii: Record<string, unknown>) {\n let per_stream = this._pii.get(stream);\n if (!per_stream) {\n per_stream = new Map();\n this._pii.set(stream, per_stream);\n }\n per_stream.set(id, structuredClone(pii));\n }\n\n // First index whose id is greater than `after` (ids are sorted, not dense).\n private _first_index_after(after: number): number {\n let lo = 0;\n let hi = this._events.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (this._events[mid].id > after) hi = mid;\n else lo = mid + 1;\n }\n return lo;\n }\n\n // Allocation-free for events without PII, the common case.\n private _with_pii<E extends Schemas>(\n e: Committed<E, keyof E>,\n wanted = true\n ): Committed<E, keyof E> {\n if (!wanted) return e;\n const pii = this._pii.get(e.stream)?.get(e.id);\n return pii ? ({ ...e, pii } as Committed<E, keyof E>) : e;\n }\n\n async dispose() {\n await sleep();\n this._reset_indexes();\n }\n\n async seed() {\n await sleep();\n }\n\n async drop() {\n await sleep();\n this._reset_indexes();\n this._streams = new Map();\n }\n\n private _in_query(\n query: Query\n ): (e: Committed<Schemas, keyof Schemas>) => boolean {\n const stream_ok = query.stream\n ? name_test(query.stream, query.stream_exact)\n : undefined;\n return (e) => {\n if (stream_ok && !stream_ok(e.stream)) return false;\n if (query.names && !query.names.includes(e.name as string)) return false;\n if (query.correlation && e.meta?.correlation !== query.correlation)\n return false;\n if (e.name === SNAP_EVENT && !query.with_snaps) return false;\n // `created` is not monotonic with `id` (restore keeps it), so time\n // bounds filter; they never end the scan.\n if (query.created_after && e.created <= query.created_after) return false;\n if (query.created_before && e.created >= query.created_before)\n return false;\n return true;\n };\n }\n\n // Index of the stream's latest snapshot, or -1; an explicit `after` wins.\n private _snap_floor(query: Query | undefined): number {\n if (\n !query?.with_snaps ||\n !query.stream_exact ||\n query.stream === undefined ||\n query.after !== undefined\n )\n return -1;\n for (let j = this._events.length - 1; j >= 0; j--) {\n const e = this._events[j];\n if (e.stream === query.stream && e.name === SNAP_EVENT) return j;\n }\n return -1;\n }\n\n async query<E extends Schemas>(\n callback: (event: Committed<E, keyof E>) => void,\n query?: Query\n ) {\n await sleep();\n // The id bounds (`after`, `before`, the snapshot floor) are one index\n // window over the id-ordered log; every other filter is per event.\n const floor = this._snap_floor(query);\n const lo = floor >= 0 ? floor : this._first_index_after(query?.after ?? -1);\n const hi =\n query?.before !== undefined\n ? this._first_index_after(query.before - 1)\n : this._events.length;\n const with_pii = query?.with_pii !== false;\n const in_query = this._in_query(query ?? {});\n let count = 0;\n for (let k = 0; k < hi - lo; k++) {\n const e = this._events[query?.backward ? hi - 1 - k : lo + k];\n if (!in_query(e)) continue;\n await Promise.resolve(\n callback(this._with_pii(e as Committed<E, keyof E>, with_pii))\n );\n count++;\n if (query?.limit && count >= query.limit) break;\n }\n return count;\n }\n\n async commit<E extends Schemas>(\n stream: string,\n msgs: Message<E, keyof E>[],\n meta: EventMeta,\n expectedVersion?: number\n ) {\n await sleep();\n const current_version = this._stream_versions.get(stream) ?? -1;\n if (\n typeof expectedVersion === \"number\" &&\n current_version !== expectedVersion\n ) {\n throw new ConcurrencyError(\n stream,\n current_version,\n msgs as Message<Schemas, keyof Schemas>[],\n expectedVersion\n );\n }\n\n let version = current_version + 1;\n const committed = msgs.map(({ name, data, pii }) => {\n const c: Committed<E, keyof E> = {\n id: this._next_id++,\n stream,\n version,\n created: new Date(),\n name,\n data,\n meta,\n };\n // Stored pii-less, so `forget_pii` never touches the event row.\n this._events.push(c as Committed<Schemas, keyof Schemas>);\n if (pii != null) this._put_pii(stream, c.id, pii);\n version++;\n return this._with_pii(c);\n });\n this._stream_versions.set(stream, version - 1);\n return committed;\n }\n\n async claim(\n lagging: number,\n leading: number,\n by: string,\n millis: number,\n lane?: string\n ) {\n await sleep();\n // Eligibility is `at < correlated_at` on the row alone; the event log\n // is never read. An unmarked row is not claimable.\n const has_work = (s: InMemoryStream): boolean =>\n s.correlated_at !== undefined && s.at < s.correlated_at;\n const available = [...this._streams.values()].filter(\n (s) =>\n s.is_available && has_work(s) && (lane === undefined || s.lane === lane)\n );\n // Lagging: priority DESC, then watermark ASC, like the PG SQL. The\n // `fair` slots ignore priority so sustained high-priority load can't\n // starve a default-priority stream.\n const fair = lagging >= 2 ? Math.max(1, Math.floor(lagging / 4)) : 0;\n const by_priority = [...available].sort(\n (a, b) => b.priority - a.priority || a.at - b.at\n );\n const priority_slice = by_priority.slice(0, lagging - fair);\n const picked = new Set(priority_slice.map((s) => s.stream));\n const fair_slice = [...available]\n .sort((a, b) => a.at - b.at)\n .filter((s) => !picked.has(s.stream))\n .slice(0, fair);\n const lag = [...priority_slice, ...fair_slice].map((s) => ({\n stream: s.stream,\n source: s.source,\n at: s.at,\n lagging: true,\n }));\n const lead = available\n .sort((a, b) => b.at - a.at)\n .slice(0, leading)\n .map((s) => ({\n stream: s.stream,\n source: s.source,\n at: s.at,\n lagging: false,\n }));\n const seen = new Set<string>();\n const combined = [...lag, ...lead].filter((p) => {\n if (seen.has(p.stream)) return false;\n seen.add(p.stream);\n return true;\n });\n return combined\n .map((p) =>\n this._streams.get(p.stream)?.lease({ ...p, by, retry: 0 }, millis)\n )\n .filter((l) => !!l);\n }\n\n async subscribe(\n streams: SubscribeInput[],\n correlated_at?: number,\n correlator?: { key: string; by: string; millis: number }\n ) {\n await sleep();\n\n // The checkpoint is monotonic. With a correlator, position and lease\n // are per key.\n let correlating: boolean | undefined;\n let keyed_at: number | undefined;\n if (correlator) {\n const now = Date.now();\n const held = this._correlators.get(correlator.key);\n // A key with no row yet inherits the shared position, so a new\n // correlator does not re-read history.\n const at = Math.max(held?.at ?? this._correlated_at, correlated_at ?? -1);\n keyed_at = at;\n if (!held || held.until < now || held.by === correlator.by) {\n correlating = true;\n this._correlators.set(correlator.key, {\n at,\n by: correlator.by,\n // Release outright, or a successor in the same ms is still refused.\n until: correlator.millis > 0 ? now + correlator.millis : 0,\n });\n } else {\n // Refused, but the position still advances: this caller may already\n // have scanned and marked.\n correlating = false;\n held.at = at;\n }\n // How far any correlator has read.\n if (correlated_at !== undefined && correlated_at > this._correlated_at)\n this._correlated_at = correlated_at;\n } else if (\n correlated_at !== undefined &&\n correlated_at > this._correlated_at\n )\n this._correlated_at = correlated_at;\n\n let subscribed = 0;\n for (const {\n stream,\n source,\n priority = 0,\n lane = DEFAULT_LANE,\n correlated_at,\n } of streams) {\n const existing = this._streams.get(stream);\n if (existing) {\n existing.resubscribe(priority, lane);\n if (correlated_at !== undefined) existing.mark(correlated_at);\n } else {\n const created = new InMemoryStream(stream, source, priority, lane);\n if (correlated_at !== undefined) created.mark(correlated_at);\n this._streams.set(stream, created);\n subscribed++;\n }\n }\n let watermark = -1;\n for (const s of this._streams.values()) {\n if (s.at > watermark) watermark = s.at;\n }\n return {\n subscribed,\n watermark,\n correlated_at: keyed_at ?? this._correlated_at,\n ...(correlating === undefined ? {} : { correlating }),\n };\n }\n\n async ack(leases: Lease[]) {\n await sleep();\n // One synchronous pass: the in-memory form of the single transaction.\n return leases\n .map((l) => this._streams.get(l.stream)?.ack(l))\n .filter((l) => !!l);\n }\n\n async block(leases: BlockedLease[]) {\n await sleep();\n return leases\n .map((l) => this._streams.get(l.stream)?.block(l, l.error))\n .filter((l) => !!l);\n }\n\n async defer(input: string[] | StreamFilter, deferred_at: number) {\n await sleep();\n const selected = this._select(input);\n for (const s of selected) s.defer(deferred_at);\n return selected.length;\n }\n\n // De-duplicated like the SQL `stream = ANY(...)`; unknown names skipped.\n private _select(input: string[] | StreamFilter): InMemoryStream[] {\n if (Array.isArray(input))\n return [...new Set(input)]\n .map((name) => this._streams.get(name))\n .filter((s) => s !== undefined);\n return [...this._streams.values()].filter(this._filter_predicate(input));\n }\n\n private _filter_predicate(\n filter: StreamFilter\n ): (s: InMemoryStream) => boolean {\n const stream_ok =\n filter.stream !== undefined\n ? name_test(filter.stream, filter.stream_exact)\n : undefined;\n const source_ok =\n filter.source !== undefined\n ? name_test(filter.source, filter.source_exact)\n : undefined;\n return (s) => {\n if (stream_ok && !stream_ok(s.stream)) return false;\n if (source_ok && (s.source === undefined || !source_ok(s.source)))\n return false;\n if (filter.blocked !== undefined && s.blocked !== filter.blocked)\n return false;\n if (filter.lane !== undefined && s.lane !== filter.lane) return false;\n return true;\n };\n }\n\n async reset(input: string[] | StreamFilter) {\n await sleep();\n const selected = this._select(input);\n for (const s of selected) s.reset();\n return selected.length;\n }\n\n async forget_pii(stream: string): Promise<number> {\n await sleep();\n const count = this._pii.get(stream)?.size ?? 0;\n this._pii.delete(stream);\n return count;\n }\n\n async unblock(input: string[] | StreamFilter) {\n await sleep();\n const selected = this._select(\n Array.isArray(input) ? input : { ...input, blocked: true }\n );\n return selected.filter((s) => s.unblock()).length;\n }\n\n async prioritize(filter: StreamFilter, priority: number) {\n await sleep();\n const changed = this._select(filter).filter((s) => s.priority !== priority);\n for (const s of changed) s.prioritize(priority);\n return changed.length;\n }\n\n async query_streams(\n callback: (position: StreamPosition) => void,\n query?: QueryStreams\n ): Promise<QueryStreamsResult> {\n await sleep();\n const limit = query?.limit ?? 100;\n const after = query?.after;\n const source_matches = query?.source_matches;\n const matches = this._filter_predicate(query ?? {});\n // Reverse-match: the stored `source` pattern must match a requested name.\n const reverse_cache = new Map<string, RegExp>();\n const reverse_match = (source: string): boolean => {\n let re = reverse_cache.get(source);\n if (!re) {\n re = new RegExp(source);\n reverse_cache.set(source, re);\n }\n return source_matches!.some((name) => re!.test(name));\n };\n\n // The default sort is code-unit order, which agrees with the `<=`\n // cursor and the SQL binary collation; `localeCompare` would not.\n const sorted = [...this._streams.keys()]\n .sort()\n .map((stream) => this._streams.get(stream) as InMemoryStream);\n\n let count = 0;\n for (const s of sorted) {\n if (after !== undefined && s.stream <= after) continue;\n if (!matches(s)) continue;\n if (source_matches !== undefined) {\n // No source consumes every stream, so it matches any name.\n if (s.source && !reverse_match(s.source)) continue;\n }\n // Before emitting, so `limit: 0` returns none.\n if (count >= limit) break;\n callback({\n stream: s.stream,\n source: s.source,\n at: s.at,\n retry: s.retry,\n blocked: s.blocked,\n error: s.error,\n priority: s.priority,\n leased_by: s.leased_by,\n leased_until: s.leased_until,\n lane: s.lane,\n deferred_at: s.deferred_at,\n correlated_at: s.correlated_at,\n });\n count++;\n }\n return { maxEventId: this._events.at(-1)?.id ?? -1, count };\n }\n\n async query_stats<E extends Schemas>(\n input: string[] | Pick<StreamFilter, \"stream\" | \"stream_exact\">,\n options?: QueryStatsOptions<E>\n ): Promise<Map<string, StreamStats<E>>> {\n await sleep();\n const exclude = new Set<string>(options?.exclude ?? []);\n const want_tail = options?.tail ?? false;\n const want_count = options?.count ?? false;\n const want_names = options?.names ?? false;\n const before = options?.before;\n const after = options?.after;\n const limit = options?.limit;\n\n const array_targets = Array.isArray(input) ? new Set(input) : null;\n const stream_ok =\n !Array.isArray(input) && input.stream !== undefined\n ? name_test(input.stream, input.stream_exact)\n : undefined;\n\n const scope_cache = new Map<string, boolean>();\n const in_scope = (stream: string): boolean => {\n const cached = scope_cache.get(stream);\n if (cached !== undefined) return cached;\n const ok = array_targets\n ? array_targets.has(stream)\n : (stream_ok?.(stream) ?? true);\n scope_cache.set(stream, ok);\n return ok;\n };\n\n type Acc = {\n head: Committed<Schemas, keyof Schemas>;\n tail?: Committed<Schemas, keyof Schemas>;\n count: number;\n names?: Record<string, number>;\n };\n const acc = new Map<string, Acc>();\n for (const e of this._events) {\n if (before !== undefined && e.id >= before) continue;\n if (!in_scope(e.stream)) continue;\n if (exclude.has(e.name as string)) continue;\n let a = acc.get(e.stream);\n if (!a) {\n a = { head: e, count: 0 };\n if (want_tail) a.tail = e;\n if (want_names) a.names = {};\n acc.set(e.stream, a);\n }\n a.head = e;\n a.count++;\n if (want_names) {\n const n = String(e.name);\n a.names![n] = (a.names![n] ?? 0) + 1;\n }\n }\n\n // Code-unit order, to agree with the `<=` cursor (see query_streams).\n const ordered = [...acc.keys()].sort();\n const out = new Map<string, StreamStats<E>>();\n for (const stream of ordered) {\n if (limit !== undefined && out.size >= limit) break;\n if (after !== undefined && stream <= after) continue;\n const a = acc.get(stream)!;\n const stats: {\n head: Committed<Schemas, keyof Schemas>;\n tail?: Committed<Schemas, keyof Schemas>;\n count?: number;\n names?: Record<string, number>;\n } = { head: a.head };\n if (want_tail) stats.tail = a.tail;\n if (want_count) stats.count = a.count;\n if (want_names) stats.names = a.names;\n out.set(stream, stats as StreamStats<E>);\n }\n return out;\n }\n\n async truncate(\n targets: Array<{\n stream: string;\n snapshot?: Schema;\n meta?: EventMeta;\n before?: Date;\n max_id?: number;\n }>\n ) {\n await sleep();\n const result = new Map<\n string,\n {\n deleted: number;\n committed: Committed<Schemas, keyof Schemas>;\n before?: Date;\n }\n >();\n\n // Per target, like the SQL adapters: a later target sees what an\n // earlier one in the same call already pruned.\n const windowed = targets.filter((t) => t.before !== undefined);\n for (const { stream, before, max_id } of windowed) {\n let boundary: Committed<Schemas, keyof Schemas> | undefined;\n for (const e of this._events) {\n if (\n e.stream === stream &&\n e.name === SNAP_EVENT &&\n e.created < before! &&\n (max_id === undefined || e.id <= max_id) &&\n (!boundary || e.id > boundary.id)\n )\n boundary = e;\n }\n if (!boundary) continue; // no qualifying snapshot → no-op\n const below = boundary.id;\n let deleted = 0;\n this._events = this._events.filter((e) => {\n if (e.stream !== stream || e.id >= below) return true;\n this._pii.get(stream)?.delete(e.id);\n deleted++;\n return false;\n });\n result.set(stream, { deleted, committed: boundary, before });\n }\n\n const full = targets.filter((t) => t.before === undefined);\n // Per target, like the SQL adapters, so a stream listed twice gets one seed.\n for (const { stream, snapshot, meta } of full) {\n let deleted = 0;\n this._events = this._events.filter((e) => {\n if (e.stream !== stream) return true;\n deleted++;\n return false;\n });\n // Subscriptions untouched; `seed()` reaps inert ones.\n this._stream_versions.delete(stream);\n this._pii.delete(stream);\n const event: Committed<Schemas, keyof Schemas> = {\n id: this._next_id++,\n stream,\n version: 0,\n created: new Date(),\n name: snapshot !== undefined ? SNAP_EVENT : TOMBSTONE_EVENT,\n data: snapshot ?? {},\n meta: meta ?? { correlation: \"\", causation: {} },\n };\n this._events.push(event);\n this._stream_versions.set(stream, 0);\n result.set(stream, { deleted, committed: event });\n }\n return result;\n }\n\n /** A throw inside the driver restores the captured state. Ids restart at 0. */\n async restore(\n driver: (\n callback: (event: Committed<Schemas, keyof Schemas>) => Promise<number>\n ) => Promise<void>\n ): Promise<void> {\n await sleep();\n const prev_events = this._events;\n const prev_next_id = this._next_id;\n const prev_streams = this._streams;\n const prev_stream_versions = this._stream_versions;\n const prev_pii = this._pii;\n const prev_correlated_at = this._correlated_at;\n const prev_correlators = new Map(\n [...this._correlators].map(([k, v]) => [k, { ...v }])\n );\n // Renumbered from 0, so checkpoints restart too; leases are kept.\n this._correlated_at = -1;\n for (const c of this._correlators.values()) c.at = -1;\n this._events = [];\n this._next_id = 0;\n this._streams = new Map();\n this._stream_versions = new Map();\n this._pii = new Map();\n try {\n await driver(async (event) => {\n const id = this._next_id++;\n // Split `pii` out like `commit`, so `forget_pii` erases restored PII.\n const { pii, ...rest } = event;\n const committed: Committed<Schemas, keyof Schemas> = { ...rest, id };\n this._events.push(committed);\n if (pii != null) this._put_pii(event.stream, id, pii);\n // Last event per stream wins.\n this._stream_versions.set(event.stream, event.version);\n return id;\n });\n } catch (err) {\n this._events = prev_events;\n this._next_id = prev_next_id;\n this._streams = prev_streams;\n this._stream_versions = prev_stream_versions;\n this._pii = prev_pii;\n this._correlated_at = prev_correlated_at;\n this._correlators = prev_correlators;\n throw err;\n }\n }\n}\n","import type { Disposer } from \"./types/index.js\";\n\n/**\n * The shape {@link register_weak_disposer} needs from a `WeakRef`. Declared\n * structurally so tests can hand in a stub that reports its target as\n * collected — real garbage collection is not schedulable, and a guarantee\n * about releasing memory deserves a deterministic test.\n */\nexport type RefLike<T extends object> = { deref: () => T | undefined };\n\n/**\n * A registered cleanup function, optionally tied to the lifetime of the\n * object it cleans up. `ref` present means \"run this only while its target\n * is still reachable\" — the entry holds no strong reference to that target,\n * so registering never keeps it alive. The target is handed back to `run`,\n * so a weak disposer never has to re-check what the registry just proved.\n */\ntype Entry = {\n readonly run: (target: never) => Promise<void>;\n readonly ref?: RefLike<object>;\n};\n\n/** Registered cleanup functions, executed in reverse order during shutdown. */\nconst entries: Entry[] = [];\n\n/**\n * Drop entries whose target has been collected.\n *\n * Called on every registration so the registry stays proportional to the\n * live objects rather than to every object ever built. That matters for apps\n * that mint short-lived Acts — one per tenant, per request, per test — where\n * the registry would otherwise grow without bound for the process lifetime.\n */\nconst prune = (): void => {\n for (let i = entries.length - 1; i >= 0; i--) {\n const { ref } = entries[i];\n if (ref && !ref.deref()) entries.splice(i, 1);\n }\n};\n\n/** Register a cleanup function that runs unconditionally at teardown. */\nexport const register_disposer = (run: Disposer): void => {\n prune();\n entries.push({ run });\n};\n\n/**\n * Register a cleanup function bound to `ref`'s target, held weakly.\n *\n * The registry never retains the target, so an object that becomes\n * unreachable is collectable whether or not it was cleaned up first, and its\n * entry is skipped at teardown — there is nothing left to clean up.\n */\nexport const register_weak_disposer = <T extends object>(\n ref: RefLike<T>,\n run: (target: T) => Promise<void>\n): void => {\n prune();\n entries.push({\n run: run as (target: never) => Promise<void>,\n ref: ref as RefLike<object>,\n });\n};\n\n/**\n * Run every live disposer in reverse registration order, sequentially, so a\n * disposer can rely on later-registered ones having already finished.\n *\n * Registrations are left in place, so a second teardown call re-runs them,\n * exactly as before this registry learned about weak entries.\n */\nexport const run_disposers = async (): Promise<void> => {\n for (const { run, ref } of [...entries].reverse()) {\n if (!ref) {\n await (run as Disposer)();\n continue;\n }\n const target = ref.deref();\n if (target) await (run as (t: object) => Promise<void>)(target);\n }\n};\n","/**\n * @module scoped\n * @category Internal\n *\n * Ambient execution context — every `AsyncLocalStorage` the framework owns\n * lives here, and so does every operation on one. No other module calls\n * `.run()` or `.getStore()`; they ask for a runner or a reader instead, so\n * this file is the single place to look at the abstraction.\n *\n * Two contexts:\n *\n * - **ports** — the active Act's store/cache bag, so `store()` / `cache()`\n * resolve per-Act rather than per-process. Installed by the\n * orchestrator via {@link make_run_scoped}, read by the port singletons\n * via {@link current_ports}.\n * - **reaction** — the event a handler is processing, so a dispatch made\n * anywhere inside that handler can thread `reactingTo` whichever `IAct`\n * reference made the call. Installed via {@link run_reacting},\n * read at the orchestrator boundary via {@link current_reacting}.\n *\n * Keeping the mechanics here keeps ambient state out of `internal/`, whose\n * modules are stateless implementations that receive what they need.\n *\n * @internal\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Actor, Committed, IAct, Schemas, Scoped } from \"./types/index.js\";\n\n/**\n * What an Act actually installs in its frame: the ports a caller passed,\n * plus per-Act settings that runtime code has to read from the *running*\n * Act rather than from whatever closure it was built in.\n *\n * `autoclose_window` is here because the autoclose reactions are\n * synthesized once into the shared registry and handed by reference to\n * every Act built from that builder, so a window captured at synthesis is\n * the first tenant's window for everyone. The frame is per-Act, so\n * reading it here is what makes the setting per-Act too.\n *\n * Wider than {@link Scoped} on purpose: `Scoped` types what a caller\n * *passes* through `ActOptions.scoped` and is public; this is what the\n * orchestrator *installs* and is not.\n *\n * @internal\n */\nexport type ActFrame = Scoped & {\n readonly autoclose_window?: {\n readonly start: number;\n readonly end: number;\n readonly timeZone: string;\n };\n};\n\n/**\n * AsyncLocalStorage carrying the active Act's ports.\n *\n * Exported for in-repo tooling that measures the context itself (the\n * scope-overhead bench). NOT public: `ports.ts` no longer re-exports it and\n * `index.ts` reaches this module only for the `Scoped` type, so it is not\n * importable from the package. Everything else uses the helpers below.\n */\nexport const scoped = new AsyncLocalStorage<ActFrame>();\n\n/**\n * The reaction currently running, as a box the handler can empty.\n *\n * A frame captured by work the handler started and did not await outlives the\n * handler and can never be unbound. The *frame* is unreclaimable, but the\n * *box inside it* is not: clearing `event` as the handler settles turns every\n * later read through that frame into \"no reaction\", without anyone having to\n * ask a second question.\n *\n * Not reachable from `index.ts`.\n */\ntype Reacting = { event: Committed<Schemas, string> | undefined };\n\nconst reacting = new AsyncLocalStorage<Reacting>();\n\n/**\n * Builds the runner an Act uses to enter its own port scope.\n *\n * Every Act gets a frame, including one built without `ActOptions.scoped` —\n * that one carries the singleton adapters (see `default_scope` in `ports.ts`).\n * Entering unconditionally is what makes an Act's ports its own: a runner that\n * collapsed to `fn()` for a singleton Act did not leave whatever frame it was\n * called from, so dispatching into a shared Act from inside a tenant's handler\n * resolved `store()` to that tenant and wrote the shared Act's events into the\n * tenant's log.\n *\n * @internal\n */\nexport function make_run_scoped(\n bag: ActFrame\n): <T>(fn: () => Promise<T>) => Promise<T> {\n return (fn) => scoped.run(bag, fn);\n}\n\n/**\n * The running Act's off-hours autoclose window, or `undefined` when it\n * declared none (or when read outside any Act).\n *\n * Read at resolution time rather than captured at synthesis: the autoclose\n * reactions belong to the shared registry, and only the frame knows which\n * Act is running them.\n *\n * @internal\n */\nexport function current_autoclose_window(): ActFrame[\"autoclose_window\"] {\n return scoped.getStore()?.autoclose_window;\n}\n\n/**\n * The active Act's ports, or `undefined` outside any Act.\n *\n * Every Act runs in a frame, so this is `undefined` only for a call made\n * outside one — `store()` and `cache()` fall back to the singleton adapters\n * there, which is what a bare `store()` in application setup expects.\n *\n * @internal\n */\nexport function current_ports(): Scoped | undefined {\n return scoped.getStore();\n}\n\n/**\n * Runs `fn` with `event` installed as the triggering-event context.\n *\n * Entered per payload rather than per lease: the context has to unwind with\n * the handler so it never reaches the drain cycle, and work a handler started\n * without awaiting has to resume into its own event's frame.\n *\n * @internal\n */\nfunction run_reacting<T>(\n event: Committed<Schemas, string>,\n fn: () => Promise<T>\n): Promise<T> {\n const box: Reacting = { event };\n return reacting.run(box, async () => {\n try {\n return await fn();\n } finally {\n // Anything still running keeps this frame; from here it reads empty.\n box.event = undefined;\n }\n });\n}\n\n/**\n * The event being reacted to, or `undefined` outside a running handler —\n * including inside work that outlived one.\n *\n * @internal\n */\nexport function current_reacting(): Committed<Schemas, string> | undefined {\n return reacting.getStore()?.event;\n}\n\n/**\n * Everything a reaction handler runs inside: the `IAct` facade it is handed\n * as its third argument, and the triggering-event context that every dispatch\n * made within it resolves — including one through a captured `app`.\n *\n * Built here rather than in the dispatcher so the dispatcher never has to\n * know how either half works; it receives this whole and calls it.\n *\n * @internal\n */\nexport type ReactionScope<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n> = {\n readonly app: IAct<TEvents, TActions, TActor>;\n readonly run: <T>(\n event: Committed<Schemas, string>,\n fn: () => Promise<T>\n ) => Promise<T>;\n};\n\n/**\n * Assembles the reaction scope from the orchestrator's bound `IAct` methods.\n *\n * @internal\n */\nexport function make_reaction_scope<\n TEvents extends Schemas,\n TActions extends Schemas,\n TActor extends Actor = Actor,\n>(\n app: IAct<TEvents, TActions, TActor>\n): ReactionScope<TEvents, TActions, TActor> {\n return { app, run: run_reacting };\n}\n","import { ConsoleLogger } from \"./adapters/console-logger.js\";\nimport { InMemoryCache } from \"./adapters/in-memory-cache.js\";\nimport { InMemoryStore } from \"./adapters/in-memory-store.js\";\nimport { config } from \"./config.js\";\nimport { register_disposer, run_disposers } from \"./disposers.js\";\nimport { current_ports } from \"./scoped.js\";\nimport type {\n Cache,\n Disposable,\n Disposer,\n ExitCode,\n Logger,\n Scoped,\n Store,\n} from \"./types/index.js\";\n\n/**\n * Port/adapter infrastructure for the Act framework.\n *\n * All infrastructure concerns (logging, storage, caching) are managed as\n * singleton adapters injected via port functions. Each port follows the same\n * pattern: first call wins with a sensible default, optional adapter injection.\n *\n * - `log()` — structured logging (default: ConsoleLogger)\n * - `store()` — event persistence (default: InMemoryStore)\n * - `cache()` — state checkpoints (default: InMemoryCache)\n * - `dispose()` — register cleanup functions for graceful shutdown\n *\n * @module ports\n */\n\n// ---------------------------------------------------------------------------\n// Port factory\n// ---------------------------------------------------------------------------\n\n/**\n * Factory function that creates or returns the injected adapter.\n * @internal\n */\ntype Injector<Port extends Disposable> = (adapter?: Port) => Port;\n\n/** Singleton adapter registry, keyed by injector function name. */\nconst adapters = new Map<string, Disposable>();\n\n/**\n * Creates a singleton port with optional adapter injection.\n *\n * The first call initializes the adapter (using the provided adapter or the\n * injector's default). Subsequent calls return the cached singleton. Adapters\n * are disposed in reverse registration order during {@link disposeAndExit}.\n *\n * @param injector - Named function that creates the default adapter\n * @returns Port function: call with no args to get the singleton, or pass an\n * adapter on the first call to override the default\n *\n * @example\n * ```typescript\n * const store = port(function store(adapter?: Store) {\n * return adapter || new InMemoryStore();\n * });\n * const s = store(); // InMemoryStore\n * ```\n */\nexport function port<Port extends Disposable>(injector: Injector<Port>) {\n return (adapter?: Port): Port => {\n if (!adapters.has(injector.name)) {\n const injected = injector(adapter);\n adapters.set(injector.name, injected);\n // log() is now in adapters (or this IS the log port we just registered),\n // so the recursive call resolves immediately. Routing through the logger\n // means level gating (e.g. silenced in tests at fatal) takes effect.\n log().info(`[act] + ${injector.name}:${injected.constructor.name}`);\n }\n return adapters.get(injector.name) as Port;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Ports: log, store, cache\n// ---------------------------------------------------------------------------\n\n/**\n * Gets or injects the singleton logger.\n *\n * By default, Act uses a built-in {@link ConsoleLogger} that emits JSON lines\n * in production (compatible with GCP, AWS CloudWatch, Datadog) and colorized\n * output in development — zero external dependencies.\n *\n * For pino, inject a `PinoLogger` from `@rotorsoft/act-pino` before building\n * your application.\n *\n * @param adapter - Optional logger implementation to inject\n * @returns The singleton logger instance\n *\n * @example Default console logger\n * ```typescript\n * import { log } from \"@rotorsoft/act\";\n * const logger = log();\n * logger.info(\"Application started\");\n * ```\n *\n * @see {@link Logger} for the interface contract\n * @see {@link ConsoleLogger} for the default implementation\n */\nexport const log = port(function log(adapter?: Logger) {\n const cfg = config();\n return (\n adapter ||\n new ConsoleLogger({\n level: cfg.logLevel,\n pretty: cfg.env !== \"production\",\n })\n );\n});\n\n/**\n * Gets or injects the singleton event store.\n *\n * By default, Act uses an {@link InMemoryStore} suitable for development and\n * testing. For production, inject a persistent store like `PostgresStore` from\n * `@rotorsoft/act-pg` before building your application.\n *\n * **Important:** Store injection must happen before creating any Act instances.\n * Once set, the store cannot be changed without restarting the application.\n *\n * @param adapter - Optional store implementation to inject\n * @returns The singleton store instance\n *\n * @example Default in-memory store\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n * const s = store();\n * ```\n *\n * @see {@link Store} for the interface contract\n * @see {@link InMemoryStore} for the default implementation\n */\n// ALS check lives outside `port()` — its cache fires only once, so the\n// per-call branch on a scoped Act has to be in the public wrapper.\nconst _store = port(function store(adapter?: Store): Store {\n return adapter ?? new InMemoryStore();\n});\n\nexport const store = ((adapter?: Store): Store => {\n return current_ports()?.store ?? _store(adapter);\n}) as (adapter?: Store) => Store;\n\n/**\n * Gets or injects the singleton cache.\n *\n * By default, Act uses an {@link InMemoryCache} (LRU, maxSize 1000). For\n * distributed deployments, inject a Redis-backed cache before building your\n * application.\n *\n * @param adapter - Optional cache implementation to inject\n * @returns The singleton cache instance\n *\n * @see {@link Cache} for the interface contract\n * @see {@link InMemoryCache} for the default implementation\n */\nconst _cache = port(function cache(adapter?: Cache) {\n return adapter ?? new InMemoryCache();\n});\n\nexport const cache = ((adapter?: Cache): Cache => {\n return current_ports()?.cache ?? _cache(adapter);\n}) as (adapter?: Cache) => Cache;\n\n/**\n * The ports bag an Act without `ActOptions.scoped` runs in: the singleton\n * adapters, read through the same frame a scoped Act uses.\n *\n * Every Act entering a frame is what keeps its ports its own. Without one, a\n * shared Act called from inside a tenant's handler inherited that tenant's\n * frame and committed to the tenant's store.\n *\n * The properties are getters on purpose. The adapters are resolved lazily and\n * injected after `act().build()` in the normal case — `store(new PgStore())`\n * in application setup, or a test's `beforeEach` — so capturing them when the\n * bag is made would pin whatever existed at build time. They read the raw\n * resolvers rather than the public `store()`/`cache()`, which consult the\n * frame this bag *is* and would recurse.\n *\n * Published for adapter and decorator authors, not for apps.\n */\nexport const default_scope = (): Scoped => DEFAULT_SCOPE;\n\nconst DEFAULT_SCOPE: Scoped = {\n get store() {\n return _store();\n },\n get cache() {\n return _cache();\n },\n};\n\n// ---------------------------------------------------------------------------\n// Disposal\n// ---------------------------------------------------------------------------\n\n/**\n * Registered cleanup functions live in `disposers.ts`, which holds\n * lifetime-bound entries weakly so registering never pins its target for the\n * process lifetime. The public surface here is unchanged.\n */\n\n/**\n * Disposes all registered adapters and disposers, then exits the process.\n *\n * Execution order:\n * 1. Custom disposers (registered via {@link dispose}) — in reverse order\n * 2. Port adapters (log, store, cache) — in reverse registration order\n * 3. Adapter registry is cleared\n * 4. Process exits (skipped in test environment)\n *\n * In production, `\"ERROR\"` exits are silently ignored to avoid crashing on\n * transient failures (e.g. an uncaught promise in a non-critical path).\n *\n * @param code - Exit code: `\"EXIT\"` for clean shutdown (exit 0),\n * `\"ERROR\"` for abnormal termination (exit 1)\n */\nexport async function disposeAndExit(code: ExitCode = \"EXIT\"): Promise<void> {\n if (code === \"ERROR\" && config().env === \"production\") {\n // Surface the swallow so incident triage can see it. Without this\n // log the framework looks unresponsive after an uncaught exception\n // in prod — exactly when operators most need a breadcrumb.\n log().warn(\n \"disposeAndExit('ERROR') ignored in production — process kept alive\"\n );\n return;\n }\n\n // Run sequentially in reverse registration order so a disposer can rely on\n // later-registered disposers (and adapters on later-registered adapters)\n // having already finished — Promise.all would race them.\n await run_disposers();\n for (const adapter of [...adapters.values()].reverse()) {\n await adapter.dispose();\n log().info(`[act] - ${adapter.constructor.name}`);\n }\n adapters.clear();\n config().env !== \"test\" && process.exit(code === \"ERROR\" ? 1 : 0);\n}\n\n/**\n * Registers a cleanup function for graceful shutdown.\n *\n * Disposers are called automatically on SIGINT, SIGTERM, uncaught exceptions,\n * and unhandled rejections. They execute in reverse registration order before\n * port adapters are disposed.\n *\n * @param disposer - Async function to call during cleanup. Omit to get a\n * reference to {@link disposeAndExit} without registering.\n * @returns Function to manually trigger disposal and exit\n *\n * @example\n * ```typescript\n * import { dispose } from \"@rotorsoft/act\";\n *\n * const db = connectDatabase();\n * dispose(async () => await db.close());\n *\n * // In tests\n * afterAll(async () => await dispose()());\n * ```\n *\n * @see {@link disposeAndExit} for the full shutdown sequence\n */\nexport function dispose(\n disposer?: Disposer\n): (code?: ExitCode) => Promise<void> {\n disposer && register_disposer(disposer);\n return disposeAndExit;\n}\n"],"mappings":"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","names":["z","correlated_at","log","store","cache","z","pkg","resolveAutocloseConfig"]}