@rotorsoft/act 0.45.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/act.d.ts +51 -1
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/internal/audit.d.ts +95 -0
- package/dist/@types/internal/audit.d.ts.map +1 -0
- package/dist/@types/internal/index.d.ts +1 -0
- package/dist/@types/internal/index.d.ts.map +1 -1
- package/dist/@types/types/audit.d.ts +126 -0
- package/dist/@types/types/audit.d.ts.map +1 -0
- package/dist/@types/types/index.d.ts +1 -0
- package/dist/@types/types/index.d.ts.map +1 -1
- package/dist/{chunk-VMX7RPTC.js → chunk-TZWDSNSN.js} +1 -1
- package/dist/{chunk-VMX7RPTC.js.map → chunk-TZWDSNSN.js.map} +1 -1
- package/dist/{chunk-PGTC7VOC.js → chunk-VC6MSVC3.js} +2 -2
- package/dist/index.cjs +480 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +482 -39
- package/dist/index.js.map +1 -1
- package/dist/test/index.cjs +9 -9
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.js +11 -11
- package/dist/test/index.js.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.js +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-PGTC7VOC.js.map → chunk-VC6MSVC3.js.map} +0 -0
package/dist/@types/act.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Scoped } from "./ports.js";
|
|
2
|
-
import type { Actor, AsOf, BatchHandler, BlockedLease, CloseResult, CloseTarget, Committed, Correlator, Drain, DrainOptions, IAct, LaneConfig, Lease, Query, Registry, Schema, SchemaRegister, Schemas, SettleOptions, Snapshot, State, StoreNotification, StreamFilter, StreamPosition, Target } from "./types/index.js";
|
|
2
|
+
import type { Actor, AsOf, AuditCategory, AuditFinding, AuditOptions, BatchHandler, BlockedLease, CloseResult, CloseTarget, Committed, Correlator, Drain, DrainOptions, IAct, LaneConfig, Lease, Query, Registry, Schema, SchemaRegister, Schemas, SettleOptions, Snapshot, State, StoreNotification, StreamFilter, StreamPosition, Target } from "./types/index.js";
|
|
3
3
|
/**
|
|
4
4
|
* @category Orchestrator
|
|
5
5
|
* @see Store
|
|
@@ -161,6 +161,14 @@ export declare class Act<TSchemaReg extends SchemaRegister<TActions>, TEvents ex
|
|
|
161
161
|
* reactions target.
|
|
162
162
|
*/
|
|
163
163
|
private readonly _event_to_lanes;
|
|
164
|
+
/**
|
|
165
|
+
* Audit dependency bag (#723). Built once at construction; held as
|
|
166
|
+
* an immutable snapshot of the registry state the audit module
|
|
167
|
+
* needs. Lives in `internal/audit.ts` — this orchestrator never
|
|
168
|
+
* carries audit logic, only the deps + a one-liner that hands them
|
|
169
|
+
* over.
|
|
170
|
+
*/
|
|
171
|
+
private readonly _audit_deps;
|
|
164
172
|
/** Logger resolved at construction time (after user port configuration) */
|
|
165
173
|
private readonly _logger;
|
|
166
174
|
/** Wraps a public-method body so internal `store()`/`cache()` resolve to the
|
|
@@ -701,6 +709,48 @@ export declare class Act<TSchemaReg extends SchemaRegister<TActions>, TEvents ex
|
|
|
701
709
|
after?: string;
|
|
702
710
|
limit?: number;
|
|
703
711
|
}): Promise<StreamPosition[]>;
|
|
712
|
+
/**
|
|
713
|
+
* Operator-driven store audit (#723).
|
|
714
|
+
*
|
|
715
|
+
* Walks the connected store and yields per-category findings —
|
|
716
|
+
* each tagged with the remediation it suggests. Same operator-
|
|
717
|
+
* driven category as `app.close()` / `app.reset()` /
|
|
718
|
+
* `app.unblock()` / `app.blocked_streams()`: never auto-invoked by
|
|
719
|
+
* the framework; the operator decides when to run it (CI gate,
|
|
720
|
+
* scheduled job, ad-hoc forensics) and what to do with the
|
|
721
|
+
* findings.
|
|
722
|
+
*
|
|
723
|
+
* Categories are independent — pass a subset to scope the work,
|
|
724
|
+
* or omit to run everything:
|
|
725
|
+
*
|
|
726
|
+
* ```typescript
|
|
727
|
+
* // Targeted: schema drift + deprecated-event load only
|
|
728
|
+
* for await (const f of app.audit(["schema", "deprecated-load"], {
|
|
729
|
+
* query: { created_after: lastScan },
|
|
730
|
+
* thresholds: { deprecatedLoadShareMin: 0.10 },
|
|
731
|
+
* })) {
|
|
732
|
+
* await escalate(f);
|
|
733
|
+
* }
|
|
734
|
+
*
|
|
735
|
+
* // Full audit, default thresholds
|
|
736
|
+
* for await (const f of app.audit()) console.log(f);
|
|
737
|
+
* ```
|
|
738
|
+
*
|
|
739
|
+
* Returns an `AsyncIterable` so callers can `break` early — the
|
|
740
|
+
* underlying store paginations respect the iterator protocol and
|
|
741
|
+
* stop cleanly. Each finding is emitted independently, so
|
|
742
|
+
* pipelining into Slack / persistence / further analysis works
|
|
743
|
+
* without buffering the full report in memory.
|
|
744
|
+
*
|
|
745
|
+
* Findings shape — see {@link AuditFinding}. The discriminated
|
|
746
|
+
* union carries enough context for the operator to act on each
|
|
747
|
+
* finding directly: stream id, event id, recommendation hints.
|
|
748
|
+
*
|
|
749
|
+
* @param categories - Subset of categories to run (default: all).
|
|
750
|
+
* @param options - Query window + per-category thresholds.
|
|
751
|
+
* @returns Async iterable of {@link AuditFinding}.
|
|
752
|
+
*/
|
|
753
|
+
audit(categories?: AuditCategory[], options?: AuditOptions): AsyncIterable<AuditFinding>;
|
|
704
754
|
/**
|
|
705
755
|
* Bulk-update scheduling priority for streams matching `filter`.
|
|
706
756
|
*
|
package/dist/@types/act.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/act.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/act.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAgB,KAAK,MAAM,EAAiB,MAAM,YAAY,CAAC;AACtE,OAAO,KAAK,EACV,KAAK,EACL,IAAI,EACJ,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,SAAS,EACT,UAAU,EACV,KAAK,EACL,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,KAAK,EAEL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,cAAc,EACd,OAAO,EACP,aAAa,EACb,QAAQ,EACR,KAAK,EAEL,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,MAAM,EACP,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,OAAO,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,CAC5B,UAAU,SAAS,cAAc,CAAC,QAAQ,CAAC,EAC3C,OAAO,SAAS,OAAO,EACvB,QAAQ,SAAS,OAAO,IACtB;IACF,SAAS,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;IAC3C,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB;;;;;;;;;;;;OAYG;IACH,QAAQ,EAAE,iBAAiB,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM,IAAI;IACvD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC5C,CAAC;AAEF,qBAAa,GAAG,CACd,UAAU,SAAS,cAAc,CAAC,QAAQ,CAAC,EAC3C,OAAO,SAAS,OAAO,EACvB,QAAQ,SAAS,OAAO,EACxB,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAChE,MAAM,SAAS,KAAK,GAAG,KAAK,CAC5B,YAAW,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC;aAiJxB,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhJ1B,OAAO,CAAC,QAAQ,CAAsB;IACtC,iFAAiF;IACjF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsB;IACvD,+DAA+D;IAC/D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAGjC;IACF,oFAAoF;IACpF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgD;IAC3E,+CAA+C;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAE/B;IAEF;;;OAGG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,EACpE,KAAK,EAAE,CAAC,EACR,IAAI,EAAE,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,GACzD,OAAO;IAIV;;;OAGG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,EAClE,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CACR,IAAI,EAAE,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,KACvD,IAAI,GACR,IAAI;IAKP;;OAEG;IACH,GAAG,CAAC,CAAC,SAAS,MAAM,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,EACnE,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CACR,IAAI,EAAE,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,KACvD,IAAI,GACR,IAAI;IAKP,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;IACrE,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4C;IAC5E;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IACpE;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAY;IACxC,2EAA2E;IAC3E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC;;;mDAG+C;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;IAElE;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC;gFAC4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwB;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyB;IACtD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA+B;IAClE,8EAA8E;IAC9E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuB;IACrD,uCAAuC;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IAEnD,gFAAgF;IAChF,IAAI,KAAK,IAAI,aAAa,CAAC,UAAU,CAAC,CAErC;IAED;;;;;;;;;;;;;OAaG;gBAEe,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,EAChD,OAAO,GAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAa,EACvE,aAAa,GAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,CAAa,EACzD,OAAO,GAAE,UAAe,EACxB,KAAK,GAAE,aAAa,CAAC,UAAU,CAAM;IAqIvC,kEAAkE;IAClE,OAAO,CAAC,iBAAiB,CAA4B;IAErD;;;;;;;;;OASG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBzB;;;;;OAKG;YACW,WAAW;IAiCzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgFG;IACG,EAAE,CAAC,IAAI,SAAS,MAAM,QAAQ,EAClC,MAAM,EAAE,IAAI,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EACtB,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EACjC,UAAU,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,OAAO,CAAC,EACvD,cAAc,UAAQ;IA4BxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;IACG,IAAI,CACR,SAAS,SAAS,MAAM,EACxB,UAAU,SAAS,OAAO,EAC1B,WAAW,SAAS,OAAO,EAE3B,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,EAChD,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,KAAK,IAAI,EAC9D,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACrC,IAAI,CAAC,IAAI,SAAS,MAAM,SAAS,GAAG,MAAM,EAC9C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,KAAK,IAAI,EACjE,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IAoB9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6CG;IACG,KAAK,CACT,KAAK,EAAE,KAAK,EACZ,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,KAAK,IAAI,GAC5D,OAAO,CAAC;QACT,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC;QACzC,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IAaF;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,WAAW,CACf,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC;IAQ/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;IACG,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAIhE,mDAAmD;IACnD,OAAO,CAAC,OAAO;IAIf;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;;;;;;uBAOmB;YACL,SAAS;IAiBvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4CG;IACG,SAAS,CACb,KAAK,GAAE,KAAgC,GACtC,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAInD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACH,kBAAkB,CAChB,KAAK,GAAE,KAAU,EACjB,SAAS,SAAS,EAClB,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GACtC,OAAO;IAIV;;;;;;;;;;;;;;;;OAgBG;IACH,iBAAiB;IAIjB;;;;OAIG;IACH,aAAa;IAIb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ5D;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ9D;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,eAAe,CAAC,OAAO,CAAC,EAAE;QAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAa7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;IACH,KAAK,CACH,UAAU,CAAC,EAAE,aAAa,EAAE,EAC5B,OAAO,CAAC,EAAE,YAAY,GACrB,aAAa,CAAC,YAAY,CAAC;IAI9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACG,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACG,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAyBzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,IAAI;CAG1C"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module audit
|
|
3
|
+
* @category Internal
|
|
4
|
+
*
|
|
5
|
+
* Operator-driven store audit (#723).
|
|
6
|
+
*
|
|
7
|
+
* Walks the connected store and yields per-category {@link AuditFinding}s.
|
|
8
|
+
* Each category answers a different "what should I do with this store?"
|
|
9
|
+
* question and pairs with a remediation:
|
|
10
|
+
*
|
|
11
|
+
* - `schema` → fix the data model (poison events, unknown names)
|
|
12
|
+
* - `close-candidate` → `app.close([...])`
|
|
13
|
+
* - `restart-candidate` → `app.close([{stream, restart:true}, …])`
|
|
14
|
+
* - `deprecated-load` → `app.close([...])` on the heaviest carriers
|
|
15
|
+
* - `reaction-health` → `app.unblock(...)` / `app.reset(...)`
|
|
16
|
+
* - `snapshot-drift` → manual `load({snap:true})` or wait for policy
|
|
17
|
+
* - `routing-health` → restart-with-new-config to re-lane
|
|
18
|
+
* - `correlation-gaps` → fix upstream correlator misconfig
|
|
19
|
+
* - `clock-anomalies` → infra remediation (clock skew)
|
|
20
|
+
*
|
|
21
|
+
* ## Single-scan multiplex (efficiency contract)
|
|
22
|
+
*
|
|
23
|
+
* Earlier draft had each category run its own `store.query(...)`,
|
|
24
|
+
* which meant N requested categories → N table walks. Bad for large
|
|
25
|
+
* stores. Refactored to a pass-based design: each category is a
|
|
26
|
+
* factory that returns an {@link AuditPass} with optional per-row
|
|
27
|
+
* callbacks (`onEvent` / `onStream` / `onStat`) and a `finalize` hook
|
|
28
|
+
* for any second-pass work. The dispatcher determines the UNION of
|
|
29
|
+
* required data sources, runs each *once*, and broadcasts each row
|
|
30
|
+
* to all interested passes. Worst case: three scans total (events,
|
|
31
|
+
* streams, stats) regardless of how many categories the operator
|
|
32
|
+
* requested. Most categories also share state — close-candidate and
|
|
33
|
+
* restart-candidate both consume the same `onStat` stream; schema,
|
|
34
|
+
* correlation-gaps, and clock-anomalies all hang off the same
|
|
35
|
+
* `onEvent` broadcast.
|
|
36
|
+
*
|
|
37
|
+
* Categories that need follow-up work (snapshot-drift's per-stream
|
|
38
|
+
* snapshot lookup, correlation-gaps' orphan-id check after collecting
|
|
39
|
+
* ids) do that in their `finalize` hook with their own targeted store
|
|
40
|
+
* calls — keeps the shared scan path minimal.
|
|
41
|
+
*
|
|
42
|
+
* Isolated from orchestration internals — `act.ts` builds the
|
|
43
|
+
* {@link AuditDeps} bag at `.build()` time and hands it here via
|
|
44
|
+
* a one-liner. The audit module never reaches into
|
|
45
|
+
* `internal/{event-sourcing,drain-cycle,settle,close-cycle}.ts`; it
|
|
46
|
+
* only reads through the deps interface and the public `Store`
|
|
47
|
+
* surface. Same shape as `act-tck` within the workspace — a peer of
|
|
48
|
+
* orchestration, not entangled with its private mechanics.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
import type { AuditCategory, AuditFinding, AuditOptions, Logger, State, Store } from "../types/index.js";
|
|
53
|
+
/**
|
|
54
|
+
* Snapshot of orchestrator state the audit reads. Built once at
|
|
55
|
+
* `app.build()`; the audit treats it as immutable for the duration
|
|
56
|
+
* of a call. The orchestrator never passes its own private maps in
|
|
57
|
+
* directly — this bag is the abstraction boundary so a future
|
|
58
|
+
* orchestration refactor can't accidentally entangle with audit
|
|
59
|
+
* logic.
|
|
60
|
+
*/
|
|
61
|
+
export type AuditDeps = {
|
|
62
|
+
readonly store: () => Store;
|
|
63
|
+
readonly logger: Logger;
|
|
64
|
+
/** event-name → state that registers it (for schema validation). */
|
|
65
|
+
readonly event_to_state: ReadonlyMap<string, State<any, any, any>>;
|
|
66
|
+
/** state-name → state (for snapshot-supported check on restart-candidate). */
|
|
67
|
+
readonly states: ReadonlyMap<string, State<any, any, any>>;
|
|
68
|
+
/** All event names the registry knows (for unknown-name detection). */
|
|
69
|
+
readonly known_events: ReadonlySet<string>;
|
|
70
|
+
/** Declared drain lanes (for routing-health unknown-lane). */
|
|
71
|
+
readonly declared_lanes: ReadonlySet<string>;
|
|
72
|
+
/**
|
|
73
|
+
* Event names that the registry has at least one reaction for —
|
|
74
|
+
* used by routing-health to detect "registered but unrouted"
|
|
75
|
+
* events. Normalized down from the internal `eventToLanes` map
|
|
76
|
+
* (which carries lane-set details audit doesn't need).
|
|
77
|
+
*/
|
|
78
|
+
readonly routed_events: ReadonlySet<string>;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Top-level audit dispatcher. Single-scan multiplex: each requested
|
|
82
|
+
* category contributes a `AuditPass`, the dispatcher determines the
|
|
83
|
+
* union of required data sources (events / streams / stats), runs
|
|
84
|
+
* each once, broadcasts rows, and yields per-category findings in
|
|
85
|
+
* the order the categories were requested.
|
|
86
|
+
*
|
|
87
|
+
* Callers can `break` the iteration early — the underlying scan
|
|
88
|
+
* loops have already completed by the time yield starts, so early
|
|
89
|
+
* break only saves the iteration over already-collected findings.
|
|
90
|
+
* (Per-row early termination during a scan isn't feasible without
|
|
91
|
+
* coordination across passes; the audit is bounded by `options.query`
|
|
92
|
+
* scoping rather than mid-scan cancellation.)
|
|
93
|
+
*/
|
|
94
|
+
export declare function audit(deps: AuditDeps, categories?: AuditCategory[], options?: AuditOptions): AsyncIterable<AuditFinding>;
|
|
95
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/internal/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EAEZ,MAAM,EAEN,KAAK,EACL,KAAK,EAGN,MAAM,mBAAmB,CAAC;AAG3B;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACnE,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3D,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,8DAA8D;IAC9D,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7C,CAAC;AAmDF;;;;;;;;;;;;;GAaG;AACH,wBAAuB,KAAK,CAC1B,IAAI,EAAE,SAAS,EACf,UAAU,CAAC,EAAE,aAAa,EAAE,EAC5B,OAAO,GAAE,YAAiB,GACzB,aAAa,CAAC,YAAY,CAAC,CA8C7B"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @internal
|
|
18
18
|
*/
|
|
19
|
+
export { type AuditDeps, audit } from "./audit.js";
|
|
19
20
|
export type { EventLaneSet } from "./build-classify.js";
|
|
20
21
|
export { ALL_LANES, classifyRegistry } from "./build-classify.js";
|
|
21
22
|
export { runCloseCycle } from "./close-cycle.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/internal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACtE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,MAAM,EACN,kBAAkB,EAClB,eAAe,EACf,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/internal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnD,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACtE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,MAAM,EACN,kBAAkB,EAClB,eAAe,EACf,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module act/types/audit
|
|
3
|
+
*
|
|
4
|
+
* Operator-driven store audit (#723).
|
|
5
|
+
*
|
|
6
|
+
* The `app.audit(...)` method walks the connected store and yields
|
|
7
|
+
* per-category findings — each tagged with the remediation it
|
|
8
|
+
* suggests. Same operator-driven category as `app.close()`,
|
|
9
|
+
* `app.reset()`, `app.unblock()`: never auto-invoked by the
|
|
10
|
+
* framework; the operator decides when to run it and what to do
|
|
11
|
+
* with the findings.
|
|
12
|
+
*
|
|
13
|
+
* Categories are independent — operators can request a subset
|
|
14
|
+
* (`app.audit(["schema", "deprecated-load"])`) or run everything by
|
|
15
|
+
* omitting the category list.
|
|
16
|
+
*
|
|
17
|
+
* Findings are yielded as an `AsyncIterable` so callers can break
|
|
18
|
+
* out early, pipe into Slack alerts, save to disk, etc. without
|
|
19
|
+
* loading the entire report in memory.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Audit category names. Each maps to a distinct family of findings
|
|
23
|
+
* and a distinct remediation. See {@link AuditFinding} for the
|
|
24
|
+
* shapes each category emits.
|
|
25
|
+
*/
|
|
26
|
+
export type AuditCategory = "schema" | "close-candidate" | "restart-candidate" | "deprecated-load" | "reaction-health" | "snapshot-drift" | "routing-health" | "correlation-gaps" | "clock-anomalies";
|
|
27
|
+
/**
|
|
28
|
+
* Tunable thresholds for categories whose findings depend on a
|
|
29
|
+
* cutoff. Sensible defaults are documented per field; operators
|
|
30
|
+
* can override per call.
|
|
31
|
+
*/
|
|
32
|
+
export type AuditThresholds = {
|
|
33
|
+
/** `close-candidate` (idle): days since head event committed. Default 90. */
|
|
34
|
+
idle_days?: number;
|
|
35
|
+
/** `restart-candidate`: minimum event count to consider close-with-restart. Default 10_000. */
|
|
36
|
+
restart_min?: number;
|
|
37
|
+
/** `reaction-health` (stuck-backoff): minutes since lease started. Default 30. */
|
|
38
|
+
stuck_minutes?: number;
|
|
39
|
+
/** `reaction-health` (near-block): retry count at which a stream is "about to block." Default 3. */
|
|
40
|
+
near_block?: number;
|
|
41
|
+
/** `deprecated-load`: minimum fraction-of-total to surface. Default 0.10. */
|
|
42
|
+
deprecated_min?: number;
|
|
43
|
+
/** `snapshot-drift`: minimum events since last snapshot to flag. Default 500. */
|
|
44
|
+
drift_min?: number;
|
|
45
|
+
/** `close-candidate` (terminal): event names the operator considers terminal. */
|
|
46
|
+
terminal_events?: string[];
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Audit options. Most categories run unconditionally over the
|
|
50
|
+
* store; `query` narrows the scan window (e.g., "only audit events
|
|
51
|
+
* committed since yesterday" for an incremental cron).
|
|
52
|
+
*/
|
|
53
|
+
export type AuditOptions = {
|
|
54
|
+
/**
|
|
55
|
+
* Query filter applied to event-table scans. Mirrors
|
|
56
|
+
* {@link Query} (stream / source / created_before / created_after /
|
|
57
|
+
* before / etc.). When omitted, the audit scans the whole table.
|
|
58
|
+
*/
|
|
59
|
+
query?: import("./action.js").Query;
|
|
60
|
+
/** Pagination size for event scans. Default 500. */
|
|
61
|
+
page_size?: number;
|
|
62
|
+
/** Per-category thresholds; see {@link AuditThresholds}. */
|
|
63
|
+
thresholds?: AuditThresholds;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Discriminated union of audit findings. Each shape carries enough
|
|
67
|
+
* context for the operator to act on the finding directly —
|
|
68
|
+
* stream name, event id, suggested remediation hints.
|
|
69
|
+
*/
|
|
70
|
+
export type AuditFinding = {
|
|
71
|
+
category: "schema";
|
|
72
|
+
stream: string;
|
|
73
|
+
event_id: number;
|
|
74
|
+
name: string;
|
|
75
|
+
reason: "unknown_event_name" | "schema_validation_failed";
|
|
76
|
+
zod_error?: unknown;
|
|
77
|
+
} | {
|
|
78
|
+
category: "close-candidate";
|
|
79
|
+
stream: string;
|
|
80
|
+
last_event_at: string;
|
|
81
|
+
reason: "terminal" | "idle";
|
|
82
|
+
idle_days?: number;
|
|
83
|
+
/** True when the state has a snapshot patch (`close({restart: true})` would work). */
|
|
84
|
+
restart_supported: boolean;
|
|
85
|
+
} | {
|
|
86
|
+
category: "restart-candidate";
|
|
87
|
+
stream: string;
|
|
88
|
+
count: number;
|
|
89
|
+
snaps: number;
|
|
90
|
+
} | {
|
|
91
|
+
category: "deprecated-load";
|
|
92
|
+
name: string;
|
|
93
|
+
current_version: string;
|
|
94
|
+
total: number;
|
|
95
|
+
top_streams: Array<{
|
|
96
|
+
stream: string;
|
|
97
|
+
count: number;
|
|
98
|
+
}>;
|
|
99
|
+
} | {
|
|
100
|
+
category: "reaction-health";
|
|
101
|
+
stream: string;
|
|
102
|
+
status: "blocked" | "near-block" | "stuck-backoff";
|
|
103
|
+
retry: number;
|
|
104
|
+
reason: string;
|
|
105
|
+
} | {
|
|
106
|
+
category: "snapshot-drift";
|
|
107
|
+
stream: string;
|
|
108
|
+
events_since_snap: number;
|
|
109
|
+
snap_at?: number;
|
|
110
|
+
} | {
|
|
111
|
+
category: "routing-health";
|
|
112
|
+
stream: string;
|
|
113
|
+
reason: "unknown-lane" | "unrouted";
|
|
114
|
+
lane?: string;
|
|
115
|
+
} | {
|
|
116
|
+
category: "correlation-gaps";
|
|
117
|
+
stream: string;
|
|
118
|
+
event_id: number;
|
|
119
|
+
reason: "orphan-parent" | "missing-correlation";
|
|
120
|
+
} | {
|
|
121
|
+
category: "clock-anomalies";
|
|
122
|
+
stream: string;
|
|
123
|
+
event_id: number;
|
|
124
|
+
reason: "future-created" | "out-of-order";
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/types/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* Import from this module to access all core framework types in one place.
|
|
11
11
|
*/
|
|
12
12
|
export type * from "./action.js";
|
|
13
|
+
export type * from "./audit.js";
|
|
13
14
|
export * from "./errors.js";
|
|
14
15
|
export type * from "./ports.js";
|
|
15
16
|
export type * from "./reaction.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,mBAAmB,aAAa,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,mBAAmB,YAAY,CAAC;AAChC,mBAAmB,eAAe,CAAC;AACnC,mBAAmB,eAAe,CAAC;AACnC,cAAc,cAAc,CAAC;AAE7B;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,2DAKf,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,SAAS,+DAOZ,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,mBAAmB,aAAa,CAAC;AACjC,mBAAmB,YAAY,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,mBAAmB,YAAY,CAAC;AAChC,mBAAmB,eAAe,CAAC;AACnC,mBAAmB,eAAe,CAAC;AACnC,cAAc,cAAc,CAAC;AAE7B;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,2DAKf,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,SAAS,+DAOZ,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/errors.ts","../src/types/schemas.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Actor,\n Message,\n Schema,\n Schemas,\n Snapshot,\n Target,\n} from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n StreamClosedError: \"ERR_STREAM_CLOSED\",\n NonRetryableError: \"ERR_NON_RETRYABLE\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @example Logging validation details\n * ```typescript\n * try {\n * await app.do(\"updateProfile\", target, payload);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * error.details.errors.forEach((err) => {\n * console.error(`Field ${err.path.join(\".\")}: ${err.message}`);\n * });\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n constructor(\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string,\n /** The invalid payload that failed validation */\n public readonly payload: any,\n /** Zod validation error details */\n public readonly details: any\n ) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TKey - Action name\n * @template TActor - Actor type extending base Actor\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @example User-friendly error messages\n * ```typescript\n * try {\n * await app.do(\"closeTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * // Present friendly message to user\n * if (error.description === \"Ticket must be open\") {\n * return { error: \"This ticket is already closed\" };\n * } else if (error.description === \"Not authorized\") {\n * return { error: \"You don't have permission to close this ticket\" };\n * }\n * }\n * }\n * ```\n *\n * @example Logging with context\n * ```typescript\n * try {\n * await app.do(\"transfer\", target, { to: \"account2\", amount: 500 });\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * logger.error({\n * action: error.action,\n * stream: error.target.stream,\n * actor: error.target.actor,\n * reason: error.description,\n * balance: error.snapshot.state.balance,\n * attempted: error.payload.amount\n * }, \"Invariant violation\");\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n TActor extends Actor = Actor,\n> extends Error {\n constructor(\n /** The action that was attempted */\n readonly action: TKey,\n /** The action payload that was provided */\n readonly payload: Readonly<TActions[TKey]>,\n /** The target stream and actor context */\n readonly target: Target<TActor>,\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<TState, TEvents>,\n /** Human-readable description of why the invariant failed */\n readonly description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @example Logging concurrency conflicts\n * ```typescript\n * try {\n * await app.do(\"updateInventory\", target, payload);\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * logger.warn({\n * stream: error.stream,\n * expectedVersion: error.expectedVersion,\n * actualVersion: error.lastVersion,\n * events: error.events.map(e => e.name)\n * }, \"Concurrent modification detected\");\n * }\n * }\n * ```\n *\n * @example User feedback for conflicts\n * ```typescript\n * try {\n * await app.do(\"editDocument\", target, { content: newContent });\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * return {\n * error: \"This document was modified by another user. Please refresh and try again.\",\n * code: \"CONCURRENT_MODIFICATION\"\n * };\n * }\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\nexport class ConcurrencyError extends Error {\n constructor(\n /** The stream that had the concurrent modification */\n public readonly stream: string,\n /** The actual current version in the store */\n public readonly lastVersion: number,\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[],\n /** The version number that was expected */\n public readonly expectedVersion: number\n ) {\n // Message lists stream + event names only. Payloads remain accessible\n // via `error.events` for callers who need them — keeping them out of\n // the message avoids MB-scale strings on contended writes and keeps\n // potentially-sensitive data out of log streams.\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n }\n}\n\n/**\n * Thrown when attempting to write to a stream that has been closed\n * with a tombstone event.\n *\n * A tombstoned stream is permanently closed — no further actions can\n * be executed against it. The only way to reopen a tombstoned stream\n * is through `Act.close()` with a `restart` callback.\n *\n * @example\n * ```typescript\n * import { StreamClosedError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"updateTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof StreamClosedError) {\n * console.error(`Stream ${error.stream} is closed`);\n * }\n * }\n * ```\n *\n * @see {@link Act.close} for closing streams\n */\nexport class StreamClosedError extends Error {\n constructor(\n /** The stream that is closed */\n public readonly stream: string\n ) {\n super(`Stream \"${stream}\" is closed (tombstoned)`);\n this.name = Errors.StreamClosedError;\n }\n}\n\n/**\n * Thrown by a reaction handler to signal that the failure is permanent\n * and the drain pipeline should block the stream immediately, without\n * consuming the rest of the `maxRetries` budget.\n *\n * The drain finalizer detects `instanceof NonRetryableError` and forces\n * `block = options.blockOnError` regardless of `lease.retry`. When\n * `blockOnError` is `false`, behavior is unchanged (drain keeps retrying\n * forever) — the class never overrides the operator's explicit \"never\n * block\" choice.\n *\n * Use this for failures the handler *knows* won't get better on retry:\n * a 4xx from a webhook, a `ZodError` on malformed input, a \"user\n * deleted\" 404 from a downstream API. Use regular `Error` (or a\n * subclass) for transient failures so the existing retry-with-backoff\n * loop applies.\n *\n * @example Wrapping a permanent downstream error\n * ```typescript\n * import { NonRetryableError } from \"@rotorsoft/act\";\n *\n * .on(\"OrderConfirmed\")\n * .do(async (event) => {\n * const res = await fetch(url, ...);\n * if (res.status >= 400 && res.status < 500) {\n * throw new NonRetryableError(\n * `webhook ${url} responded ${res.status}`,\n * { cause: await res.text() }\n * );\n * }\n * if (!res.ok) throw new Error(`webhook ${url} responded ${res.status}`);\n * })\n * ```\n *\n * @example Marking validation failures as non-retryable\n * ```typescript\n * .on(\"PaymentReceived\")\n * .do(async (event) => {\n * const parsed = Schema.safeParse(event.data);\n * if (!parsed.success) {\n * throw new NonRetryableError(\"payment payload failed validation\", {\n * cause: parsed.error,\n * });\n * }\n * // ... handle parsed payload\n * })\n * ```\n */\nexport class NonRetryableError extends Error {\n /** The original failure, if any. Mirrors the standard `Error.cause` shape. */\n public override readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = Errors.NonRetryableError;\n this.cause = options?.cause;\n }\n}\n","import { type ZodObject, type ZodRawShape, z } from \"zod\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n stream_exact: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types/errors.ts","../src/types/schemas.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Actor,\n Message,\n Schema,\n Schemas,\n Snapshot,\n Target,\n} from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n StreamClosedError: \"ERR_STREAM_CLOSED\",\n NonRetryableError: \"ERR_NON_RETRYABLE\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @example Logging validation details\n * ```typescript\n * try {\n * await app.do(\"updateProfile\", target, payload);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * error.details.errors.forEach((err) => {\n * console.error(`Field ${err.path.join(\".\")}: ${err.message}`);\n * });\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n constructor(\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string,\n /** The invalid payload that failed validation */\n public readonly payload: any,\n /** Zod validation error details */\n public readonly details: any\n ) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TKey - Action name\n * @template TActor - Actor type extending base Actor\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @example User-friendly error messages\n * ```typescript\n * try {\n * await app.do(\"closeTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * // Present friendly message to user\n * if (error.description === \"Ticket must be open\") {\n * return { error: \"This ticket is already closed\" };\n * } else if (error.description === \"Not authorized\") {\n * return { error: \"You don't have permission to close this ticket\" };\n * }\n * }\n * }\n * ```\n *\n * @example Logging with context\n * ```typescript\n * try {\n * await app.do(\"transfer\", target, { to: \"account2\", amount: 500 });\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * logger.error({\n * action: error.action,\n * stream: error.target.stream,\n * actor: error.target.actor,\n * reason: error.description,\n * balance: error.snapshot.state.balance,\n * attempted: error.payload.amount\n * }, \"Invariant violation\");\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n TActor extends Actor = Actor,\n> extends Error {\n constructor(\n /** The action that was attempted */\n readonly action: TKey,\n /** The action payload that was provided */\n readonly payload: Readonly<TActions[TKey]>,\n /** The target stream and actor context */\n readonly target: Target<TActor>,\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<TState, TEvents>,\n /** Human-readable description of why the invariant failed */\n readonly description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @example Logging concurrency conflicts\n * ```typescript\n * try {\n * await app.do(\"updateInventory\", target, payload);\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * logger.warn({\n * stream: error.stream,\n * expectedVersion: error.expectedVersion,\n * actualVersion: error.lastVersion,\n * events: error.events.map(e => e.name)\n * }, \"Concurrent modification detected\");\n * }\n * }\n * ```\n *\n * @example User feedback for conflicts\n * ```typescript\n * try {\n * await app.do(\"editDocument\", target, { content: newContent });\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * return {\n * error: \"This document was modified by another user. Please refresh and try again.\",\n * code: \"CONCURRENT_MODIFICATION\"\n * };\n * }\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\nexport class ConcurrencyError extends Error {\n constructor(\n /** The stream that had the concurrent modification */\n public readonly stream: string,\n /** The actual current version in the store */\n public readonly lastVersion: number,\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[],\n /** The version number that was expected */\n public readonly expectedVersion: number\n ) {\n // Message lists stream + event names only. Payloads remain accessible\n // via `error.events` for callers who need them — keeping them out of\n // the message avoids MB-scale strings on contended writes and keeps\n // potentially-sensitive data out of log streams.\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n }\n}\n\n/**\n * Thrown when attempting to write to a stream that has been closed\n * with a tombstone event.\n *\n * A tombstoned stream is permanently closed — no further actions can\n * be executed against it. The only way to reopen a tombstoned stream\n * is through `Act.close()` with a `restart` callback.\n *\n * @example\n * ```typescript\n * import { StreamClosedError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"updateTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof StreamClosedError) {\n * console.error(`Stream ${error.stream} is closed`);\n * }\n * }\n * ```\n *\n * @see {@link Act.close} for closing streams\n */\nexport class StreamClosedError extends Error {\n constructor(\n /** The stream that is closed */\n public readonly stream: string\n ) {\n super(`Stream \"${stream}\" is closed (tombstoned)`);\n this.name = Errors.StreamClosedError;\n }\n}\n\n/**\n * Thrown by a reaction handler to signal that the failure is permanent\n * and the drain pipeline should block the stream immediately, without\n * consuming the rest of the `maxRetries` budget.\n *\n * The drain finalizer detects `instanceof NonRetryableError` and forces\n * `block = options.blockOnError` regardless of `lease.retry`. When\n * `blockOnError` is `false`, behavior is unchanged (drain keeps retrying\n * forever) — the class never overrides the operator's explicit \"never\n * block\" choice.\n *\n * Use this for failures the handler *knows* won't get better on retry:\n * a 4xx from a webhook, a `ZodError` on malformed input, a \"user\n * deleted\" 404 from a downstream API. Use regular `Error` (or a\n * subclass) for transient failures so the existing retry-with-backoff\n * loop applies.\n *\n * @example Wrapping a permanent downstream error\n * ```typescript\n * import { NonRetryableError } from \"@rotorsoft/act\";\n *\n * .on(\"OrderConfirmed\")\n * .do(async (event) => {\n * const res = await fetch(url, ...);\n * if (res.status >= 400 && res.status < 500) {\n * throw new NonRetryableError(\n * `webhook ${url} responded ${res.status}`,\n * { cause: await res.text() }\n * );\n * }\n * if (!res.ok) throw new Error(`webhook ${url} responded ${res.status}`);\n * })\n * ```\n *\n * @example Marking validation failures as non-retryable\n * ```typescript\n * .on(\"PaymentReceived\")\n * .do(async (event) => {\n * const parsed = Schema.safeParse(event.data);\n * if (!parsed.success) {\n * throw new NonRetryableError(\"payment payload failed validation\", {\n * cause: parsed.error,\n * });\n * }\n * // ... handle parsed payload\n * })\n * ```\n */\nexport class NonRetryableError extends Error {\n /** The original failure, if any. Mirrors the standard `Error.cause` shape. */\n public override readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = Errors.NonRetryableError;\n this.cause = options?.cause;\n }\n}\n","import { type ZodObject, type ZodRawShape, z } from \"zod\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n stream_exact: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport type * from \"./audit.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n"],"mappings":";AAmBO,IAAM,SAAS;AAAA,EACpB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,mBAAmB;AACrB;AA2CO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YAEkB,QAEA,SAEA,SAChB;AACA,UAAM,WAAW,MAAM,UAAU;AANjB;AAEA;AAEA;AAGhB,SAAK,OAAO,OAAO;AAAA,EACrB;AACF;AAuEO,IAAM,iBAAN,cAMG,MAAM;AAAA,EACd,YAEW,QAEA,SAEA,QAEA,UAEA,aACT;AACA,UAAM,GAAG,MAAgB,sBAAsB,WAAW,EAAE;AAVnD;AAEA;AAEA;AAEA;AAEA;AAGT,SAAK,OAAO,OAAO;AAAA,EACrB;AACF;AAuEO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YAEkB,QAEA,aAEA,QAEA,iBAChB;AAKA;AAAA,MACE,iCAAiC,OAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE,IAAI,EAAE,EAChC;AAAA,QACC;AAAA,MACF,CAAC,uBAAuB,eAAe,sBAAsB,WAAW;AAAA,IAC5E;AAlBgB;AAEA;AAEA;AAEA;AAahB,SAAK,OAAO,OAAO;AAAA,EACrB;AACF;AAyBO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC3C,YAEkB,QAChB;AACA,UAAM,WAAW,MAAM,0BAA0B;AAFjC;AAGhB,SAAK,OAAO,OAAO;AAAA,EACrB;AACF;AAkDO,IAAM,oBAAN,cAAgC,MAAM;AAAA;AAAA,EAElB;AAAA,EAEzB,YAAY,SAAiB,SAA+B;AAC1D,UAAM,OAAO;AACb,SAAK,OAAO,OAAO;AACnB,SAAK,QAAQ,SAAS;AAAA,EACxB;AACF;;;ACxWA,SAA2C,SAAS;AAY7C,IAAM,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,CAAC;AAK/C,IAAM,cAAc,EACxB,OAAO;AAAA,EACN,IAAI,EAAE,OAAO;AAAA,EACb,MAAM,EAAE,OAAO;AACjB,CAAC,EACA,MAAM,EACN,SAAS;AAKL,IAAM,eAAe,EACzB,OAAO;AAAA,EACN,QAAQ,EAAE,OAAO;AAAA,EACjB,OAAO;AAAA,EACP,iBAAiB,EAAE,OAAO,EAAE,SAAS;AACvC,CAAC,EACA,MAAM,EACN,SAAS;AAKL,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,IAAI,EAAE,OAAO;AAAA,EACb,MAAM,EAAE,OAAO;AAAA,EACf,QAAQ,EAAE,OAAO;AACnB,CAAC;AAKM,IAAM,kBAAkB,EAC5B,OAAO;AAAA,EACN,aAAa,EAAE,OAAO;AAAA,EACtB,WAAW,EAAE,OAAO;AAAA,IAClB,QAAQ,aAAa,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,SAAS;AAAA,IAClE,OAAO,qBAAqB,SAAS;AAAA,EACvC,CAAC;AACH,CAAC,EACA,SAAS;AAKL,IAAM,sBAAsB,EAChC,OAAO;AAAA,EACN,IAAI,EAAE,OAAO;AAAA,EACb,QAAQ,EAAE,OAAO;AAAA,EACjB,SAAS,EAAE,OAAO;AAAA,EAClB,SAAS,EAAE,KAAK;AAAA,EAChB,MAAM;AACR,CAAC,EACA,SAAS;AAiBL,IAAM,cAAc,EACxB,OAAO;AAAA,EACN,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS;AAAA,EACnC,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,gBAAgB,EAAE,KAAK,EAAE,SAAS;AAAA,EAClC,eAAe,EAAE,KAAK,EAAE,SAAS;AAAA,EACjC,UAAU,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC/B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,YAAY,EAAE,QAAQ,EAAE,SAAS;AAAA,EACjC,cAAc,EAAE,QAAQ,EAAE,SAAS;AACrC,CAAC,EACA,SAAS;;;AC3EL,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAWO,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
Environments,
|
|
4
4
|
LogLevels,
|
|
5
5
|
ValidationError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TZWDSNSN.js";
|
|
7
7
|
|
|
8
8
|
// src/adapters/console-logger.ts
|
|
9
9
|
var LEVEL_VALUES = {
|
|
@@ -1045,4 +1045,4 @@ export {
|
|
|
1045
1045
|
TOMBSTONE_EVENT,
|
|
1046
1046
|
DEFAULT_LANE
|
|
1047
1047
|
};
|
|
1048
|
-
//# sourceMappingURL=chunk-
|
|
1048
|
+
//# sourceMappingURL=chunk-VC6MSVC3.js.map
|