@rotorsoft/act 0.31.1 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/act-builder.d.ts.map +1 -1
- package/dist/@types/act.d.ts +4 -0
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/internal/drain.d.ts +43 -0
- package/dist/@types/internal/drain.d.ts.map +1 -0
- package/dist/@types/{event-sourcing.d.ts → internal/event-sourcing.d.ts} +15 -2
- package/dist/@types/internal/event-sourcing.d.ts.map +1 -0
- package/dist/@types/internal/index.d.ts +17 -0
- package/dist/@types/internal/index.d.ts.map +1 -0
- package/dist/@types/{merge.d.ts → internal/merge.d.ts} +2 -2
- package/dist/@types/internal/merge.d.ts.map +1 -0
- package/dist/@types/internal/tracing.d.ts +37 -0
- package/dist/@types/internal/tracing.d.ts.map +1 -0
- package/dist/@types/ports.d.ts +1 -25
- package/dist/@types/ports.d.ts.map +1 -1
- package/dist/@types/projection-builder.d.ts.map +1 -1
- package/dist/@types/slice-builder.d.ts.map +1 -1
- package/dist/chunk-JBKZJXQZ.js +127 -0
- package/dist/chunk-JBKZJXQZ.js.map +1 -0
- package/dist/index.cjs +294 -244
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +322 -366
- package/dist/index.js.map +1 -1
- package/dist/types/index.cjs +166 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.js +33 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +6 -1
- package/dist/@types/event-sourcing.d.ts.map +0 -1
- package/dist/@types/merge.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ActorSchema,
|
|
3
|
+
CausationEventSchema,
|
|
4
|
+
CommittedMetaSchema,
|
|
5
|
+
ConcurrencyError,
|
|
6
|
+
Environments,
|
|
7
|
+
Errors,
|
|
8
|
+
EventMetaSchema,
|
|
9
|
+
InvariantError,
|
|
10
|
+
LogLevels,
|
|
11
|
+
QuerySchema,
|
|
12
|
+
StreamClosedError,
|
|
13
|
+
TargetSchema,
|
|
14
|
+
ValidationError,
|
|
15
|
+
ZodEmpty
|
|
16
|
+
} from "./chunk-JBKZJXQZ.js";
|
|
17
|
+
|
|
1
18
|
// src/adapters/ConsoleLogger.ts
|
|
2
19
|
var LEVEL_VALUES = {
|
|
3
20
|
fatal: 60,
|
|
@@ -136,141 +153,29 @@ var InMemoryCache = class {
|
|
|
136
153
|
}
|
|
137
154
|
};
|
|
138
155
|
|
|
139
|
-
// src/types/errors.ts
|
|
140
|
-
var Errors = {
|
|
141
|
-
ValidationError: "ERR_VALIDATION",
|
|
142
|
-
InvariantError: "ERR_INVARIANT",
|
|
143
|
-
ConcurrencyError: "ERR_CONCURRENCY",
|
|
144
|
-
StreamClosedError: "ERR_STREAM_CLOSED"
|
|
145
|
-
};
|
|
146
|
-
var ValidationError = class extends Error {
|
|
147
|
-
constructor(target, payload, details) {
|
|
148
|
-
super(`Invalid ${target} payload`);
|
|
149
|
-
this.target = target;
|
|
150
|
-
this.payload = payload;
|
|
151
|
-
this.details = details;
|
|
152
|
-
this.name = Errors.ValidationError;
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
var InvariantError = class extends Error {
|
|
156
|
-
constructor(action2, payload, target, snapshot, description) {
|
|
157
|
-
super(`${action2} failed invariant: ${description}`);
|
|
158
|
-
this.action = action2;
|
|
159
|
-
this.payload = payload;
|
|
160
|
-
this.target = target;
|
|
161
|
-
this.snapshot = snapshot;
|
|
162
|
-
this.description = description;
|
|
163
|
-
this.name = Errors.InvariantError;
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
var StreamClosedError = class extends Error {
|
|
167
|
-
constructor(stream) {
|
|
168
|
-
super(`Stream "${stream}" is closed (tombstoned)`);
|
|
169
|
-
this.stream = stream;
|
|
170
|
-
this.name = Errors.StreamClosedError;
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
var ConcurrencyError = class extends Error {
|
|
174
|
-
constructor(stream, lastVersion, events, expectedVersion) {
|
|
175
|
-
super(
|
|
176
|
-
`Concurrency error committing "${events.map((e) => `${stream}.${e.name}.${JSON.stringify(e.data)}`).join(
|
|
177
|
-
", "
|
|
178
|
-
)}". Expected version ${expectedVersion} but found version ${lastVersion}.`
|
|
179
|
-
);
|
|
180
|
-
this.stream = stream;
|
|
181
|
-
this.lastVersion = lastVersion;
|
|
182
|
-
this.events = events;
|
|
183
|
-
this.expectedVersion = expectedVersion;
|
|
184
|
-
this.name = Errors.ConcurrencyError;
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
|
|
188
156
|
// src/utils.ts
|
|
189
157
|
import { prettifyError } from "zod";
|
|
190
158
|
|
|
191
159
|
// src/config.ts
|
|
192
160
|
import * as fs from "fs";
|
|
193
|
-
import { z as z2 } from "zod";
|
|
194
|
-
|
|
195
|
-
// src/types/schemas.ts
|
|
196
161
|
import { z } from "zod";
|
|
197
|
-
var
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}).
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
actor: ActorSchema,
|
|
205
|
-
expectedVersion: z.number().optional()
|
|
206
|
-
}).loose().readonly();
|
|
207
|
-
var CausationEventSchema = z.object({
|
|
208
|
-
id: z.number(),
|
|
209
|
-
name: z.string(),
|
|
210
|
-
stream: z.string()
|
|
211
|
-
});
|
|
212
|
-
var EventMetaSchema = z.object({
|
|
213
|
-
correlation: z.string(),
|
|
214
|
-
causation: z.object({
|
|
215
|
-
action: TargetSchema.and(z.object({ name: z.string() })).optional(),
|
|
216
|
-
event: CausationEventSchema.optional()
|
|
217
|
-
})
|
|
218
|
-
}).readonly();
|
|
219
|
-
var CommittedMetaSchema = z.object({
|
|
220
|
-
id: z.number(),
|
|
221
|
-
stream: z.string(),
|
|
222
|
-
version: z.number(),
|
|
223
|
-
created: z.date(),
|
|
224
|
-
meta: EventMetaSchema
|
|
225
|
-
}).readonly();
|
|
226
|
-
var QuerySchema = z.object({
|
|
227
|
-
stream: z.string().optional(),
|
|
228
|
-
names: z.string().array().optional(),
|
|
229
|
-
before: z.number().optional(),
|
|
230
|
-
after: z.number().optional(),
|
|
231
|
-
limit: z.number().optional(),
|
|
232
|
-
created_before: z.date().optional(),
|
|
233
|
-
created_after: z.date().optional(),
|
|
234
|
-
backward: z.boolean().optional(),
|
|
235
|
-
correlation: z.string().optional(),
|
|
236
|
-
with_snaps: z.boolean().optional(),
|
|
237
|
-
stream_exact: z.boolean().optional()
|
|
238
|
-
}).readonly();
|
|
239
|
-
|
|
240
|
-
// src/types/index.ts
|
|
241
|
-
var Environments = [
|
|
242
|
-
"development",
|
|
243
|
-
"test",
|
|
244
|
-
"staging",
|
|
245
|
-
"production"
|
|
246
|
-
];
|
|
247
|
-
var LogLevels = [
|
|
248
|
-
"fatal",
|
|
249
|
-
"error",
|
|
250
|
-
"warn",
|
|
251
|
-
"info",
|
|
252
|
-
"debug",
|
|
253
|
-
"trace"
|
|
254
|
-
];
|
|
255
|
-
|
|
256
|
-
// src/config.ts
|
|
257
|
-
var PackageSchema = z2.object({
|
|
258
|
-
name: z2.string().min(1),
|
|
259
|
-
version: z2.string().min(1),
|
|
260
|
-
description: z2.string().min(1).optional(),
|
|
261
|
-
author: z2.object({ name: z2.string().min(1), email: z2.string().optional() }).optional().or(z2.string().min(1)).optional(),
|
|
262
|
-
license: z2.string().min(1).optional(),
|
|
263
|
-
dependencies: z2.record(z2.string(), z2.string()).optional()
|
|
162
|
+
var PackageSchema = z.object({
|
|
163
|
+
name: z.string().min(1),
|
|
164
|
+
version: z.string().min(1),
|
|
165
|
+
description: z.string().min(1).optional(),
|
|
166
|
+
author: z.object({ name: z.string().min(1), email: z.string().optional() }).optional().or(z.string().min(1)).optional(),
|
|
167
|
+
license: z.string().min(1).optional(),
|
|
168
|
+
dependencies: z.record(z.string(), z.string()).optional()
|
|
264
169
|
});
|
|
265
170
|
var getPackage = () => {
|
|
266
171
|
const pkg2 = fs.readFileSync("package.json");
|
|
267
172
|
return JSON.parse(pkg2.toString());
|
|
268
173
|
};
|
|
269
174
|
var BaseSchema = PackageSchema.extend({
|
|
270
|
-
env:
|
|
271
|
-
logLevel:
|
|
272
|
-
logSingleLine:
|
|
273
|
-
sleepMs:
|
|
175
|
+
env: z.enum(Environments),
|
|
176
|
+
logLevel: z.enum(LogLevels),
|
|
177
|
+
logSingleLine: z.boolean(),
|
|
178
|
+
sleepMs: z.number().int().min(0).max(5e3)
|
|
274
179
|
});
|
|
275
180
|
var { NODE_ENV, LOG_LEVEL, LOG_SINGLE_LINE, SLEEP_MS } = process.env;
|
|
276
181
|
var env = NODE_ENV || "development";
|
|
@@ -743,63 +648,6 @@ function dispose(disposer) {
|
|
|
743
648
|
}
|
|
744
649
|
var SNAP_EVENT = "__snapshot__";
|
|
745
650
|
var TOMBSTONE_EVENT = "__tombstone__";
|
|
746
|
-
function build_tracer(logLevel2) {
|
|
747
|
-
if (logLevel2 === "trace") {
|
|
748
|
-
const logger4 = log();
|
|
749
|
-
return {
|
|
750
|
-
fetched: (fetched) => {
|
|
751
|
-
const data = Object.fromEntries(
|
|
752
|
-
fetched.map(({ stream, source, events }) => {
|
|
753
|
-
const key = source ? `${stream}<-${source}` : stream;
|
|
754
|
-
const value = Object.fromEntries(
|
|
755
|
-
events.map(({ id, stream: stream2, name }) => [id, { [stream2]: name }])
|
|
756
|
-
);
|
|
757
|
-
return [key, value];
|
|
758
|
-
})
|
|
759
|
-
);
|
|
760
|
-
logger4.trace(data, ">> fetch");
|
|
761
|
-
},
|
|
762
|
-
correlated: (streams) => {
|
|
763
|
-
const data = streams.map(({ stream }) => stream).join(" ");
|
|
764
|
-
logger4.trace(`>> correlate ${data}`);
|
|
765
|
-
},
|
|
766
|
-
leased: (leases) => {
|
|
767
|
-
const data = Object.fromEntries(
|
|
768
|
-
leases.map(({ stream, at, retry }) => [stream, { at, retry }])
|
|
769
|
-
);
|
|
770
|
-
logger4.trace(data, ">> lease");
|
|
771
|
-
},
|
|
772
|
-
acked: (leases) => {
|
|
773
|
-
const data = Object.fromEntries(
|
|
774
|
-
leases.map(({ stream, at, retry }) => [stream, { at, retry }])
|
|
775
|
-
);
|
|
776
|
-
logger4.trace(data, ">> ack");
|
|
777
|
-
},
|
|
778
|
-
blocked: (leases) => {
|
|
779
|
-
const data = Object.fromEntries(
|
|
780
|
-
leases.map(({ stream, at, retry, error }) => [
|
|
781
|
-
stream,
|
|
782
|
-
{ at, retry, error }
|
|
783
|
-
])
|
|
784
|
-
);
|
|
785
|
-
logger4.trace(data, ">> block");
|
|
786
|
-
}
|
|
787
|
-
};
|
|
788
|
-
} else {
|
|
789
|
-
return {
|
|
790
|
-
fetched: () => {
|
|
791
|
-
},
|
|
792
|
-
correlated: () => {
|
|
793
|
-
},
|
|
794
|
-
leased: () => {
|
|
795
|
-
},
|
|
796
|
-
acked: () => {
|
|
797
|
-
},
|
|
798
|
-
blocked: () => {
|
|
799
|
-
}
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
651
|
|
|
804
652
|
// src/signals.ts
|
|
805
653
|
var logger = log();
|
|
@@ -824,14 +672,33 @@ process.once("unhandledRejection", async (arg) => {
|
|
|
824
672
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
825
673
|
import EventEmitter from "events";
|
|
826
674
|
|
|
827
|
-
// src/
|
|
675
|
+
// src/internal/drain.ts
|
|
676
|
+
var claim = (lagging, leading, by, millis) => store().claim(lagging, leading, by, millis);
|
|
677
|
+
async function fetch(leased, eventLimit) {
|
|
678
|
+
return Promise.all(
|
|
679
|
+
leased.map(async ({ stream, source, at, lagging }) => {
|
|
680
|
+
const events = [];
|
|
681
|
+
await store().query((e) => events.push(e), {
|
|
682
|
+
stream: source,
|
|
683
|
+
after: at,
|
|
684
|
+
limit: eventLimit
|
|
685
|
+
});
|
|
686
|
+
return { stream, source, at, lagging, events };
|
|
687
|
+
})
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
var ack = (leases) => store().ack(leases);
|
|
691
|
+
var block = (leases) => store().block(leases);
|
|
692
|
+
var subscribe = (streams) => store().subscribe(streams);
|
|
693
|
+
|
|
694
|
+
// src/internal/event-sourcing.ts
|
|
828
695
|
import { patch } from "@rotorsoft/act-patch";
|
|
829
696
|
import { randomUUID } from "crypto";
|
|
830
697
|
var logger2 = log();
|
|
831
698
|
async function snap(snapshot) {
|
|
832
699
|
try {
|
|
833
700
|
const { id, stream, name, meta, version } = snapshot.event;
|
|
834
|
-
|
|
701
|
+
await store().commit(
|
|
835
702
|
stream,
|
|
836
703
|
[{ name: SNAP_EVENT, data: snapshot.state }],
|
|
837
704
|
{
|
|
@@ -841,7 +708,6 @@ async function snap(snapshot) {
|
|
|
841
708
|
version
|
|
842
709
|
// IMPORTANT! - state events are committed right after the snapshot event
|
|
843
710
|
);
|
|
844
|
-
logger2.trace(snapped, "\u{1F7E0} snap");
|
|
845
711
|
} catch (error) {
|
|
846
712
|
logger2.error(error);
|
|
847
713
|
}
|
|
@@ -853,7 +719,7 @@ async function load(me, stream, callback, asOf) {
|
|
|
853
719
|
let patches = cached?.patches ?? 0;
|
|
854
720
|
let snaps = cached?.snaps ?? 0;
|
|
855
721
|
let event;
|
|
856
|
-
|
|
722
|
+
await store().query(
|
|
857
723
|
(e) => {
|
|
858
724
|
event = e;
|
|
859
725
|
if (e.name === SNAP_EVENT) {
|
|
@@ -872,10 +738,6 @@ async function load(me, stream, callback, asOf) {
|
|
|
872
738
|
...cached ? { after: cached.event_id } : { with_snaps: true, ...asOf }
|
|
873
739
|
}
|
|
874
740
|
);
|
|
875
|
-
logger2.trace(
|
|
876
|
-
state2,
|
|
877
|
-
`\u{1F7E2} load ${stream}${cached && count === 0 ? " (cached)" : ""}${timeTravel ? " (as-of)" : ""}`
|
|
878
|
-
);
|
|
879
741
|
return { event, state: state2, patches, snaps };
|
|
880
742
|
}
|
|
881
743
|
async function action(me, action2, target, payload, reactingTo, skipValidation = false) {
|
|
@@ -886,10 +748,6 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
|
|
|
886
748
|
if (snapshot.event?.name === TOMBSTONE_EVENT)
|
|
887
749
|
throw new StreamClosedError(stream);
|
|
888
750
|
const expected = expectedVersion ?? snapshot.event?.version;
|
|
889
|
-
logger2.trace(
|
|
890
|
-
payload,
|
|
891
|
-
`\u{1F535} ${stream}.${action2}${typeof expected === "number" ? `.${expected}` : ""}`
|
|
892
|
-
);
|
|
893
751
|
if (me.given) {
|
|
894
752
|
const invariants = me.given[action2] || [];
|
|
895
753
|
invariants.forEach(({ valid, description }) => {
|
|
@@ -929,10 +787,6 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
|
|
|
929
787
|
} : void 0
|
|
930
788
|
}
|
|
931
789
|
};
|
|
932
|
-
logger2.trace(
|
|
933
|
-
emitted.map((e) => e.data),
|
|
934
|
-
`\u{1F534} commit ${stream}.${emitted.map((e) => e.name).join(", ")}`
|
|
935
|
-
);
|
|
936
790
|
let committed;
|
|
937
791
|
try {
|
|
938
792
|
committed = await store().commit(
|
|
@@ -968,14 +822,257 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
|
|
|
968
822
|
return snapshots;
|
|
969
823
|
}
|
|
970
824
|
|
|
971
|
-
// src/
|
|
825
|
+
// src/internal/merge.ts
|
|
826
|
+
import { ZodObject } from "zod";
|
|
827
|
+
function baseTypeName(zodType) {
|
|
828
|
+
let t = zodType;
|
|
829
|
+
while (typeof t.unwrap === "function") {
|
|
830
|
+
t = t.unwrap();
|
|
831
|
+
}
|
|
832
|
+
return t.constructor.name;
|
|
833
|
+
}
|
|
834
|
+
function mergeSchemas(existing, incoming, stateName) {
|
|
835
|
+
if (existing instanceof ZodObject && incoming instanceof ZodObject) {
|
|
836
|
+
const existingShape = existing.shape;
|
|
837
|
+
const incomingShape = incoming.shape;
|
|
838
|
+
for (const key of Object.keys(incomingShape)) {
|
|
839
|
+
if (key in existingShape) {
|
|
840
|
+
const existingBase = baseTypeName(existingShape[key]);
|
|
841
|
+
const incomingBase = baseTypeName(incomingShape[key]);
|
|
842
|
+
if (existingBase !== incomingBase) {
|
|
843
|
+
throw new Error(
|
|
844
|
+
`Schema conflict in "${stateName}": key "${key}" has type "${existingBase}" but incoming partial declares "${incomingBase}"`
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
return existing.extend(incomingShape);
|
|
850
|
+
}
|
|
851
|
+
return existing;
|
|
852
|
+
}
|
|
853
|
+
function mergeInits(existing, incoming) {
|
|
854
|
+
return () => ({ ...existing(), ...incoming() });
|
|
855
|
+
}
|
|
856
|
+
function registerState(state2, states, actions, events) {
|
|
857
|
+
if (states.has(state2.name)) {
|
|
858
|
+
const existing = states.get(state2.name);
|
|
859
|
+
for (const name of Object.keys(state2.actions)) {
|
|
860
|
+
if (existing.actions[name] === state2.actions[name]) continue;
|
|
861
|
+
if (actions[name]) throw new Error(`Duplicate action "${name}"`);
|
|
862
|
+
}
|
|
863
|
+
for (const name of Object.keys(state2.events)) {
|
|
864
|
+
if (existing.events[name] === state2.events[name]) continue;
|
|
865
|
+
if (existing.events[name]) continue;
|
|
866
|
+
if (events[name]) throw new Error(`Duplicate event "${name}"`);
|
|
867
|
+
}
|
|
868
|
+
const mergedPatch = { ...existing.patch };
|
|
869
|
+
for (const name of Object.keys(state2.patch)) {
|
|
870
|
+
const existingP = existing.patch[name];
|
|
871
|
+
const incomingP = state2.patch[name];
|
|
872
|
+
if (!existingP) {
|
|
873
|
+
mergedPatch[name] = incomingP;
|
|
874
|
+
} else {
|
|
875
|
+
const existingIsDefault = existingP._passthrough;
|
|
876
|
+
const incomingIsDefault = incomingP._passthrough;
|
|
877
|
+
if (!existingIsDefault && !incomingIsDefault && existingP !== incomingP) {
|
|
878
|
+
throw new Error(
|
|
879
|
+
`Duplicate custom patch for event "${name}" in state "${state2.name}"`
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
if (existingIsDefault && !incomingIsDefault) {
|
|
883
|
+
mergedPatch[name] = incomingP;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
const merged = {
|
|
888
|
+
...existing,
|
|
889
|
+
state: mergeSchemas(existing.state, state2.state, state2.name),
|
|
890
|
+
init: mergeInits(existing.init, state2.init),
|
|
891
|
+
events: { ...existing.events, ...state2.events },
|
|
892
|
+
actions: { ...existing.actions, ...state2.actions },
|
|
893
|
+
patch: mergedPatch,
|
|
894
|
+
on: { ...existing.on, ...state2.on },
|
|
895
|
+
given: { ...existing.given, ...state2.given },
|
|
896
|
+
snap: state2.snap && existing.snap && state2.snap !== existing.snap ? (() => {
|
|
897
|
+
throw new Error(
|
|
898
|
+
`Duplicate snap strategy for state "${state2.name}"`
|
|
899
|
+
);
|
|
900
|
+
})() : state2.snap || existing.snap
|
|
901
|
+
};
|
|
902
|
+
states.set(state2.name, merged);
|
|
903
|
+
for (const name of Object.keys(merged.actions)) {
|
|
904
|
+
actions[name] = merged;
|
|
905
|
+
}
|
|
906
|
+
for (const name of Object.keys(state2.events)) {
|
|
907
|
+
if (events[name]) continue;
|
|
908
|
+
events[name] = {
|
|
909
|
+
schema: state2.events[name],
|
|
910
|
+
reactions: /* @__PURE__ */ new Map()
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
} else {
|
|
914
|
+
states.set(state2.name, state2);
|
|
915
|
+
for (const name of Object.keys(state2.actions)) {
|
|
916
|
+
if (actions[name]) throw new Error(`Duplicate action "${name}"`);
|
|
917
|
+
actions[name] = state2;
|
|
918
|
+
}
|
|
919
|
+
for (const name of Object.keys(state2.events)) {
|
|
920
|
+
if (events[name]) throw new Error(`Duplicate event "${name}"`);
|
|
921
|
+
events[name] = {
|
|
922
|
+
schema: state2.events[name],
|
|
923
|
+
reactions: /* @__PURE__ */ new Map()
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
function mergeProjection(proj, events) {
|
|
929
|
+
for (const eventName of Object.keys(proj.events)) {
|
|
930
|
+
const projRegister = proj.events[eventName];
|
|
931
|
+
const existing = events[eventName];
|
|
932
|
+
if (!existing) {
|
|
933
|
+
events[eventName] = {
|
|
934
|
+
schema: projRegister.schema,
|
|
935
|
+
reactions: new Map(projRegister.reactions)
|
|
936
|
+
};
|
|
937
|
+
} else {
|
|
938
|
+
for (const [name, reaction] of projRegister.reactions) {
|
|
939
|
+
let key = name;
|
|
940
|
+
while (existing.reactions.has(key)) key = `${key}_p`;
|
|
941
|
+
existing.reactions.set(key, reaction);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
var _this_ = ({ stream }) => ({
|
|
947
|
+
source: stream,
|
|
948
|
+
target: stream
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
// src/internal/tracing.ts
|
|
972
952
|
var logger3 = log();
|
|
973
|
-
var
|
|
953
|
+
var withSnapTrace = (inner) => async (snapshot) => {
|
|
954
|
+
logger3.trace(
|
|
955
|
+
`\u{1F7E0} snap ${snapshot.event.stream}@${snapshot.event.version}`
|
|
956
|
+
);
|
|
957
|
+
return inner(snapshot);
|
|
958
|
+
};
|
|
959
|
+
var withLoadTrace = (inner) => async (me, stream, callback, asOf) => {
|
|
960
|
+
logger3.trace(`\u{1F7E2} load ${stream}${asOf ? " (as-of)" : ""}`);
|
|
961
|
+
return inner(me, stream, callback, asOf);
|
|
962
|
+
};
|
|
963
|
+
var withActionTrace = (inner) => async (me, action2, target, payload, reactingTo, skipValidation) => {
|
|
964
|
+
logger3.trace(payload, `\u{1F535} ${target.stream}.${action2}`);
|
|
965
|
+
const snapshots = await inner(
|
|
966
|
+
me,
|
|
967
|
+
action2,
|
|
968
|
+
target,
|
|
969
|
+
payload,
|
|
970
|
+
reactingTo,
|
|
971
|
+
skipValidation
|
|
972
|
+
);
|
|
973
|
+
const committed = snapshots.filter((s) => s.event);
|
|
974
|
+
if (committed.length) {
|
|
975
|
+
logger3.trace(
|
|
976
|
+
committed.map((s) => s.event.data),
|
|
977
|
+
`\u{1F534} commit ${target.stream}.${committed.map((s) => s.event.name).join(", ")}`
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
return snapshots;
|
|
981
|
+
};
|
|
982
|
+
function buildEs(level) {
|
|
983
|
+
if (level !== "trace") {
|
|
984
|
+
return { snap, load, action };
|
|
985
|
+
}
|
|
986
|
+
return {
|
|
987
|
+
snap: withSnapTrace(snap),
|
|
988
|
+
load: withLoadTrace(load),
|
|
989
|
+
action: withActionTrace(action)
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
var withClaimTrace = (inner) => async (lagging, leading, by, millis) => {
|
|
993
|
+
const leased = await inner(lagging, leading, by, millis);
|
|
994
|
+
if (leased.length) {
|
|
995
|
+
const data = Object.fromEntries(
|
|
996
|
+
leased.map(({ stream, at, retry }) => [stream, { at, retry }])
|
|
997
|
+
);
|
|
998
|
+
logger3.trace(data, ">> lease");
|
|
999
|
+
}
|
|
1000
|
+
return leased;
|
|
1001
|
+
};
|
|
1002
|
+
var withFetchTrace = (inner) => async (leased, eventLimit) => {
|
|
1003
|
+
const fetched = await inner(leased, eventLimit);
|
|
1004
|
+
const data = Object.fromEntries(
|
|
1005
|
+
fetched.map(({ stream, source, events }) => {
|
|
1006
|
+
const key = source ? `${stream}<-${source}` : stream;
|
|
1007
|
+
const value = Object.fromEntries(
|
|
1008
|
+
events.map(({ id, stream: stream2, name }) => [id, { [stream2]: name }])
|
|
1009
|
+
);
|
|
1010
|
+
return [key, value];
|
|
1011
|
+
})
|
|
1012
|
+
);
|
|
1013
|
+
logger3.trace(data, ">> fetch");
|
|
1014
|
+
return fetched;
|
|
1015
|
+
};
|
|
1016
|
+
var withAckTrace = (inner) => async (leases) => {
|
|
1017
|
+
const acked = await inner(leases);
|
|
1018
|
+
if (acked.length) {
|
|
1019
|
+
const data = Object.fromEntries(
|
|
1020
|
+
acked.map(({ stream, at, retry }) => [stream, { at, retry }])
|
|
1021
|
+
);
|
|
1022
|
+
logger3.trace(data, ">> ack");
|
|
1023
|
+
}
|
|
1024
|
+
return acked;
|
|
1025
|
+
};
|
|
1026
|
+
var withBlockTrace = (inner) => async (leases) => {
|
|
1027
|
+
const blocked = await inner(leases);
|
|
1028
|
+
if (blocked.length) {
|
|
1029
|
+
const data = Object.fromEntries(
|
|
1030
|
+
blocked.map(({ stream, at, retry, error }) => [
|
|
1031
|
+
stream,
|
|
1032
|
+
{ at, retry, error }
|
|
1033
|
+
])
|
|
1034
|
+
);
|
|
1035
|
+
logger3.trace(data, ">> block");
|
|
1036
|
+
}
|
|
1037
|
+
return blocked;
|
|
1038
|
+
};
|
|
1039
|
+
var withSubscribeTrace = (inner) => async (streams) => {
|
|
1040
|
+
const result = await inner(streams);
|
|
1041
|
+
if (result.subscribed) {
|
|
1042
|
+
const data = streams.map(({ stream }) => stream).join(" ");
|
|
1043
|
+
logger3.trace(`>> correlate ${data}`);
|
|
1044
|
+
}
|
|
1045
|
+
return result;
|
|
1046
|
+
};
|
|
1047
|
+
function buildDrain(level) {
|
|
1048
|
+
if (level !== "trace") {
|
|
1049
|
+
return {
|
|
1050
|
+
claim,
|
|
1051
|
+
fetch,
|
|
1052
|
+
ack,
|
|
1053
|
+
block,
|
|
1054
|
+
subscribe
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
return {
|
|
1058
|
+
claim: withClaimTrace(claim),
|
|
1059
|
+
fetch: withFetchTrace(fetch),
|
|
1060
|
+
ack: withAckTrace(ack),
|
|
1061
|
+
block: withBlockTrace(block),
|
|
1062
|
+
subscribe: withSubscribeTrace(subscribe)
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
// src/act.ts
|
|
1067
|
+
var logger4 = log();
|
|
974
1068
|
var Act = class {
|
|
975
1069
|
constructor(registry, _states = /* @__PURE__ */ new Map(), batchHandlers = /* @__PURE__ */ new Map()) {
|
|
976
1070
|
this.registry = registry;
|
|
977
1071
|
this._states = _states;
|
|
978
1072
|
this._batch_handlers = batchHandlers;
|
|
1073
|
+
const level = log().level;
|
|
1074
|
+
this._es = buildEs(level);
|
|
1075
|
+
this._cd = buildDrain(level);
|
|
979
1076
|
const statics = [];
|
|
980
1077
|
for (const [name, register] of Object.entries(this.registry.events)) {
|
|
981
1078
|
if (register.reactions.size > 0) {
|
|
@@ -1035,6 +1132,10 @@ var Act = class {
|
|
|
1035
1132
|
_static_targets;
|
|
1036
1133
|
/** Batch handlers for static-target projections (target → handler) */
|
|
1037
1134
|
_batch_handlers;
|
|
1135
|
+
/** Event-sourcing handlers, optionally wrapped with trace decorators */
|
|
1136
|
+
_es;
|
|
1137
|
+
/** Correlate/drain pipeline ops, optionally wrapped with trace decorators */
|
|
1138
|
+
_cd;
|
|
1038
1139
|
/**
|
|
1039
1140
|
* Executes an action on a state instance, committing resulting events.
|
|
1040
1141
|
*
|
|
@@ -1117,7 +1218,7 @@ var Act = class {
|
|
|
1117
1218
|
* @see {@link ValidationError}, {@link InvariantError}, {@link ConcurrencyError}
|
|
1118
1219
|
*/
|
|
1119
1220
|
async do(action2, target, payload, reactingTo, skipValidation = false) {
|
|
1120
|
-
const snapshots = await action(
|
|
1221
|
+
const snapshots = await this._es.action(
|
|
1121
1222
|
this.registry.actions[action2],
|
|
1122
1223
|
action2,
|
|
1123
1224
|
target,
|
|
@@ -1143,7 +1244,7 @@ var Act = class {
|
|
|
1143
1244
|
} else {
|
|
1144
1245
|
merged = this._states.get(stateOrName.name) || stateOrName;
|
|
1145
1246
|
}
|
|
1146
|
-
return await load(merged, stream, callback, asOf);
|
|
1247
|
+
return await this._es.load(merged, stream, callback, asOf);
|
|
1147
1248
|
}
|
|
1148
1249
|
/**
|
|
1149
1250
|
* Queries the event store for events matching a filter.
|
|
@@ -1256,7 +1357,7 @@ var Act = class {
|
|
|
1256
1357
|
if (payloads.length === 0) return { lease, handled: 0, at: lease.at };
|
|
1257
1358
|
const stream = lease.stream;
|
|
1258
1359
|
let at = payloads.at(0).event.id, handled = 0;
|
|
1259
|
-
lease.retry > 0 &&
|
|
1360
|
+
lease.retry > 0 && logger4.warn(`Retrying ${stream}@${at} (${lease.retry}).`);
|
|
1260
1361
|
const doAction = this.do.bind(this);
|
|
1261
1362
|
const scopedApp = {
|
|
1262
1363
|
do: doAction,
|
|
@@ -1278,16 +1379,16 @@ var Act = class {
|
|
|
1278
1379
|
at = event.id;
|
|
1279
1380
|
handled++;
|
|
1280
1381
|
} catch (error) {
|
|
1281
|
-
|
|
1282
|
-
const
|
|
1283
|
-
|
|
1382
|
+
logger4.error(error);
|
|
1383
|
+
const block2 = lease.retry >= options.maxRetries && options.blockOnError;
|
|
1384
|
+
block2 && logger4.error(`Blocking ${stream} after ${lease.retry} retries.`);
|
|
1284
1385
|
return {
|
|
1285
1386
|
lease,
|
|
1286
1387
|
handled,
|
|
1287
1388
|
at,
|
|
1288
1389
|
// only report error when nothing was handled
|
|
1289
1390
|
error: handled === 0 ? error.message : void 0,
|
|
1290
|
-
block
|
|
1391
|
+
block: block2
|
|
1291
1392
|
};
|
|
1292
1393
|
}
|
|
1293
1394
|
}
|
|
@@ -1310,21 +1411,21 @@ var Act = class {
|
|
|
1310
1411
|
const stream = lease.stream;
|
|
1311
1412
|
const events = payloads.map((p) => p.event);
|
|
1312
1413
|
const at = events.at(-1).id;
|
|
1313
|
-
lease.retry > 0 &&
|
|
1414
|
+
lease.retry > 0 && logger4.warn(`Retrying batch ${stream}@${events[0].id} (${lease.retry}).`);
|
|
1314
1415
|
try {
|
|
1315
1416
|
await batchHandler(events, stream);
|
|
1316
1417
|
return { lease, handled: events.length, at };
|
|
1317
1418
|
} catch (error) {
|
|
1318
|
-
|
|
1419
|
+
logger4.error(error);
|
|
1319
1420
|
const { options } = payloads[0];
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1421
|
+
const block2 = lease.retry >= options.maxRetries && options.blockOnError;
|
|
1422
|
+
block2 && logger4.error(`Blocking ${stream} after ${lease.retry} retries.`);
|
|
1322
1423
|
return {
|
|
1323
1424
|
lease,
|
|
1324
1425
|
handled: 0,
|
|
1325
1426
|
at: lease.at,
|
|
1326
1427
|
error: error.message,
|
|
1327
|
-
block
|
|
1428
|
+
block: block2
|
|
1328
1429
|
};
|
|
1329
1430
|
}
|
|
1330
1431
|
}
|
|
@@ -1380,7 +1481,7 @@ var Act = class {
|
|
|
1380
1481
|
this._drain_locked = true;
|
|
1381
1482
|
const lagging = Math.ceil(streamLimit * this._drain_lag2lead_ratio);
|
|
1382
1483
|
const leading = streamLimit - lagging;
|
|
1383
|
-
const leased = await
|
|
1484
|
+
const leased = await this._cd.claim(
|
|
1384
1485
|
lagging,
|
|
1385
1486
|
leading,
|
|
1386
1487
|
randomUUID2(),
|
|
@@ -1390,17 +1491,7 @@ var Act = class {
|
|
|
1390
1491
|
this._needs_drain = false;
|
|
1391
1492
|
return { fetched: [], leased: [], acked: [], blocked: [] };
|
|
1392
1493
|
}
|
|
1393
|
-
const fetched = await
|
|
1394
|
-
leased.map(async ({ stream, source, at, lagging: lagging2 }) => {
|
|
1395
|
-
const events = await this.query_array({
|
|
1396
|
-
stream: source,
|
|
1397
|
-
after: at,
|
|
1398
|
-
limit: eventLimit
|
|
1399
|
-
});
|
|
1400
|
-
return { stream, source, at, lagging: lagging2, events };
|
|
1401
|
-
})
|
|
1402
|
-
);
|
|
1403
|
-
tracer.fetched(fetched);
|
|
1494
|
+
const fetched = await this._cd.fetch(leased, eventLimit);
|
|
1404
1495
|
const payloadsMap = /* @__PURE__ */ new Map();
|
|
1405
1496
|
const fetch_window_at = fetched.reduce(
|
|
1406
1497
|
(max, { at, events }) => Math.max(max, events.at(-1)?.id || at),
|
|
@@ -1417,7 +1508,6 @@ var Act = class {
|
|
|
1417
1508
|
});
|
|
1418
1509
|
payloadsMap.set(stream, payloads);
|
|
1419
1510
|
});
|
|
1420
|
-
tracer.leased(leased);
|
|
1421
1511
|
const handled = await Promise.all(
|
|
1422
1512
|
leased.map((lease) => {
|
|
1423
1513
|
const streamFetch = fetched.find((f) => f.stream === lease.stream);
|
|
@@ -1441,27 +1531,21 @@ var Act = class {
|
|
|
1441
1531
|
const leading_avg = leading > 0 ? leading_handled / leading : 0;
|
|
1442
1532
|
const total = lagging_avg + leading_avg;
|
|
1443
1533
|
this._drain_lag2lead_ratio = total > 0 ? Math.max(0.2, Math.min(0.8, lagging_avg / total)) : 0.5;
|
|
1444
|
-
const acked = await
|
|
1534
|
+
const acked = await this._cd.ack(
|
|
1445
1535
|
handled.filter(({ error }) => !error).map(({ at, lease }) => ({ ...lease, at }))
|
|
1446
1536
|
);
|
|
1447
|
-
if (acked.length)
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
}
|
|
1451
|
-
const blocked = await store().block(
|
|
1452
|
-
handled.filter(({ block }) => block).map(({ lease, error }) => ({ ...lease, error }))
|
|
1537
|
+
if (acked.length) this.emit("acked", acked);
|
|
1538
|
+
const blocked = await this._cd.block(
|
|
1539
|
+
handled.filter(({ block: block2 }) => block2).map(({ lease, error }) => ({ ...lease, error }))
|
|
1453
1540
|
);
|
|
1454
|
-
if (blocked.length)
|
|
1455
|
-
tracer.blocked(blocked);
|
|
1456
|
-
this.emit("blocked", blocked);
|
|
1457
|
-
}
|
|
1541
|
+
if (blocked.length) this.emit("blocked", blocked);
|
|
1458
1542
|
const result = { fetched, leased, acked, blocked };
|
|
1459
1543
|
const hasErrors = handled.some(({ error }) => error);
|
|
1460
1544
|
if (!acked.length && !blocked.length && !hasErrors)
|
|
1461
1545
|
this._needs_drain = false;
|
|
1462
1546
|
return result;
|
|
1463
1547
|
} catch (error) {
|
|
1464
|
-
|
|
1548
|
+
logger4.error(error);
|
|
1465
1549
|
} finally {
|
|
1466
1550
|
this._drain_locked = false;
|
|
1467
1551
|
}
|
|
@@ -1567,10 +1651,9 @@ var Act = class {
|
|
|
1567
1651
|
stream,
|
|
1568
1652
|
source
|
|
1569
1653
|
}));
|
|
1570
|
-
const { subscribed } = await
|
|
1654
|
+
const { subscribed } = await this._cd.subscribe(streams);
|
|
1571
1655
|
this._correlation_checkpoint = last_id;
|
|
1572
1656
|
if (subscribed) {
|
|
1573
|
-
tracer.correlated(streams);
|
|
1574
1657
|
for (const { stream } of streams) {
|
|
1575
1658
|
this._subscribed_statics.add(stream);
|
|
1576
1659
|
}
|
|
@@ -1835,7 +1918,7 @@ var Act = class {
|
|
|
1835
1918
|
if (mergedState) {
|
|
1836
1919
|
await Promise.all(
|
|
1837
1920
|
guarded.filter((s) => targetMap.get(s)?.restart).map(async (stream) => {
|
|
1838
|
-
const snap2 = await load(mergedState, stream);
|
|
1921
|
+
const snap2 = await this._es.load(mergedState, stream);
|
|
1839
1922
|
seedStates.set(stream, snap2.state);
|
|
1840
1923
|
})
|
|
1841
1924
|
);
|
|
@@ -1942,139 +2025,13 @@ var Act = class {
|
|
|
1942
2025
|
if (!made_progress) break;
|
|
1943
2026
|
}
|
|
1944
2027
|
if (lastDrain) this.emit("settled", lastDrain);
|
|
1945
|
-
})().catch((err) =>
|
|
2028
|
+
})().catch((err) => logger4.error(err)).finally(() => {
|
|
1946
2029
|
this._settling = false;
|
|
1947
2030
|
});
|
|
1948
2031
|
}, debounceMs);
|
|
1949
2032
|
}
|
|
1950
2033
|
};
|
|
1951
2034
|
|
|
1952
|
-
// src/merge.ts
|
|
1953
|
-
import { ZodObject as ZodObject2 } from "zod";
|
|
1954
|
-
function baseTypeName(zodType) {
|
|
1955
|
-
let t = zodType;
|
|
1956
|
-
while (typeof t.unwrap === "function") {
|
|
1957
|
-
t = t.unwrap();
|
|
1958
|
-
}
|
|
1959
|
-
return t.constructor.name;
|
|
1960
|
-
}
|
|
1961
|
-
function mergeSchemas(existing, incoming, stateName) {
|
|
1962
|
-
if (existing instanceof ZodObject2 && incoming instanceof ZodObject2) {
|
|
1963
|
-
const existingShape = existing.shape;
|
|
1964
|
-
const incomingShape = incoming.shape;
|
|
1965
|
-
for (const key of Object.keys(incomingShape)) {
|
|
1966
|
-
if (key in existingShape) {
|
|
1967
|
-
const existingBase = baseTypeName(existingShape[key]);
|
|
1968
|
-
const incomingBase = baseTypeName(incomingShape[key]);
|
|
1969
|
-
if (existingBase !== incomingBase) {
|
|
1970
|
-
throw new Error(
|
|
1971
|
-
`Schema conflict in "${stateName}": key "${key}" has type "${existingBase}" but incoming partial declares "${incomingBase}"`
|
|
1972
|
-
);
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
return existing.extend(incomingShape);
|
|
1977
|
-
}
|
|
1978
|
-
return existing;
|
|
1979
|
-
}
|
|
1980
|
-
function mergeInits(existing, incoming) {
|
|
1981
|
-
return () => ({ ...existing(), ...incoming() });
|
|
1982
|
-
}
|
|
1983
|
-
function registerState(state2, states, actions, events) {
|
|
1984
|
-
if (states.has(state2.name)) {
|
|
1985
|
-
const existing = states.get(state2.name);
|
|
1986
|
-
for (const name of Object.keys(state2.actions)) {
|
|
1987
|
-
if (existing.actions[name] === state2.actions[name]) continue;
|
|
1988
|
-
if (actions[name]) throw new Error(`Duplicate action "${name}"`);
|
|
1989
|
-
}
|
|
1990
|
-
for (const name of Object.keys(state2.events)) {
|
|
1991
|
-
if (existing.events[name] === state2.events[name]) continue;
|
|
1992
|
-
if (existing.events[name]) continue;
|
|
1993
|
-
if (events[name]) throw new Error(`Duplicate event "${name}"`);
|
|
1994
|
-
}
|
|
1995
|
-
const mergedPatch = { ...existing.patch };
|
|
1996
|
-
for (const name of Object.keys(state2.patch)) {
|
|
1997
|
-
const existingP = existing.patch[name];
|
|
1998
|
-
const incomingP = state2.patch[name];
|
|
1999
|
-
if (!existingP) {
|
|
2000
|
-
mergedPatch[name] = incomingP;
|
|
2001
|
-
} else {
|
|
2002
|
-
const existingIsDefault = existingP._passthrough;
|
|
2003
|
-
const incomingIsDefault = incomingP._passthrough;
|
|
2004
|
-
if (!existingIsDefault && !incomingIsDefault && existingP !== incomingP) {
|
|
2005
|
-
throw new Error(
|
|
2006
|
-
`Duplicate custom patch for event "${name}" in state "${state2.name}"`
|
|
2007
|
-
);
|
|
2008
|
-
}
|
|
2009
|
-
if (existingIsDefault && !incomingIsDefault) {
|
|
2010
|
-
mergedPatch[name] = incomingP;
|
|
2011
|
-
}
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
const merged = {
|
|
2015
|
-
...existing,
|
|
2016
|
-
state: mergeSchemas(existing.state, state2.state, state2.name),
|
|
2017
|
-
init: mergeInits(existing.init, state2.init),
|
|
2018
|
-
events: { ...existing.events, ...state2.events },
|
|
2019
|
-
actions: { ...existing.actions, ...state2.actions },
|
|
2020
|
-
patch: mergedPatch,
|
|
2021
|
-
on: { ...existing.on, ...state2.on },
|
|
2022
|
-
given: { ...existing.given, ...state2.given },
|
|
2023
|
-
snap: state2.snap && existing.snap && state2.snap !== existing.snap ? (() => {
|
|
2024
|
-
throw new Error(
|
|
2025
|
-
`Duplicate snap strategy for state "${state2.name}"`
|
|
2026
|
-
);
|
|
2027
|
-
})() : state2.snap || existing.snap
|
|
2028
|
-
};
|
|
2029
|
-
states.set(state2.name, merged);
|
|
2030
|
-
for (const name of Object.keys(merged.actions)) {
|
|
2031
|
-
actions[name] = merged;
|
|
2032
|
-
}
|
|
2033
|
-
for (const name of Object.keys(state2.events)) {
|
|
2034
|
-
if (events[name]) continue;
|
|
2035
|
-
events[name] = {
|
|
2036
|
-
schema: state2.events[name],
|
|
2037
|
-
reactions: /* @__PURE__ */ new Map()
|
|
2038
|
-
};
|
|
2039
|
-
}
|
|
2040
|
-
} else {
|
|
2041
|
-
states.set(state2.name, state2);
|
|
2042
|
-
for (const name of Object.keys(state2.actions)) {
|
|
2043
|
-
if (actions[name]) throw new Error(`Duplicate action "${name}"`);
|
|
2044
|
-
actions[name] = state2;
|
|
2045
|
-
}
|
|
2046
|
-
for (const name of Object.keys(state2.events)) {
|
|
2047
|
-
if (events[name]) throw new Error(`Duplicate event "${name}"`);
|
|
2048
|
-
events[name] = {
|
|
2049
|
-
schema: state2.events[name],
|
|
2050
|
-
reactions: /* @__PURE__ */ new Map()
|
|
2051
|
-
};
|
|
2052
|
-
}
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
function mergeProjection(proj, events) {
|
|
2056
|
-
for (const eventName of Object.keys(proj.events)) {
|
|
2057
|
-
const projRegister = proj.events[eventName];
|
|
2058
|
-
const existing = events[eventName];
|
|
2059
|
-
if (!existing) {
|
|
2060
|
-
events[eventName] = {
|
|
2061
|
-
schema: projRegister.schema,
|
|
2062
|
-
reactions: new Map(projRegister.reactions)
|
|
2063
|
-
};
|
|
2064
|
-
} else {
|
|
2065
|
-
for (const [name, reaction] of projRegister.reactions) {
|
|
2066
|
-
let key = name;
|
|
2067
|
-
while (existing.reactions.has(key)) key = `${key}_p`;
|
|
2068
|
-
existing.reactions.set(key, reaction);
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
var _this_ = ({ stream }) => ({
|
|
2074
|
-
source: stream,
|
|
2075
|
-
target: stream
|
|
2076
|
-
});
|
|
2077
|
-
|
|
2078
2035
|
// src/act-builder.ts
|
|
2079
2036
|
function act(states = /* @__PURE__ */ new Map(), registry = {
|
|
2080
2037
|
actions: {},
|
|
@@ -2417,7 +2374,6 @@ export {
|
|
|
2417
2374
|
ValidationError,
|
|
2418
2375
|
ZodEmpty,
|
|
2419
2376
|
act,
|
|
2420
|
-
build_tracer,
|
|
2421
2377
|
cache,
|
|
2422
2378
|
config,
|
|
2423
2379
|
dispose,
|