@rotorsoft/act 0.35.1 → 0.35.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/@types/act.d.ts +672 -0
  3. package/dist/@types/act.d.ts.map +1 -0
  4. package/dist/@types/adapters/console-logger.d.ts +41 -0
  5. package/dist/@types/adapters/console-logger.d.ts.map +1 -0
  6. package/dist/@types/adapters/in-memory-cache.d.ts +34 -0
  7. package/dist/@types/adapters/in-memory-cache.d.ts.map +1 -0
  8. package/dist/@types/adapters/in-memory-store.d.ts +202 -0
  9. package/dist/@types/adapters/in-memory-store.d.ts.map +1 -0
  10. package/dist/@types/adapters/index.d.ts +4 -0
  11. package/dist/@types/adapters/index.d.ts.map +1 -0
  12. package/dist/@types/builders/act-builder.d.ts +160 -0
  13. package/dist/@types/builders/act-builder.d.ts.map +1 -0
  14. package/dist/@types/builders/index.d.ts +13 -0
  15. package/dist/@types/builders/index.d.ts.map +1 -0
  16. package/dist/@types/builders/projection-builder.d.ts +101 -0
  17. package/dist/@types/builders/projection-builder.d.ts.map +1 -0
  18. package/dist/@types/builders/slice-builder.d.ts +109 -0
  19. package/dist/@types/builders/slice-builder.d.ts.map +1 -0
  20. package/dist/@types/builders/state-builder.d.ts +424 -0
  21. package/dist/@types/builders/state-builder.d.ts.map +1 -0
  22. package/dist/@types/config.d.ts +119 -0
  23. package/dist/@types/config.d.ts.map +1 -0
  24. package/dist/@types/index.d.ts +14 -0
  25. package/dist/@types/index.d.ts.map +1 -0
  26. package/dist/@types/internal/build-classify.d.ts +44 -0
  27. package/dist/@types/internal/build-classify.d.ts.map +1 -0
  28. package/dist/@types/internal/close-cycle.d.ts +38 -0
  29. package/dist/@types/internal/close-cycle.d.ts.map +1 -0
  30. package/dist/@types/internal/correlate-cycle.d.ts +78 -0
  31. package/dist/@types/internal/correlate-cycle.d.ts.map +1 -0
  32. package/dist/@types/internal/drain-cycle.d.ts +113 -0
  33. package/dist/@types/internal/drain-cycle.d.ts.map +1 -0
  34. package/dist/@types/internal/drain-ratio.d.ts +26 -0
  35. package/dist/@types/internal/drain-ratio.d.ts.map +1 -0
  36. package/dist/@types/internal/drain.d.ts +41 -0
  37. package/dist/@types/internal/drain.d.ts.map +1 -0
  38. package/dist/@types/internal/event-sourcing.d.ts +96 -0
  39. package/dist/@types/internal/event-sourcing.d.ts.map +1 -0
  40. package/dist/@types/internal/index.d.ts +29 -0
  41. package/dist/@types/internal/index.d.ts.map +1 -0
  42. package/dist/@types/internal/merge.d.ts +31 -0
  43. package/dist/@types/internal/merge.d.ts.map +1 -0
  44. package/dist/@types/internal/reactions.d.ts +54 -0
  45. package/dist/@types/internal/reactions.d.ts.map +1 -0
  46. package/dist/@types/internal/settle.d.ts +60 -0
  47. package/dist/@types/internal/settle.d.ts.map +1 -0
  48. package/dist/@types/internal/tracing.d.ts +45 -0
  49. package/dist/@types/internal/tracing.d.ts.map +1 -0
  50. package/dist/@types/lru-map.d.ts +50 -0
  51. package/dist/@types/lru-map.d.ts.map +1 -0
  52. package/dist/@types/ports.d.ts +196 -0
  53. package/dist/@types/ports.d.ts.map +1 -0
  54. package/dist/@types/signals.d.ts +2 -0
  55. package/dist/@types/signals.d.ts.map +1 -0
  56. package/dist/@types/types/action.d.ts +444 -0
  57. package/dist/@types/types/action.d.ts.map +1 -0
  58. package/dist/@types/types/errors.d.ts +284 -0
  59. package/dist/@types/types/errors.d.ts.map +1 -0
  60. package/dist/@types/types/index.d.ts +39 -0
  61. package/dist/@types/types/index.d.ts.map +1 -0
  62. package/dist/@types/types/ports.d.ts +617 -0
  63. package/dist/@types/types/ports.d.ts.map +1 -0
  64. package/dist/@types/types/reaction.d.ts +314 -0
  65. package/dist/@types/types/reaction.d.ts.map +1 -0
  66. package/dist/@types/types/registry.d.ts +74 -0
  67. package/dist/@types/types/registry.d.ts.map +1 -0
  68. package/dist/@types/types/schemas.d.ts +117 -0
  69. package/dist/@types/types/schemas.d.ts.map +1 -0
  70. package/dist/@types/utils.d.ts +54 -0
  71. package/dist/@types/utils.d.ts.map +1 -0
  72. package/dist/chunk-AGWZY6YT.js +127 -0
  73. package/dist/chunk-AGWZY6YT.js.map +1 -0
  74. package/dist/index.cjs +3144 -0
  75. package/dist/index.cjs.map +1 -0
  76. package/dist/index.js +2975 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/types/index.cjs +166 -0
  79. package/dist/types/index.cjs.map +1 -0
  80. package/dist/types/index.js +33 -0
  81. package/dist/types/index.js.map +1 -0
  82. package/package.json +6 -2
@@ -0,0 +1,617 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * @module act/types
4
+ * @category Types
5
+ * Types and interfaces for event store ports and disposables in the Act Framework.
6
+ */
7
+ import type { Committed, EventMeta, Message, Query, Schema, Schemas } from "./action.js";
8
+ import type { BlockedLease, Lease } from "./reaction.js";
9
+ /**
10
+ * A function that disposes of a resource asynchronously.
11
+ * @returns Promise that resolves when disposal is complete.
12
+ */
13
+ export type Disposer = () => Promise<void>;
14
+ /**
15
+ * An object that can be disposed of asynchronously.
16
+ */
17
+ export type Disposable = {
18
+ dispose: Disposer;
19
+ };
20
+ /**
21
+ * Minimal logger port compatible with pino, winston, bunyan, and console.
22
+ *
23
+ * Each log method accepts either:
24
+ * - `(msg: string)` — plain message
25
+ * - `(obj: unknown, msg?: string)` — structured data with optional message
26
+ *
27
+ * Implementations should respect `level` to gate output.
28
+ *
29
+ * @see {@link ConsoleLogger} for the default implementation
30
+ * @see {@link https://www.npmjs.com/package/@rotorsoft/act-pino | @rotorsoft/act-pino} for the Pino adapter
31
+ */
32
+ export interface Logger extends Disposable {
33
+ level: string;
34
+ fatal(obj: unknown, msg?: string): void;
35
+ fatal(msg: string): void;
36
+ error(obj: unknown, msg?: string): void;
37
+ error(msg: string): void;
38
+ warn(obj: unknown, msg?: string): void;
39
+ warn(msg: string): void;
40
+ info(obj: unknown, msg?: string): void;
41
+ info(msg: string): void;
42
+ debug(obj: unknown, msg?: string): void;
43
+ debug(msg: string): void;
44
+ trace(obj: unknown, msg?: string): void;
45
+ trace(msg: string): void;
46
+ child(bindings: Record<string, unknown>): Logger;
47
+ }
48
+ /**
49
+ * Result of a {@link Store.truncate} operation, keyed by stream name.
50
+ * Each entry contains the number of deleted events and the committed
51
+ * seed event (snapshot or tombstone).
52
+ */
53
+ export type TruncateResult = Map<string, {
54
+ deleted: number;
55
+ committed: Committed<Schemas, keyof Schemas>;
56
+ }>;
57
+ /**
58
+ * Payload delivered by {@link Store.notify} when a **different process**
59
+ * commits one or more events to the same backing store.
60
+ *
61
+ * Notifications are emitted **per commit transaction**, not per event —
62
+ * a single commit of N events produces one notification carrying all N
63
+ * `events`. This matches transactional semantics, minimizes wire wakeups,
64
+ * and lets handlers reason about atomic batches.
65
+ *
66
+ * Stores that implement `notify` self-filter their own commits — handlers
67
+ * receive notifications only for cross-process activity. This is the signal
68
+ * that lets a horizontally-scaled Act deployment wake `settle()` immediately
69
+ * on remote commits, instead of waiting for the next poll/debounce cycle.
70
+ *
71
+ * @property stream - Stream that was committed to
72
+ * @property events - Events in this commit (id + name), in commit order
73
+ */
74
+ export type StoreNotification = {
75
+ readonly stream: string;
76
+ readonly events: ReadonlyArray<{
77
+ readonly id: number;
78
+ readonly name: string;
79
+ }>;
80
+ };
81
+ /**
82
+ * Disposer returned by {@link Store.notify} subscriptions. Releases the
83
+ * underlying listener (e.g., the dedicated PG `LISTEN` client). May be
84
+ * synchronous or asynchronous — callers should `await` either way.
85
+ */
86
+ export type NotifyDisposer = () => void | Promise<void>;
87
+ /**
88
+ * Subscription position for a registered stream.
89
+ *
90
+ * Streamed by {@link Store.query_streams} to power operational dashboards
91
+ * (projection lag, blocked subscriptions, in-flight leases). The shape
92
+ * mirrors what every adapter already tracks on its `streams` table.
93
+ *
94
+ * @property stream - The subscription target (projection or reaction stream)
95
+ * @property source - Optional source stream filter (for reactions)
96
+ * @property at - Last processed event id watermark (-1 for fresh streams)
97
+ * @property retry - Current retry counter
98
+ * @property blocked - True when the stream is blocked by a poison message
99
+ * @property error - Last error message (empty string when none)
100
+ * @property leased_by - Current lease holder UUID (when leased)
101
+ * @property leased_until - Lease expiration timestamp (when leased)
102
+ * @property priority - Scheduling priority (default 0). Biases the
103
+ * lagging-frontier `claim()` ordering — see {@link Store.prioritize}.
104
+ */
105
+ export type StreamPosition = {
106
+ readonly stream: string;
107
+ readonly source?: string;
108
+ readonly at: number;
109
+ readonly retry: number;
110
+ readonly blocked: boolean;
111
+ readonly error: string;
112
+ readonly priority: number;
113
+ readonly leased_by?: string;
114
+ readonly leased_until?: Date;
115
+ };
116
+ /**
117
+ * Filter options for {@link Store.query_streams}.
118
+ *
119
+ * Mirrors the {@link Query} pattern used by {@link Store.query} — pass
120
+ * filters server-side to keep the cost low on large tables (e.g., dynamic
121
+ * reactions producing one subscription per aggregate).
122
+ *
123
+ * **What the store can filter:** the columns it actually persists —
124
+ * `stream`, `source`, `blocked`. Higher-level classification ("is this a
125
+ * projection vs a reaction?", "is this a static or dynamic resolver?")
126
+ * is an orchestrator concern; the streams table doesn't store kinds.
127
+ * Layer that on top by joining results with `Act`'s built-in registry.
128
+ *
129
+ * @property stream - Stream-name filter. By default treated as a regex
130
+ * (PG `~`, SQLite/InMemory `LIKE`-translated). Pass `stream_exact: true`
131
+ * for exact string equality.
132
+ * @property stream_exact - Use exact match instead of pattern match for
133
+ * `stream`.
134
+ * @property source - Source-stream filter (regex by default). Useful to
135
+ * isolate dynamic-reaction subscriptions tied to a particular aggregate
136
+ * stream. Pass `source_exact: true` for exact equality.
137
+ * @property source_exact - Use exact match instead of pattern match for
138
+ * `source`.
139
+ * @property blocked - Restrict to blocked (`true`) or unblocked (`false`)
140
+ * streams. Omit for all.
141
+ * @property after - Keyset pagination cursor: returns only streams with
142
+ * `stream > after` (lexicographic). Pass the last seen `stream` to fetch
143
+ * the next page.
144
+ * @property limit - Max rows to return (default: 100).
145
+ */
146
+ export type QueryStreams = {
147
+ readonly stream?: string;
148
+ readonly stream_exact?: boolean;
149
+ readonly source?: string;
150
+ readonly source_exact?: boolean;
151
+ readonly blocked?: boolean;
152
+ readonly after?: string;
153
+ readonly limit?: number;
154
+ };
155
+ /**
156
+ * Result of a {@link Store.query_streams} call.
157
+ *
158
+ * @property maxEventId - Highest event id in the store (-1 when empty).
159
+ * UI uses this to compute lag as `maxEventId - position.at`.
160
+ * @property count - Number of stream positions delivered to the callback.
161
+ */
162
+ export type QueryStreamsResult = {
163
+ readonly maxEventId: number;
164
+ readonly count: number;
165
+ };
166
+ /**
167
+ * Filter for {@link Store.prioritize} bulk priority updates.
168
+ *
169
+ * Same shape as {@link QueryStreams} but without pagination — bulk
170
+ * UPDATEs don't paginate. Empty filter (`{}`) updates **every**
171
+ * registered stream.
172
+ *
173
+ * @property stream - Stream-name filter (regex by default; `stream_exact`
174
+ * for equality).
175
+ * @property stream_exact - Exact-match instead of regex.
176
+ * @property source - Source-stream filter (regex by default;
177
+ * `source_exact` for equality).
178
+ * @property source_exact - Exact-match instead of regex.
179
+ * @property blocked - Restrict to blocked / unblocked streams. Omit
180
+ * for both.
181
+ */
182
+ export type PrioritizeFilter = Pick<QueryStreams, "stream" | "stream_exact" | "source" | "source_exact" | "blocked">;
183
+ /**
184
+ * Interface for event store implementations.
185
+ *
186
+ * The Store interface defines the contract for persistence adapters in Act.
187
+ * Implementations must provide event storage, querying, and distributed processing
188
+ * capabilities through leasing and watermark tracking.
189
+ *
190
+ * Act includes two built-in implementations:
191
+ * - **InMemoryStore**: For development and testing
192
+ * - **PostgresStore**: For production use with PostgreSQL
193
+ *
194
+ * Custom stores can be implemented for other databases or event log systems.
195
+ *
196
+ * @example Using a custom store
197
+ * ```typescript
198
+ * import { store } from "@rotorsoft/act";
199
+ * import { PostgresStore } from "@rotorsoft/act-pg";
200
+ *
201
+ * // Replace the default in-memory store
202
+ * store(new PostgresStore({
203
+ * host: "localhost",
204
+ * port: 5432,
205
+ * database: "myapp",
206
+ * user: "postgres",
207
+ * password: "secret"
208
+ * }));
209
+ *
210
+ * const app = act()
211
+ * .withState(Counter)
212
+ * .build();
213
+ * ```
214
+ *
215
+ * @see {@link InMemoryStore} for the default implementation
216
+ * @see {@link PostgresStore} for the PostgreSQL implementation
217
+ */
218
+ export interface Store extends Disposable {
219
+ /**
220
+ * Initializes or resets the store.
221
+ *
222
+ * Used primarily for testing to ensure a clean state between tests.
223
+ * For production stores, this might create necessary tables or indexes.
224
+ *
225
+ * @example
226
+ * ```typescript
227
+ * // Reset store between tests
228
+ * beforeEach(async () => {
229
+ * await store().seed();
230
+ * });
231
+ * ```
232
+ */
233
+ seed: () => Promise<void>;
234
+ /**
235
+ * Drops all data from the store.
236
+ *
237
+ * Dangerous operation that deletes all events and state. Use with extreme caution,
238
+ * primarily for testing or development environments.
239
+ *
240
+ * @example
241
+ * ```typescript
242
+ * // Clean up after tests
243
+ * afterAll(async () => {
244
+ * await store().drop();
245
+ * });
246
+ * ```
247
+ */
248
+ drop: () => Promise<void>;
249
+ /**
250
+ * Commits one or more events to a stream atomically.
251
+ *
252
+ * This is the core method for persisting events. It must:
253
+ * - Assign global sequence IDs to events
254
+ * - Increment the stream version
255
+ * - Check optimistic concurrency if expectedVersion is provided
256
+ * - Store events atomically (all or nothing)
257
+ * - Attach metadata (id, stream, version, created timestamp)
258
+ *
259
+ * @template E - Event schemas
260
+ * @param stream - The stream ID to commit to
261
+ * @param msgs - Array of messages (events) to commit
262
+ * @param meta - Event metadata (correlation, causation)
263
+ * @param expectedVersion - Expected current version for optimistic concurrency
264
+ * @returns Array of committed events with full metadata
265
+ *
266
+ * @throws {ConcurrencyError} If expectedVersion doesn't match current version
267
+ *
268
+ * @example
269
+ * ```typescript
270
+ * const events = await store().commit(
271
+ * "user-123",
272
+ * [{ name: "UserCreated", data: { email: "user@example.com" } }],
273
+ * { correlation: "req-456", causation: { action: {...} } },
274
+ * 0 // Expect version 0 (new stream)
275
+ * );
276
+ * ```
277
+ */
278
+ commit: <E extends Schemas>(stream: string, msgs: Message<E, keyof E>[], meta: EventMeta, expectedVersion?: number) => Promise<Committed<E, keyof E>[]>;
279
+ /**
280
+ * Queries events from the store with optional filtering.
281
+ *
282
+ * Calls the callback for each matching event. The callback approach allows
283
+ * processing large result sets without loading everything into memory.
284
+ *
285
+ * @template E - Event schemas
286
+ * @param callback - Function invoked for each matching event
287
+ * @param query - Optional filter criteria — see {@link Query} for fields
288
+ * (`stream`, `name`, `after`, `before`, `created_after`, `created_before`,
289
+ * `limit`, `with_snaps`, `stream_exact`).
290
+ * @returns Total number of events processed
291
+ *
292
+ * @example Query all events for a stream
293
+ * ```typescript
294
+ * let count = 0;
295
+ * await store().query(
296
+ * (event) => {
297
+ * console.log(event.name, event.data);
298
+ * count++;
299
+ * },
300
+ * { stream: "user-123" }
301
+ * );
302
+ * console.log(`Found ${count} events`);
303
+ * ```
304
+ */
305
+ query: <E extends Schemas>(callback: (event: Committed<E, keyof E>) => void, query?: Query) => Promise<number>;
306
+ /**
307
+ * Atomically discovers and leases streams for reaction processing.
308
+ *
309
+ * Atomically discovers a stream and acquires a lease in one round-trip,
310
+ * eliminating the race that exists when discovery and locking are separate
311
+ * calls (a competing worker can grab the stream between the two).
312
+ *
313
+ * PostgresStore uses `FOR UPDATE SKIP LOCKED` for zero-contention competing
314
+ * consumer semantics — workers never block each other, each grabbing different
315
+ * streams atomically. InMemoryStore fuses its poll+lease logic equivalently.
316
+ *
317
+ * Used by `Act.drain()` as the primary stream acquisition method.
318
+ *
319
+ * @param lagging - Max streams from the lagging frontier (ascending watermark)
320
+ * @param leading - Max streams from the leading frontier (descending watermark)
321
+ * @param by - Unique lease holder identifier (UUID)
322
+ * @param millis - Lease duration in milliseconds
323
+ * @returns Array of successfully leased streams with metadata
324
+ *
325
+ * @example
326
+ * ```typescript
327
+ * const leased = await store().claim(5, 5, randomUUID(), 10000);
328
+ * leased.forEach(({ stream, at, lagging }) => {
329
+ * console.log(`Leased ${stream} at ${at} (lagging: ${lagging})`);
330
+ * });
331
+ * ```
332
+ *
333
+ * @see {@link subscribe} for registering new streams (used by correlate)
334
+ * @see {@link ack} for acknowledging completion
335
+ * @see {@link block} for blocking failed streams
336
+ */
337
+ claim: (lagging: number, leading: number, by: string, millis: number) => Promise<Lease[]>;
338
+ /**
339
+ * Registers streams for event processing.
340
+ *
341
+ * Upserts stream entries so they become visible to {@link claim}. Used by
342
+ * `correlate()` to register dynamically discovered reaction target streams.
343
+ *
344
+ * Also returns the current maximum watermark across all subscribed streams,
345
+ * used internally for correlation checkpoint initialization on cold start.
346
+ *
347
+ * @param streams - Streams to register with optional source hint
348
+ * @returns `subscribed` count of newly registered streams, `watermark` max `at` across all streams
349
+ *
350
+ * @example
351
+ * ```typescript
352
+ * const { subscribed, watermark } = await store().subscribe([
353
+ * { stream: "stats-user-1", source: "user-1" },
354
+ * { stream: "stats-user-2", source: "user-2", priority: 10 },
355
+ * ]);
356
+ * ```
357
+ *
358
+ * @see {@link claim} for discovering and leasing registered streams
359
+ * @see {@link prioritize} for changing priority after subscription
360
+ */
361
+ subscribe: (streams: Array<{
362
+ stream: string;
363
+ source?: string;
364
+ /**
365
+ * Optional scheduling priority for the lagging-frontier
366
+ * `claim()` ordering. Default `0`. When the same stream is
367
+ * subscribed by multiple reactions with different priorities,
368
+ * implementations must keep the **maximum** so the highest-
369
+ * priority reaction wins. Use {@link prioritize} for runtime
370
+ * overrides that ignore this max — operator-driven changes.
371
+ */
372
+ priority?: number;
373
+ }>) => Promise<{
374
+ subscribed: number;
375
+ watermark: number;
376
+ }>;
377
+ /**
378
+ * Acknowledges successful processing of leased streams.
379
+ *
380
+ * Updates the watermark to indicate events have been processed successfully.
381
+ * Releases the lease so other workers can process subsequent events.
382
+ *
383
+ * @param leases - Leases to acknowledge with updated watermarks
384
+ * @returns Acknowledged leases
385
+ *
386
+ * @example
387
+ * ```typescript
388
+ * const leased = await store().claim(5, 5, randomUUID(), 10000);
389
+ * // Process events up to ID 150
390
+ * await store().ack(leased.map(l => ({ ...l, at: 150 })));
391
+ * ```
392
+ *
393
+ * @see {@link claim} for acquiring leases
394
+ */
395
+ ack: (leases: Lease[]) => Promise<Lease[]>;
396
+ /**
397
+ * Blocks streams after persistent processing failures.
398
+ *
399
+ * Blocked streams won't be returned by {@link claim} until manually unblocked.
400
+ * This prevents poison messages from repeatedly failing and consuming resources.
401
+ *
402
+ * Streams are typically blocked when:
403
+ * - Max retries reached
404
+ * - `blockOnError` option is true
405
+ * - Handler throws an error
406
+ *
407
+ * @param leases - Leases to block with error messages
408
+ * @returns Blocked leases
409
+ *
410
+ * @example
411
+ * ```typescript
412
+ * try {
413
+ * await processEvents(lease);
414
+ * await store().ack([lease]);
415
+ * } catch (error) {
416
+ * if (lease.retry >= 3) {
417
+ * await store().block([{
418
+ * ...lease,
419
+ * error: error.message
420
+ * }]);
421
+ * }
422
+ * }
423
+ * ```
424
+ *
425
+ * @see {@link claim} for lease management
426
+ */
427
+ block: (leases: BlockedLease[]) => Promise<BlockedLease[]>;
428
+ /**
429
+ * Resets watermarks for the given streams to -1, making them eligible
430
+ * for replay from the beginning. Also clears retry, blocked, error,
431
+ * and lease state so the streams can be claimed immediately.
432
+ *
433
+ * **Prefer `Act.reset()` over calling this directly.** This primitive
434
+ * only resets the store; it does not raise the orchestrator's internal
435
+ * "needs drain" flag, so a settled `Act` instance will short-circuit and
436
+ * skip the replay. `Act.reset()` wraps this and arms the flag.
437
+ *
438
+ * @param streams - Stream names to reset
439
+ * @returns Count of streams that were actually reset
440
+ *
441
+ * @example
442
+ * ```typescript
443
+ * // Recommended
444
+ * await app.reset(["my-projection"]);
445
+ *
446
+ * // Low-level (does NOT trigger replay on settled apps)
447
+ * await store().reset(["my-projection"]);
448
+ * ```
449
+ *
450
+ * @see {@link Act.reset} for the high-level rebuild API that wraps
451
+ * this primitive and arms the orchestrator's drain flag
452
+ */
453
+ reset: (streams: string[]) => Promise<number>;
454
+ /**
455
+ * Bulk-update the scheduling priority of streams matching a filter.
456
+ *
457
+ * Used by {@link Act.prioritize} for operator runtime control over
458
+ * lagging-frontier `claim()` ordering. Unlike {@link subscribe},
459
+ * which keeps the per-stream priority at the `max()` of all
460
+ * registered reactions targeting that stream, `prioritize` sets the
461
+ * priority **directly** to `priority` for matching rows — letting
462
+ * operators override the build-time scheduling policy.
463
+ *
464
+ * Filter semantics mirror {@link query_streams}: `stream`/`source`
465
+ * are regex by default, exact with the `*_exact` flags. `blocked`
466
+ * restricts to blocked or unblocked rows. Omitted fields don't
467
+ * filter. An **empty filter** (`{}`) updates every registered
468
+ * stream — useful for "reset all priorities to N" but a footgun
469
+ * otherwise.
470
+ *
471
+ * @param filter - {@link PrioritizeFilter} selecting which streams
472
+ * to update. Required (use `{}` to target all).
473
+ * @param priority - New priority value. Set as-is — no `max()`,
474
+ * no clamp.
475
+ * @returns Count of streams whose priority was changed.
476
+ *
477
+ * @example Boost a specific replay
478
+ * ```typescript
479
+ * await store().prioritize(
480
+ * { stream: "^projection-orders$", stream_exact: false },
481
+ * 10
482
+ * );
483
+ * ```
484
+ *
485
+ * @example De-prioritize all background projections
486
+ * ```typescript
487
+ * await store().prioritize({ source: "^audit-" }, -5);
488
+ * ```
489
+ *
490
+ * @see {@link Act.prioritize} for the orchestrator-level wrapper
491
+ * @see {@link claim} for how priority biases stream scheduling
492
+ */
493
+ prioritize: (filter: PrioritizeFilter, priority: number) => Promise<number>;
494
+ /**
495
+ * Atomically truncates streams and seeds each with a final event.
496
+ *
497
+ * For each target, in a single transaction:
498
+ * 1. Deletes all events for the stream
499
+ * 2. Removes the stream's entry from the streams table
500
+ * 3. Inserts a `__snapshot__` (when `snapshot` is provided) or
501
+ * `__tombstone__` event as the sole event on the stream
502
+ *
503
+ * @param targets - Streams to truncate with optional snapshot state and meta
504
+ * @returns Map keyed by stream name, each entry with `deleted` count and `committed` event
505
+ *
506
+ * @see {@link Act.close} for the high-level close-the-books API that
507
+ * orchestrates safety checks, archive callbacks, and atomic
508
+ * truncate+seed
509
+ */
510
+ truncate: (targets: Array<{
511
+ stream: string;
512
+ snapshot?: Schema;
513
+ meta?: EventMeta;
514
+ }>) => Promise<TruncateResult>;
515
+ /**
516
+ * Streams registered subscription positions to a callback, plus the
517
+ * highest event id in the store.
518
+ *
519
+ * Read-only introspection for operational dashboards (Store /
520
+ * Subscriptions tab, projection lag, blocked subscriptions). Avoids
521
+ * forcing apps to open a second connection and run raw SQL against
522
+ * adapter-specific schemas.
523
+ *
524
+ * Mirrors the {@link Store.query} callback pattern: the callback is
525
+ * invoked once per matching position, allowing large result sets to be
526
+ * processed without buffering. Results are ordered by `stream` name; use
527
+ * `query.after` (last seen stream name) for keyset pagination on big
528
+ * tables (dynamic reactions can produce one subscription per aggregate).
529
+ *
530
+ * @param callback - Invoked once per matching {@link StreamPosition}.
531
+ * @param query - Optional {@link QueryStreams} filter (default `limit: 100`).
532
+ * @returns `maxEventId` and the `count` of positions emitted.
533
+ *
534
+ * @example List blocked streams with their lag
535
+ * ```typescript
536
+ * const { maxEventId } = await store().query_streams(
537
+ * (s) => console.log(`${s.stream}: lag=${maxEventId - s.at} ${s.error}`),
538
+ * { blocked: true, limit: 50 }
539
+ * );
540
+ * ```
541
+ *
542
+ * @example Page through all positions
543
+ * ```typescript
544
+ * let after: string | undefined;
545
+ * for (;;) {
546
+ * const page: StreamPosition[] = [];
547
+ * const { count } = await store().query_streams(
548
+ * (s) => page.push(s),
549
+ * { after, limit: 100 }
550
+ * );
551
+ * if (!count) break;
552
+ * // ... use page ...
553
+ * after = page.at(-1)?.stream;
554
+ * }
555
+ * ```
556
+ */
557
+ query_streams: (callback: (position: StreamPosition) => void, query?: QueryStreams) => Promise<QueryStreamsResult>;
558
+ /**
559
+ * Optional cross-process commit notifications.
560
+ *
561
+ * When implemented, the {@link Act} orchestrator subscribes once at build
562
+ * time and routes notifications to wake `settle()` automatically — so a
563
+ * remote worker's commit triggers reactions on this process without
564
+ * waiting for the debounce/poll cycle. Subscribers also receive each
565
+ * notification on the `"notified"` lifecycle event for fan-out
566
+ * (SSE pushes, audit logs, dashboards).
567
+ *
568
+ * **Self-filtering contract:** implementations must skip their own
569
+ * commits. The handler fires only for commits originating from a
570
+ * **different process** writing to the same backing store. This keeps
571
+ * the local fast path (`do()` already arms drain) free of duplicate
572
+ * wake-ups and gives `"notified"` a clean cross-process semantic.
573
+ *
574
+ * **Hint, not a contract:** the orchestrator never depends on `notify`
575
+ * for correctness. If absent, dropped, or the store omits it, the
576
+ * existing debounce/poll path still drains correctly — `notify` only
577
+ * lowers cross-process p99 reaction latency.
578
+ *
579
+ * Adapter status (Act 0.x):
580
+ * - {@link PostgresStore}: implemented via `LISTEN`/`NOTIFY` on the
581
+ * `act_commit` channel
582
+ * - {@link InMemoryStore}: not implemented (single-process — no remote
583
+ * writers exist)
584
+ * - `SqliteStore`: not implemented (single-node by design)
585
+ *
586
+ * @param handler Callback invoked once per remote commit
587
+ * @returns Disposer releasing the underlying listener
588
+ */
589
+ notify?: (handler: (notification: StoreNotification) => void) => NotifyDisposer | Promise<NotifyDisposer>;
590
+ }
591
+ /**
592
+ * A cached snapshot entry for a stream.
593
+ *
594
+ * @template TState - The state schema type
595
+ */
596
+ export interface CacheEntry<TState extends Schema> {
597
+ readonly state: TState;
598
+ readonly version: number;
599
+ readonly event_id: number;
600
+ readonly patches: number;
601
+ readonly snaps: number;
602
+ }
603
+ /**
604
+ * Cache port for storing stream snapshots in-process.
605
+ *
606
+ * Implementations should provide fast key-value access with bounded memory.
607
+ * The async interface is forward-compatible with external caches (e.g., Redis).
608
+ *
609
+ * @template TState - The state schema type
610
+ */
611
+ export interface Cache extends Disposable {
612
+ get<TState extends Schema>(stream: string): Promise<CacheEntry<TState> | undefined>;
613
+ set<TState extends Schema>(stream: string, entry: CacheEntry<TState>): Promise<void>;
614
+ invalidate(stream: string): Promise<void>;
615
+ clear(): Promise<void>;
616
+ }
617
+ //# sourceMappingURL=ports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/types/ports.ts"],"names":[],"mappings":"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"}