@rotorsoft/act 0.24.1 → 0.25.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/index.cjs CHANGED
@@ -35,6 +35,7 @@ __export(index_exports, {
35
35
  CausationEventSchema: () => CausationEventSchema,
36
36
  CommittedMetaSchema: () => CommittedMetaSchema,
37
37
  ConcurrencyError: () => ConcurrencyError,
38
+ ConsoleLogger: () => ConsoleLogger,
38
39
  Environments: () => Environments,
39
40
  Errors: () => Errors,
40
41
  EventMetaSchema: () => EventMetaSchema,
@@ -56,7 +57,7 @@ __export(index_exports, {
56
57
  dispose: () => dispose,
57
58
  disposeAndExit: () => disposeAndExit,
58
59
  extend: () => extend,
59
- logger: () => logger,
60
+ log: () => log,
60
61
  port: () => port,
61
62
  projection: () => projection,
62
63
  sleep: () => sleep,
@@ -67,8 +68,107 @@ __export(index_exports, {
67
68
  });
68
69
  module.exports = __toCommonJS(index_exports);
69
70
 
70
- // src/ports.ts
71
- var import_pino = require("pino");
71
+ // src/adapters/ConsoleLogger.ts
72
+ var LEVEL_VALUES = {
73
+ fatal: 60,
74
+ error: 50,
75
+ warn: 40,
76
+ info: 30,
77
+ debug: 20,
78
+ trace: 10
79
+ };
80
+ var LEVEL_COLORS = {
81
+ fatal: "\x1B[41m\x1B[37m",
82
+ // white on red bg
83
+ error: "\x1B[31m",
84
+ // red
85
+ warn: "\x1B[33m",
86
+ // yellow
87
+ info: "\x1B[32m",
88
+ // green
89
+ debug: "\x1B[36m",
90
+ // cyan
91
+ trace: "\x1B[90m"
92
+ // gray
93
+ };
94
+ var RESET = "\x1B[0m";
95
+ var noop = () => {
96
+ };
97
+ var ConsoleLogger = class _ConsoleLogger {
98
+ level;
99
+ _pretty;
100
+ fatal;
101
+ error;
102
+ warn;
103
+ info;
104
+ debug;
105
+ trace;
106
+ constructor(options = {}) {
107
+ const {
108
+ level = "info",
109
+ pretty = process.env.NODE_ENV !== "production",
110
+ bindings
111
+ } = options;
112
+ this._pretty = pretty;
113
+ this.level = level;
114
+ const threshold = LEVEL_VALUES[level] ?? 30;
115
+ const write = pretty ? this._prettyWrite.bind(this, bindings) : this._jsonWrite.bind(this, bindings);
116
+ this.fatal = write.bind(this, "fatal", 60);
117
+ this.error = threshold <= 50 ? write.bind(this, "error", 50) : noop;
118
+ this.warn = threshold <= 40 ? write.bind(this, "warn", 40) : noop;
119
+ this.info = threshold <= 30 ? write.bind(this, "info", 30) : noop;
120
+ this.debug = threshold <= 20 ? write.bind(this, "debug", 20) : noop;
121
+ this.trace = threshold <= 10 ? write.bind(this, "trace", 10) : noop;
122
+ }
123
+ async dispose() {
124
+ }
125
+ child(bindings) {
126
+ return new _ConsoleLogger({
127
+ level: this.level,
128
+ pretty: this._pretty,
129
+ bindings
130
+ });
131
+ }
132
+ _jsonWrite(bindings, level, _num, objOrMsg, msg) {
133
+ let obj;
134
+ let message;
135
+ if (typeof objOrMsg === "string") {
136
+ message = objOrMsg;
137
+ obj = {};
138
+ } else if (objOrMsg !== null && typeof objOrMsg === "object") {
139
+ message = msg;
140
+ obj = Object.fromEntries(Object.entries(objOrMsg));
141
+ } else {
142
+ message = msg;
143
+ obj = { value: objOrMsg };
144
+ }
145
+ const entry = Object.assign({ level, time: Date.now() }, bindings, obj);
146
+ if (message) entry.msg = message;
147
+ process.stdout.write(JSON.stringify(entry) + "\n");
148
+ }
149
+ _prettyWrite(bindings, level, _num, objOrMsg, msg) {
150
+ const color = LEVEL_COLORS[level];
151
+ const tag = `${color}${level.toUpperCase().padEnd(5)}${RESET}`;
152
+ const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
153
+ let message;
154
+ let data;
155
+ if (typeof objOrMsg === "string") {
156
+ message = objOrMsg;
157
+ } else {
158
+ message = msg ?? "";
159
+ if (objOrMsg !== void 0 && objOrMsg !== null) {
160
+ try {
161
+ data = JSON.stringify(objOrMsg);
162
+ } catch {
163
+ data = "[unserializable]";
164
+ }
165
+ }
166
+ }
167
+ const bindStr = bindings && Object.keys(bindings).length ? ` ${JSON.stringify(bindings)}` : "";
168
+ const parts = [ts, tag, message, data, bindStr].filter(Boolean);
169
+ process.stdout.write(parts.join(" ") + "\n");
170
+ }
171
+ };
72
172
 
73
173
  // src/adapters/InMemoryCache.ts
74
174
  var InMemoryCache = class {
@@ -195,7 +295,8 @@ var QuerySchema = import_zod.z.object({
195
295
  created_after: import_zod.z.date().optional(),
196
296
  backward: import_zod.z.boolean().optional(),
197
297
  correlation: import_zod.z.string().optional(),
198
- with_snaps: import_zod.z.boolean().optional()
298
+ with_snaps: import_zod.z.boolean().optional(),
299
+ stream_exact: import_zod.z.boolean().optional()
199
300
  }).readonly();
200
301
 
201
302
  // src/types/index.ts
@@ -376,8 +477,11 @@ var InMemoryStore = class {
376
477
  this._streams = /* @__PURE__ */ new Map();
377
478
  }
378
479
  in_query(query, e) {
379
- if (query.stream && !RegExp(`^${query.stream}$`).test(e.stream))
380
- return false;
480
+ if (query.stream) {
481
+ if (query.stream_exact) {
482
+ if (e.stream !== query.stream) return false;
483
+ } else if (!RegExp(`^${query.stream}$`).test(e.stream)) return false;
484
+ }
381
485
  if (query.names && !query.names.includes(e.name)) return false;
382
486
  if (query.correlation && e.meta?.correlation !== query.correlation)
383
487
  return false;
@@ -536,28 +640,30 @@ var InMemoryStore = class {
536
640
 
537
641
  // src/ports.ts
538
642
  var ExitCodes = ["ERROR", "EXIT"];
539
- var logger = (0, import_pino.pino)({
540
- transport: config().env !== "production" ? {
541
- target: "pino-pretty",
542
- options: {
543
- ignore: "pid,hostname",
544
- singleLine: config().logSingleLine,
545
- colorize: true
546
- }
547
- } : void 0,
548
- level: config().logLevel
549
- });
550
643
  var adapters = /* @__PURE__ */ new Map();
551
644
  function port(injector) {
552
645
  return function(adapter) {
553
646
  if (!adapters.has(injector.name)) {
554
647
  const injected = injector(adapter);
555
648
  adapters.set(injector.name, injected);
556
- logger.info(`\u{1F50C} injected ${injector.name}:${injected.constructor.name}`);
649
+ console.log(`[act] + ${injector.name}:${injected.constructor.name}`);
557
650
  }
558
651
  return adapters.get(injector.name);
559
652
  };
560
653
  }
654
+ var log = port(function log2(adapter) {
655
+ const cfg = config();
656
+ return adapter || new ConsoleLogger({
657
+ level: cfg.logLevel,
658
+ pretty: cfg.env !== "production"
659
+ });
660
+ });
661
+ var store = port(function store2(adapter) {
662
+ return adapter || new InMemoryStore();
663
+ });
664
+ var cache = port(function cache2(adapter) {
665
+ return adapter || new InMemoryCache();
666
+ });
561
667
  var disposers = [];
562
668
  async function disposeAndExit(code = "EXIT") {
563
669
  if (code === "ERROR" && config().env === "production") return;
@@ -565,7 +671,7 @@ async function disposeAndExit(code = "EXIT") {
565
671
  await Promise.all(
566
672
  [...adapters.values()].reverse().map(async (adapter) => {
567
673
  await adapter.dispose();
568
- logger.info(`\u{1F50C} disposed ${adapter.constructor.name}`);
674
+ console.log(`[act] - ${adapter.constructor.name}`);
569
675
  })
570
676
  );
571
677
  adapters.clear();
@@ -576,14 +682,9 @@ function dispose(disposer) {
576
682
  return disposeAndExit;
577
683
  }
578
684
  var SNAP_EVENT = "__snapshot__";
579
- var store = port(function store2(adapter) {
580
- return adapter || new InMemoryStore();
581
- });
582
- var cache = port(function cache2(adapter) {
583
- return adapter || new InMemoryCache();
584
- });
585
685
  function build_tracer(logLevel2) {
586
686
  if (logLevel2 === "trace") {
687
+ const logger4 = log();
587
688
  return {
588
689
  fetched: (fetched) => {
589
690
  const data = Object.fromEntries(
@@ -595,23 +696,23 @@ function build_tracer(logLevel2) {
595
696
  return [key, value];
596
697
  })
597
698
  );
598
- logger.trace(data, "\u26A1\uFE0F fetch");
699
+ logger4.trace(data, ">> fetch");
599
700
  },
600
701
  correlated: (streams) => {
601
702
  const data = streams.map(({ stream }) => stream).join(" ");
602
- logger.trace(`\u26A1\uFE0F correlate ${data}`);
703
+ logger4.trace(`>> correlate ${data}`);
603
704
  },
604
705
  leased: (leases) => {
605
706
  const data = Object.fromEntries(
606
707
  leases.map(({ stream, at, retry }) => [stream, { at, retry }])
607
708
  );
608
- logger.trace(data, "\u26A1\uFE0F lease");
709
+ logger4.trace(data, ">> lease");
609
710
  },
610
711
  acked: (leases) => {
611
712
  const data = Object.fromEntries(
612
713
  leases.map(({ stream, at, retry }) => [stream, { at, retry }])
613
714
  );
614
- logger.trace(data, "\u26A1\uFE0F ack");
715
+ logger4.trace(data, ">> ack");
615
716
  },
616
717
  blocked: (leases) => {
617
718
  const data = Object.fromEntries(
@@ -620,7 +721,7 @@ function build_tracer(logLevel2) {
620
721
  { at, retry, error }
621
722
  ])
622
723
  );
623
- logger.trace(data, "\u26A1\uFE0F block");
724
+ logger4.trace(data, ">> block");
624
725
  }
625
726
  };
626
727
  } else {
@@ -640,6 +741,7 @@ function build_tracer(logLevel2) {
640
741
  }
641
742
 
642
743
  // src/signals.ts
744
+ var logger = log();
643
745
  process.once("SIGINT", async (arg) => {
644
746
  logger.info(arg, "SIGINT");
645
747
  await disposeAndExit("EXIT");
@@ -664,6 +766,7 @@ var import_events = __toESM(require("events"), 1);
664
766
  // src/event-sourcing.ts
665
767
  var import_act_patch = require("@rotorsoft/act-patch");
666
768
  var import_crypto = require("crypto");
769
+ var logger2 = log();
667
770
  async function snap(snapshot) {
668
771
  try {
669
772
  const { id, stream, name, meta, version } = snapshot.event;
@@ -677,9 +780,9 @@ async function snap(snapshot) {
677
780
  version
678
781
  // IMPORTANT! - state events are committed right after the snapshot event
679
782
  );
680
- logger.trace(snapped, "\u{1F7E0} snap");
783
+ logger2.trace(snapped, "\u{1F7E0} snap");
681
784
  } catch (error) {
682
- logger.error(error);
785
+ logger2.error(error);
683
786
  }
684
787
  }
685
788
  async function load(me, stream, callback) {
@@ -701,9 +804,9 @@ async function load(me, stream, callback) {
701
804
  }
702
805
  callback && callback({ event, state: state2, patches, snaps });
703
806
  },
704
- { stream, with_snaps: !cached, after: cached?.event_id }
807
+ { stream, with_snaps: !cached, after: cached?.event_id, stream_exact: true }
705
808
  );
706
- logger.trace(
809
+ logger2.trace(
707
810
  state2,
708
811
  `\u{1F7E2} load ${stream}${cached && count === 0 ? " (cached)" : ""}`
709
812
  );
@@ -715,7 +818,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
715
818
  payload = skipValidation ? payload : validate(action2, payload, me.actions[action2]);
716
819
  const snapshot = await load(me, stream);
717
820
  const expected = expectedVersion || snapshot.event?.version;
718
- logger.trace(
821
+ logger2.trace(
719
822
  payload,
720
823
  `\u{1F535} ${stream}.${action2}${typeof expected === "number" ? `.${expected}` : ""}`
721
824
  );
@@ -758,7 +861,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
758
861
  } : void 0
759
862
  }
760
863
  };
761
- logger.trace(
864
+ logger2.trace(
762
865
  emitted.map((e) => e.data),
763
866
  `\u{1F534} commit ${stream}.${emitted.map((e) => e.name).join(", ")}`
764
867
  );
@@ -798,6 +901,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
798
901
  }
799
902
 
800
903
  // src/act.ts
904
+ var logger3 = log();
801
905
  var tracer = build_tracer(config().logLevel);
802
906
  var Act = class {
803
907
  constructor(registry, _states = /* @__PURE__ */ new Map()) {
@@ -1078,7 +1182,7 @@ var Act = class {
1078
1182
  if (payloads.length === 0) return { lease, handled: 0, at: lease.at };
1079
1183
  const stream = lease.stream;
1080
1184
  let at = payloads.at(0).event.id, handled = 0;
1081
- lease.retry > 0 && logger.warn(`Retrying ${stream}@${at} (${lease.retry}).`);
1185
+ lease.retry > 0 && logger3.warn(`Retrying ${stream}@${at} (${lease.retry}).`);
1082
1186
  for (const payload of payloads) {
1083
1187
  const { event, handler, options } = payload;
1084
1188
  try {
@@ -1086,9 +1190,9 @@ var Act = class {
1086
1190
  at = event.id;
1087
1191
  handled++;
1088
1192
  } catch (error) {
1089
- logger.error(error);
1193
+ logger3.error(error);
1090
1194
  const block = lease.retry >= options.maxRetries && options.blockOnError;
1091
- block && logger.error(`Blocking ${stream} after ${lease.retry} retries.`);
1195
+ block && logger3.error(`Blocking ${stream} after ${lease.retry} retries.`);
1092
1196
  return {
1093
1197
  lease,
1094
1198
  handled,
@@ -1232,7 +1336,7 @@ var Act = class {
1232
1336
  this._needs_drain = false;
1233
1337
  return result;
1234
1338
  } catch (error) {
1235
- logger.error(error);
1339
+ logger3.error(error);
1236
1340
  } finally {
1237
1341
  this._drain_locked = false;
1238
1342
  }
@@ -1505,7 +1609,7 @@ var Act = class {
1505
1609
  if (!lastDrain.acked.length && !lastDrain.blocked.length) break;
1506
1610
  }
1507
1611
  if (lastDrain) this.emit("settled", lastDrain);
1508
- })().catch((err) => logger.error(err)).finally(() => {
1612
+ })().catch((err) => logger3.error(err)).finally(() => {
1509
1613
  this._settling = false;
1510
1614
  });
1511
1615
  }, debounceMs);
@@ -1947,6 +2051,7 @@ function action_builder(state2) {
1947
2051
  CausationEventSchema,
1948
2052
  CommittedMetaSchema,
1949
2053
  ConcurrencyError,
2054
+ ConsoleLogger,
1950
2055
  Environments,
1951
2056
  Errors,
1952
2057
  EventMetaSchema,
@@ -1968,7 +2073,7 @@ function action_builder(state2) {
1968
2073
  dispose,
1969
2074
  disposeAndExit,
1970
2075
  extend,
1971
- logger,
2076
+ log,
1972
2077
  port,
1973
2078
  projection,
1974
2079
  sleep,