@rotorsoft/act 0.8.0 → 0.9.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/index.js CHANGED
@@ -564,9 +564,6 @@ process.once("unhandledRejection", async (arg) => {
564
564
  await disposeAndExit("ERROR");
565
565
  });
566
566
 
567
- // src/act-builder.ts
568
- import { ZodObject as ZodObject2 } from "zod";
569
-
570
567
  // src/act.ts
571
568
  import { randomUUID as randomUUID2 } from "crypto";
572
569
  import EventEmitter from "events";
@@ -807,7 +804,6 @@ var Act = class {
807
804
  action2,
808
805
  target,
809
806
  payload,
810
- // @ts-expect-error type lost
811
807
  reactingTo,
812
808
  skipValidation
813
809
  );
@@ -935,7 +931,7 @@ var Act = class {
935
931
  for (const payload of payloads) {
936
932
  const { event, handler, options } = payload;
937
933
  try {
938
- await handler(event, stream);
934
+ await handler(event, stream, this);
939
935
  at = event.id;
940
936
  handled++;
941
937
  } catch (error) {
@@ -1064,7 +1060,6 @@ var Act = class {
1064
1060
  retry: 0,
1065
1061
  lagging: lagging2
1066
1062
  },
1067
- // @ts-expect-error indexed by key
1068
1063
  payloads
1069
1064
  });
1070
1065
  });
@@ -1281,7 +1276,8 @@ var Act = class {
1281
1276
  }
1282
1277
  };
1283
1278
 
1284
- // src/act-builder.ts
1279
+ // src/merge.ts
1280
+ import { ZodObject as ZodObject2 } from "zod";
1285
1281
  function baseTypeName(zodType) {
1286
1282
  let t = zodType;
1287
1283
  while (typeof t.unwrap === "function") {
@@ -1311,80 +1307,133 @@ function mergeSchemas(existing, incoming, stateName) {
1311
1307
  function mergeInits(existing, incoming) {
1312
1308
  return () => ({ ...existing(), ...incoming() });
1313
1309
  }
1310
+ function registerState(state2, states, actions, events) {
1311
+ if (states.has(state2.name)) {
1312
+ const existing = states.get(state2.name);
1313
+ for (const name of Object.keys(state2.actions)) {
1314
+ if (existing.actions[name] === state2.actions[name]) continue;
1315
+ if (actions[name]) throw new Error(`Duplicate action "${name}"`);
1316
+ }
1317
+ for (const name of Object.keys(state2.events)) {
1318
+ if (existing.events[name] === state2.events[name]) continue;
1319
+ if (events[name]) throw new Error(`Duplicate event "${name}"`);
1320
+ }
1321
+ const merged = {
1322
+ ...existing,
1323
+ state: mergeSchemas(existing.state, state2.state, state2.name),
1324
+ init: mergeInits(existing.init, state2.init),
1325
+ events: { ...existing.events, ...state2.events },
1326
+ actions: { ...existing.actions, ...state2.actions },
1327
+ patch: { ...existing.patch, ...state2.patch },
1328
+ on: { ...existing.on, ...state2.on },
1329
+ given: { ...existing.given, ...state2.given },
1330
+ snap: state2.snap || existing.snap
1331
+ };
1332
+ states.set(state2.name, merged);
1333
+ for (const name of Object.keys(merged.actions)) {
1334
+ actions[name] = merged;
1335
+ }
1336
+ for (const name of Object.keys(state2.events)) {
1337
+ if (events[name]) continue;
1338
+ events[name] = {
1339
+ schema: state2.events[name],
1340
+ reactions: /* @__PURE__ */ new Map()
1341
+ };
1342
+ }
1343
+ } else {
1344
+ states.set(state2.name, state2);
1345
+ for (const name of Object.keys(state2.actions)) {
1346
+ if (actions[name]) throw new Error(`Duplicate action "${name}"`);
1347
+ actions[name] = state2;
1348
+ }
1349
+ for (const name of Object.keys(state2.events)) {
1350
+ if (events[name]) throw new Error(`Duplicate event "${name}"`);
1351
+ events[name] = {
1352
+ schema: state2.events[name],
1353
+ reactions: /* @__PURE__ */ new Map()
1354
+ };
1355
+ }
1356
+ }
1357
+ }
1314
1358
  var _this_ = ({ stream }) => ({
1315
1359
  source: stream,
1316
1360
  target: stream
1317
1361
  });
1318
1362
  var _void_ = () => void 0;
1363
+
1364
+ // src/slice-builder.ts
1365
+ function isSlice(x) {
1366
+ return x != null && x._tag === "Slice";
1367
+ }
1368
+ function slice(states = /* @__PURE__ */ new Map(), actions = {}, events = {}) {
1369
+ const builder = {
1370
+ with: (state2) => {
1371
+ registerState(state2, states, actions, events);
1372
+ return slice(states, actions, events);
1373
+ },
1374
+ on: (event) => ({
1375
+ do: (handler, options) => {
1376
+ const reaction = {
1377
+ handler,
1378
+ resolver: _this_,
1379
+ options: {
1380
+ blockOnError: options?.blockOnError ?? true,
1381
+ maxRetries: options?.maxRetries ?? 3
1382
+ }
1383
+ };
1384
+ const name = handler.name || `${String(event)}_${events[event].reactions.size}`;
1385
+ events[event].reactions.set(name, reaction);
1386
+ return {
1387
+ ...builder,
1388
+ to(resolver) {
1389
+ events[event].reactions.set(name, {
1390
+ ...reaction,
1391
+ resolver: typeof resolver === "string" ? { target: resolver } : resolver
1392
+ });
1393
+ return builder;
1394
+ },
1395
+ void() {
1396
+ events[event].reactions.set(name, {
1397
+ ...reaction,
1398
+ resolver: _void_
1399
+ });
1400
+ return builder;
1401
+ }
1402
+ };
1403
+ }
1404
+ }),
1405
+ build: () => ({
1406
+ _tag: "Slice",
1407
+ states,
1408
+ events
1409
+ }),
1410
+ events
1411
+ };
1412
+ return builder;
1413
+ }
1414
+
1415
+ // src/act-builder.ts
1319
1416
  function act(states = /* @__PURE__ */ new Map(), registry = {
1320
1417
  actions: {},
1321
1418
  events: {}
1322
1419
  }) {
1323
1420
  const builder = {
1324
- /**
1325
- * Adds a state to the builder. When a state with the same name is already
1326
- * registered, merges the new partial's actions, events, patches, and handlers
1327
- * into the existing state (errors on duplicate action/event names).
1328
- *
1329
- * @template SX The type of state
1330
- * @template EX The type of events
1331
- * @template AX The type of actions
1332
- * @param state The state to add
1333
- * @returns The builder
1334
- */
1335
- with: (state2) => {
1336
- if (states.has(state2.name)) {
1337
- const existing = states.get(state2.name);
1338
- for (const name of Object.keys(state2.actions)) {
1339
- if (registry.actions[name])
1340
- throw new Error(`Duplicate action "${name}"`);
1341
- }
1342
- for (const name of Object.keys(state2.events)) {
1343
- if (registry.events[name])
1344
- throw new Error(`Duplicate event "${name}"`);
1345
- }
1346
- const merged = {
1347
- ...existing,
1348
- state: mergeSchemas(existing.state, state2.state, state2.name),
1349
- init: mergeInits(existing.init, state2.init),
1350
- events: { ...existing.events, ...state2.events },
1351
- actions: { ...existing.actions, ...state2.actions },
1352
- patch: { ...existing.patch, ...state2.patch },
1353
- on: { ...existing.on, ...state2.on },
1354
- given: { ...existing.given, ...state2.given },
1355
- snap: state2.snap || existing.snap
1356
- };
1357
- states.set(state2.name, merged);
1358
- for (const name of Object.keys(merged.actions)) {
1359
- registry.actions[name] = merged;
1421
+ with: ((input) => {
1422
+ if (isSlice(input)) {
1423
+ for (const s of input.states.values()) {
1424
+ registerState(s, states, registry.actions, registry.events);
1360
1425
  }
1361
- for (const name of Object.keys(state2.events)) {
1362
- registry.events[name] = {
1363
- schema: state2.events[name],
1364
- reactions: /* @__PURE__ */ new Map()
1365
- };
1366
- }
1367
- } else {
1368
- states.set(state2.name, state2);
1369
- for (const name of Object.keys(state2.actions)) {
1370
- if (registry.actions[name])
1371
- throw new Error(`Duplicate action "${name}"`);
1372
- registry.actions[name] = state2;
1373
- }
1374
- for (const name of Object.keys(state2.events)) {
1375
- if (registry.events[name])
1376
- throw new Error(`Duplicate event "${name}"`);
1377
- registry.events[name] = {
1378
- schema: state2.events[name],
1379
- reactions: /* @__PURE__ */ new Map()
1380
- };
1426
+ for (const eventName of Object.keys(input.events)) {
1427
+ const sliceRegister = input.events[eventName];
1428
+ for (const [name, reaction] of sliceRegister.reactions) {
1429
+ registry.events[eventName].reactions.set(name, reaction);
1430
+ }
1381
1431
  }
1432
+ return act(states, registry);
1382
1433
  }
1383
- return act(
1384
- states,
1385
- registry
1386
- );
1387
- },
1434
+ registerState(input, states, registry.actions, registry.events);
1435
+ return act(states, registry);
1436
+ }),
1388
1437
  /**
1389
1438
  * Adds a reaction to an event.
1390
1439
  *
@@ -1402,18 +1451,19 @@ function act(states = /* @__PURE__ */ new Map(), registry = {
1402
1451
  maxRetries: options?.maxRetries ?? 3
1403
1452
  }
1404
1453
  };
1405
- registry.events[event].reactions.set(handler.name, reaction);
1454
+ const name = handler.name || `${String(event)}_${registry.events[event].reactions.size}`;
1455
+ registry.events[event].reactions.set(name, reaction);
1406
1456
  return {
1407
1457
  ...builder,
1408
1458
  to(resolver) {
1409
- registry.events[event].reactions.set(handler.name, {
1459
+ registry.events[event].reactions.set(name, {
1410
1460
  ...reaction,
1411
1461
  resolver: typeof resolver === "string" ? { target: resolver } : resolver
1412
1462
  });
1413
1463
  return builder;
1414
1464
  },
1415
1465
  void() {
1416
- registry.events[event].reactions.set(handler.name, {
1466
+ registry.events[event].reactions.set(name, {
1417
1467
  ...reaction,
1418
1468
  resolver: _void_
1419
1469
  });
@@ -1507,10 +1557,12 @@ export {
1507
1557
  dispose,
1508
1558
  disposeAndExit,
1509
1559
  extend,
1560
+ isSlice,
1510
1561
  logger,
1511
1562
  patch,
1512
1563
  port,
1513
1564
  sleep,
1565
+ slice,
1514
1566
  state,
1515
1567
  store,
1516
1568
  validate