@rotorsoft/act 0.9.0 → 0.11.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
@@ -1361,6 +1361,70 @@ var _this_ = ({ stream }) => ({
1361
1361
  });
1362
1362
  var _void_ = () => void 0;
1363
1363
 
1364
+ // src/projection-builder.ts
1365
+ function isProjection(x) {
1366
+ return x != null && x._tag === "Projection";
1367
+ }
1368
+ function projection(target, events = {}) {
1369
+ const defaultResolver = target ? { target } : void 0;
1370
+ const builder = {
1371
+ on: (entry) => {
1372
+ const keys = Object.keys(entry);
1373
+ if (keys.length !== 1) throw new Error(".on() requires exactly one key");
1374
+ const event = keys[0];
1375
+ const schema = entry[event];
1376
+ if (!(event in events)) {
1377
+ events[event] = {
1378
+ schema,
1379
+ reactions: /* @__PURE__ */ new Map()
1380
+ };
1381
+ }
1382
+ return {
1383
+ do: (handler) => {
1384
+ const reaction = {
1385
+ handler,
1386
+ resolver: defaultResolver ?? _this_,
1387
+ options: {
1388
+ blockOnError: true,
1389
+ maxRetries: 3
1390
+ }
1391
+ };
1392
+ const register = events[event];
1393
+ const name = handler.name || `${event}_${register.reactions.size}`;
1394
+ register.reactions.set(name, reaction);
1395
+ const nextBuilder = projection(
1396
+ target,
1397
+ events
1398
+ );
1399
+ return {
1400
+ ...nextBuilder,
1401
+ to(resolver) {
1402
+ register.reactions.set(name, {
1403
+ ...reaction,
1404
+ resolver: typeof resolver === "string" ? { target: resolver } : resolver
1405
+ });
1406
+ return nextBuilder;
1407
+ },
1408
+ void() {
1409
+ register.reactions.set(name, {
1410
+ ...reaction,
1411
+ resolver: _void_
1412
+ });
1413
+ return nextBuilder;
1414
+ }
1415
+ };
1416
+ }
1417
+ };
1418
+ },
1419
+ build: () => ({
1420
+ _tag: "Projection",
1421
+ events
1422
+ }),
1423
+ events
1424
+ };
1425
+ return builder;
1426
+ }
1427
+
1364
1428
  // src/slice-builder.ts
1365
1429
  function isSlice(x) {
1366
1430
  return x != null && x._tag === "Slice";
@@ -1419,6 +1483,25 @@ function act(states = /* @__PURE__ */ new Map(), registry = {
1419
1483
  }) {
1420
1484
  const builder = {
1421
1485
  with: ((input) => {
1486
+ if (isProjection(input)) {
1487
+ for (const eventName of Object.keys(input.events)) {
1488
+ const projRegister = input.events[eventName];
1489
+ const existing = registry.events[eventName];
1490
+ if (!existing) {
1491
+ registry.events[eventName] = {
1492
+ schema: projRegister.schema,
1493
+ reactions: new Map(projRegister.reactions)
1494
+ };
1495
+ } else {
1496
+ for (const [name, reaction] of projRegister.reactions) {
1497
+ let key = name;
1498
+ while (existing.reactions.has(key)) key = `${key}_p`;
1499
+ existing.reactions.set(key, reaction);
1500
+ }
1501
+ }
1502
+ }
1503
+ return act(states, registry);
1504
+ }
1422
1505
  if (isSlice(input)) {
1423
1506
  for (const s of input.states.values()) {
1424
1507
  registerState(s, states, registry.actions, registry.events);
@@ -1479,7 +1562,11 @@ function act(states = /* @__PURE__ */ new Map(), registry = {
1479
1562
  }
1480
1563
 
1481
1564
  // src/state-builder.ts
1482
- function state(name, state2) {
1565
+ function state(entry) {
1566
+ const keys = Object.keys(entry);
1567
+ if (keys.length !== 1) throw new Error("state() requires exactly one key");
1568
+ const name = keys[0];
1569
+ const stateSchema = entry[name];
1483
1570
  return {
1484
1571
  init(init) {
1485
1572
  return {
@@ -1489,7 +1576,7 @@ function state(name, state2) {
1489
1576
  return action_builder({
1490
1577
  events,
1491
1578
  actions: {},
1492
- state: state2,
1579
+ state: stateSchema,
1493
1580
  name,
1494
1581
  init,
1495
1582
  patch: patch2,
@@ -1504,7 +1591,11 @@ function state(name, state2) {
1504
1591
  }
1505
1592
  function action_builder(state2) {
1506
1593
  return {
1507
- on(action2, schema) {
1594
+ on(entry) {
1595
+ const keys = Object.keys(entry);
1596
+ if (keys.length !== 1) throw new Error(".on() requires exactly one key");
1597
+ const action2 = keys[0];
1598
+ const schema = entry[action2];
1508
1599
  if (action2 in state2.actions)
1509
1600
  throw new Error(`Duplicate action "${action2}"`);
1510
1601
  const actions = { ...state2.actions, [action2]: schema };
@@ -1557,10 +1648,12 @@ export {
1557
1648
  dispose,
1558
1649
  disposeAndExit,
1559
1650
  extend,
1651
+ isProjection,
1560
1652
  isSlice,
1561
1653
  logger,
1562
1654
  patch,
1563
1655
  port,
1656
+ projection,
1564
1657
  sleep,
1565
1658
  slice,
1566
1659
  state,