@rotorsoft/act 1.19.0 → 1.20.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/dist/.tsbuildinfo +1 -1
- package/dist/@types/builders/act-builder.d.ts.map +1 -1
- package/dist/@types/builders/projection-builder.d.ts +41 -12
- package/dist/@types/builders/projection-builder.d.ts.map +1 -1
- package/dist/@types/internal/event-sourcing.d.ts +1 -1
- package/dist/@types/internal/event-sourcing.d.ts.map +1 -1
- package/dist/index.cjs +74 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +74 -33
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* actions, and are pure side-effect handlers routed to a named stream.
|
|
10
10
|
*/
|
|
11
11
|
import type { ZodType } from "zod";
|
|
12
|
+
import { type FoldConfig } from "../internal/index.js";
|
|
12
13
|
import type { BatchHandler, CacheEntry, Committed, EventRegister, FoldOptions, ReactionResolver, Schema, Schemas, State } from "../types/index.js";
|
|
13
14
|
/**
|
|
14
15
|
* A self-contained projection grouping read-model update handlers.
|
|
@@ -21,6 +22,45 @@ export type Projection<TEvents extends Schemas> = {
|
|
|
21
22
|
readonly events: EventRegister<TEvents>;
|
|
22
23
|
readonly target?: string;
|
|
23
24
|
readonly batchHandler?: BatchHandler<TEvents>;
|
|
25
|
+
/**
|
|
26
|
+
* State-fold spec from `.of()`. The builder only records intent — the
|
|
27
|
+
* orchestrator resolves the REGISTRY-MERGED full state at
|
|
28
|
+
* `act().build()` and synthesizes the batch handler there, so the
|
|
29
|
+
* fold always covers every reducer of the state, including partials
|
|
30
|
+
* merged by slices the projection never saw.
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
readonly fold?: {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly flush: (rows: ReadonlyArray<CacheEntry<any>>) => Promise<void>;
|
|
36
|
+
readonly config: FoldConfig;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The `.of()` continuation: state projections flush the cache layer
|
|
41
|
+
* outward — the rows ARE the streams' {@link CacheEntry} values, one
|
|
42
|
+
* per dirty stream per flush round. Must be an idempotent upsert keyed
|
|
43
|
+
* on `stream` (guard with `event_id` for order safety when a rebuild
|
|
44
|
+
* races a live worker).
|
|
45
|
+
*/
|
|
46
|
+
type FoldFlush<TState extends Schema, TE extends Schemas> = {
|
|
47
|
+
flush: (handler: (rows: ReadonlyArray<CacheEntry<TState>>) => Promise<void>) => {
|
|
48
|
+
build: () => Projection<TE>;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* `.of()` accepts the partials of ONE state (same name, enforced at the
|
|
53
|
+
* type level via `TName`) purely for typing and event registration —
|
|
54
|
+
* the fold itself always runs on the registry-merged full state,
|
|
55
|
+
* resolved at `act().build()`. Passing every partial is required: the
|
|
56
|
+
* orchestrator validates completeness at build and throws on missing
|
|
57
|
+
* events.
|
|
58
|
+
*/
|
|
59
|
+
type OfSignatures = {
|
|
60
|
+
<TS1 extends Schema, TE1 extends Schemas, TA1 extends Schemas, TN extends string>(s1: State<TS1, TE1, TA1, TN>, options?: FoldOptions): FoldFlush<TS1, TE1>;
|
|
61
|
+
<TS1 extends Schema, TE1 extends Schemas, TA1 extends Schemas, TS2 extends Schema, TE2 extends Schemas, TA2 extends Schemas, TN extends string>(s1: State<TS1, TE1, TA1, TN>, s2: State<TS2, TE2, TA2, TN>, options?: FoldOptions): FoldFlush<TS1 & TS2, TE1 & TE2>;
|
|
62
|
+
<TS1 extends Schema, TE1 extends Schemas, TA1 extends Schemas, TS2 extends Schema, TE2 extends Schemas, TA2 extends Schemas, TS3 extends Schema, TE3 extends Schemas, TA3 extends Schemas, TN extends string>(s1: State<TS1, TE1, TA1, TN>, s2: State<TS2, TE2, TA2, TN>, s3: State<TS3, TE3, TA3, TN>, options?: FoldOptions): FoldFlush<TS1 & TS2 & TS3, TE1 & TE2 & TE3>;
|
|
63
|
+
<TS1 extends Schema, TE1 extends Schemas, TA1 extends Schemas, TS2 extends Schema, TE2 extends Schemas, TA2 extends Schemas, TS3 extends Schema, TE3 extends Schemas, TA3 extends Schemas, TS4 extends Schema, TE4 extends Schemas, TA4 extends Schemas, TN extends string>(s1: State<TS1, TE1, TA1, TN>, s2: State<TS2, TE2, TA2, TN>, s3: State<TS3, TE3, TA3, TN>, s4: State<TS4, TE4, TA4, TN>, options?: FoldOptions): FoldFlush<TS1 & TS2 & TS3 & TS4, TE1 & TE2 & TE3 & TE4>;
|
|
24
64
|
};
|
|
25
65
|
/** Helper: a single-key record mapping an event name to its Zod schema. */
|
|
26
66
|
type EventEntry<TKey extends string = string, TData extends Schema = Schema> = {
|
|
@@ -99,18 +139,7 @@ export type ProjectionBuilder<TEvents extends Schemas, TTarget extends string |
|
|
|
99
139
|
* `.build()` — a projection either folds a state or declares
|
|
100
140
|
* handlers, never both.
|
|
101
141
|
*/
|
|
102
|
-
of:
|
|
103
|
-
/**
|
|
104
|
-
* The sink: state projections flush the cache layer outward —
|
|
105
|
-
* the rows ARE the streams' {@link CacheEntry} values, one per
|
|
106
|
-
* dirty stream per flush round. Must be an idempotent upsert
|
|
107
|
-
* keyed on `stream` (guard with `event_id` for order safety
|
|
108
|
-
* when a rebuild races a live worker).
|
|
109
|
-
*/
|
|
110
|
-
flush: (handler: (rows: ReadonlyArray<CacheEntry<TState>>) => Promise<void>) => {
|
|
111
|
-
build: () => Projection<TE>;
|
|
112
|
-
};
|
|
113
|
-
};
|
|
142
|
+
of: OfSignatures;
|
|
114
143
|
} : {}) : {});
|
|
115
144
|
/**
|
|
116
145
|
* Creates a new projection builder with a static target stream.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projection-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/projection-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"projection-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/projection-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -46,7 +46,7 @@ export interface EsOps {
|
|
|
46
46
|
* @example
|
|
47
47
|
* await snap(snapshot);
|
|
48
48
|
*/
|
|
49
|
-
export declare function snap<TState extends Schema, TEvents extends Schemas>(snapshot: Snapshot<TState, TEvents>): Promise<
|
|
49
|
+
export declare function snap<TState extends Schema, TEvents extends Schemas>(snapshot: Snapshot<TState, TEvents>): Promise<Committed<TEvents, keyof TEvents> | undefined>;
|
|
50
50
|
/**
|
|
51
51
|
* Commits a tombstone event with optimistic concurrency, returning the
|
|
52
52
|
* committed record on success or `undefined` if the stream moved past
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-sourcing.d.ts","sourceRoot":"","sources":["../../../src/internal/event-sourcing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AASH,OAAO,KAAK,EACV,SAAS,EAET,SAAS,EAGT,WAAW,EACX,UAAU,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,OAAO,EACP,QAAQ,EACR,KAAK,EACL,MAAM,EACP,MAAM,mBAAmB,CAAC;AAa3B;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,SAAS,MAAM,EACrB,OAAO,SAAS,OAAO,EACvB,QAAQ,SAAS,OAAO,EACxB,IAAI,SAAS,MAAM,QAAQ,EAE3B,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,EACpC,MAAM,EAAE,IAAI,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EACjC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,KACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;AAE1C,gBAAgB;AAChB,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,OAAO,SAAS,CAAC;CAC7B;AAED;;;GAGG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAsB,IAAI,CAAC,MAAM,SAAS,MAAM,EAAE,OAAO,SAAS,OAAO,EACvE,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"event-sourcing.d.ts","sourceRoot":"","sources":["../../../src/internal/event-sourcing.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -3024,7 +3024,7 @@ var DEFAULT_BATCH = 500;
|
|
|
3024
3024
|
async function snap(snapshot) {
|
|
3025
3025
|
const { id, stream, name, meta, version } = snapshot.event;
|
|
3026
3026
|
try {
|
|
3027
|
-
await store2().commit(
|
|
3027
|
+
const [committed] = await store2().commit(
|
|
3028
3028
|
stream,
|
|
3029
3029
|
[{ name: SNAP_EVENT, data: snapshot.state }],
|
|
3030
3030
|
{
|
|
@@ -3034,6 +3034,7 @@ async function snap(snapshot) {
|
|
|
3034
3034
|
version
|
|
3035
3035
|
// IMPORTANT! - state events are committed right after the snapshot event
|
|
3036
3036
|
);
|
|
3037
|
+
return committed;
|
|
3037
3038
|
} catch (error) {
|
|
3038
3039
|
const reason = error instanceof Error ? error.message : String(error);
|
|
3039
3040
|
log().warn(
|
|
@@ -3246,7 +3247,7 @@ async function action(me, action2, target, payload, options) {
|
|
|
3246
3247
|
const snapshot = await load(me, { stream, actor: target.actor });
|
|
3247
3248
|
if (snapshot.event?.name === TOMBSTONE_EVENT)
|
|
3248
3249
|
throw new StreamClosedError(stream);
|
|
3249
|
-
const expected = expectedVersion ?? snapshot.
|
|
3250
|
+
const expected = expectedVersion ?? (snapshot.version >= 0 ? snapshot.version : void 0);
|
|
3250
3251
|
if (me.given) {
|
|
3251
3252
|
const invariants = me.given[action2] || [];
|
|
3252
3253
|
invariants.forEach(({ valid: valid2, description }) => {
|
|
@@ -3328,18 +3329,22 @@ async function action(me, action2, target, payload, options) {
|
|
|
3328
3329
|
};
|
|
3329
3330
|
});
|
|
3330
3331
|
const last = snapshots.at(-1);
|
|
3331
|
-
const
|
|
3332
|
+
const contiguous = committed[0].version === snapshot.version + 1;
|
|
3333
|
+
const snapped = contiguous && me.snap?.(last);
|
|
3334
|
+
const snap_event = snapped ? await snap(last) : void 0;
|
|
3332
3335
|
if (!me.pii_aware) {
|
|
3333
|
-
|
|
3334
|
-
stream,
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3336
|
+
if (contiguous)
|
|
3337
|
+
cache2().set(stream, {
|
|
3338
|
+
stream,
|
|
3339
|
+
state: last.state,
|
|
3340
|
+
version: snap_event?.version ?? last.event.version,
|
|
3341
|
+
event_id: snap_event?.id ?? last.event.id,
|
|
3342
|
+
patches: snap_event ? 0 : last.patches,
|
|
3343
|
+
snaps: snap_event ? last.snaps + 1 : last.snaps
|
|
3344
|
+
}).catch((err) => log().error(err));
|
|
3345
|
+
else
|
|
3346
|
+
cache2().invalidate(stream).catch((err) => log().error(err));
|
|
3341
3347
|
}
|
|
3342
|
-
if (snapped) void snap(last);
|
|
3343
3348
|
return snapshots;
|
|
3344
3349
|
} catch (error) {
|
|
3345
3350
|
if (!(error instanceof ConcurrencyError)) throw error;
|
|
@@ -5208,6 +5213,7 @@ function act() {
|
|
|
5208
5213
|
autoclose_archiver: (state_name) => _aa.get(state_name) ?? null
|
|
5209
5214
|
};
|
|
5210
5215
|
const pending_projections = [];
|
|
5216
|
+
const fold_projections = [];
|
|
5211
5217
|
const batch_handlers = /* @__PURE__ */ new Map();
|
|
5212
5218
|
const lanes = [];
|
|
5213
5219
|
let _built = false;
|
|
@@ -5273,6 +5279,8 @@ function act() {
|
|
|
5273
5279
|
withProjection: (proj) => {
|
|
5274
5280
|
merge_projection(proj, registry.events);
|
|
5275
5281
|
register_batch_handler(proj, batch_handlers);
|
|
5282
|
+
if (proj.fold)
|
|
5283
|
+
fold_projections.push(proj);
|
|
5276
5284
|
return builder;
|
|
5277
5285
|
},
|
|
5278
5286
|
withActor: () => builder,
|
|
@@ -5286,6 +5294,26 @@ function act() {
|
|
|
5286
5294
|
for (const proj of pending_projections) {
|
|
5287
5295
|
merge_projection(proj, registry.events);
|
|
5288
5296
|
register_batch_handler(proj, batch_handlers);
|
|
5297
|
+
if (proj.fold) fold_projections.push(proj);
|
|
5298
|
+
}
|
|
5299
|
+
for (const proj of fold_projections) {
|
|
5300
|
+
const fold = proj.fold;
|
|
5301
|
+
const merged = states.get(fold.name);
|
|
5302
|
+
if (!merged)
|
|
5303
|
+
throw new Error(
|
|
5304
|
+
`State projection "${proj.target}" folds "${fold.name}", which is not registered \u2014 add it via withState/withSlice before build()`
|
|
5305
|
+
);
|
|
5306
|
+
const missing = Object.keys(merged.events).filter(
|
|
5307
|
+
(event_name) => !(event_name in proj.events)
|
|
5308
|
+
);
|
|
5309
|
+
if (missing.length > 0)
|
|
5310
|
+
throw new Error(
|
|
5311
|
+
`State projection "${proj.target}" of "${fold.name}" is missing events ${missing.join(", ")} \u2014 pass every partial of the state to .of()`
|
|
5312
|
+
);
|
|
5313
|
+
batch_handlers.set(
|
|
5314
|
+
proj.target,
|
|
5315
|
+
make_fold_handler(merged, fold.flush, fold.config)
|
|
5316
|
+
);
|
|
5289
5317
|
}
|
|
5290
5318
|
finalize_deprecations();
|
|
5291
5319
|
validate_lane_references(registry, lanes);
|
|
@@ -5428,39 +5456,52 @@ function _projection(target) {
|
|
|
5428
5456
|
batchHandler: handler
|
|
5429
5457
|
})
|
|
5430
5458
|
}),
|
|
5431
|
-
of: (
|
|
5459
|
+
of: (...args) => {
|
|
5432
5460
|
if (Object.keys(events).length > 0)
|
|
5433
5461
|
throw new Error(
|
|
5434
5462
|
`Projection "${target}" mixes .of() with .on() handlers \u2014 a projection either folds a state or declares handlers, never both`
|
|
5435
5463
|
);
|
|
5464
|
+
const is_state = (a) => !!a && typeof a.init === "function";
|
|
5465
|
+
const partials = args.filter(is_state);
|
|
5466
|
+
const options = args.find((a) => !is_state(a)) ?? {};
|
|
5467
|
+
if (partials.length === 0)
|
|
5468
|
+
throw new Error(`Projection "${target}" .of() requires a state`);
|
|
5469
|
+
const name = partials[0].name;
|
|
5470
|
+
for (const partial of partials)
|
|
5471
|
+
if (partial.name !== name)
|
|
5472
|
+
throw new Error(
|
|
5473
|
+
`Projection "${target}" .of() partials must share one state name \u2014 got "${name}" and "${partial.name}"`
|
|
5474
|
+
);
|
|
5436
5475
|
const config2 = resolveFoldConfig(options);
|
|
5437
5476
|
const fold_events = {};
|
|
5438
|
-
for (const
|
|
5439
|
-
const
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5477
|
+
for (const partial of partials)
|
|
5478
|
+
for (const [event_name, schema] of Object.entries(partial.events)) {
|
|
5479
|
+
if (event_name in fold_events) continue;
|
|
5480
|
+
const noop2 = {
|
|
5481
|
+
[`${target}_fold`]: async () => {
|
|
5482
|
+
}
|
|
5483
|
+
}[`${target}_fold`];
|
|
5484
|
+
fold_events[event_name] = {
|
|
5485
|
+
schema,
|
|
5486
|
+
reactions: /* @__PURE__ */ new Map([
|
|
5487
|
+
[
|
|
5488
|
+
`${target}_fold`,
|
|
5489
|
+
{
|
|
5490
|
+
handler: noop2,
|
|
5491
|
+
resolver: { target },
|
|
5492
|
+
options: { blockOnError: true, maxRetries: 3 }
|
|
5493
|
+
}
|
|
5494
|
+
]
|
|
5495
|
+
])
|
|
5496
|
+
};
|
|
5497
|
+
}
|
|
5457
5498
|
return {
|
|
5458
5499
|
flush: (handler) => ({
|
|
5459
5500
|
build: () => ({
|
|
5460
5501
|
_tag: "Projection",
|
|
5461
5502
|
events: fold_events,
|
|
5462
5503
|
target,
|
|
5463
|
-
|
|
5504
|
+
fold: { name, flush: handler, config: config2 }
|
|
5464
5505
|
})
|
|
5465
5506
|
})
|
|
5466
5507
|
};
|