@rotorsoft/act 1.31.14 → 1.31.15

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
@@ -68,6 +68,7 @@ __export(index_exports, {
68
68
  cache: () => cache2,
69
69
  config: () => config,
70
70
  dateReviver: () => dateReviver,
71
+ default_scope: () => default_scope,
71
72
  dispose: () => dispose,
72
73
  disposeAndExit: () => disposeAndExit,
73
74
  extend: () => extend,
@@ -407,23 +408,28 @@ function is_pii(schema) {
407
408
  cur = inner;
408
409
  }
409
410
  }
410
- function pii_fields(schema) {
411
+ function pii_schemas(schema) {
411
412
  const shape = schema.shape;
412
413
  if (shape && typeof shape === "object") {
413
- const fields = [];
414
- for (const key of Object.keys(shape)) {
415
- if (is_pii(shape[key])) fields.push(key);
416
- }
414
+ const fields = {};
415
+ for (const key of Object.keys(shape))
416
+ if (is_pii(shape[key])) fields[key] = shape[key];
417
417
  return fields;
418
418
  }
419
419
  const options = schema.options;
420
420
  if (Array.isArray(options)) {
421
- const fields = /* @__PURE__ */ new Set();
421
+ const fields = {};
422
422
  for (const option of options)
423
- for (const key of pii_fields(option)) fields.add(key);
424
- return [...fields];
423
+ for (const [key, field] of Object.entries(
424
+ pii_schemas(option)
425
+ ))
426
+ fields[key] ??= field;
427
+ return fields;
425
428
  }
426
- return [];
429
+ return {};
430
+ }
431
+ function pii_fields(schema) {
432
+ return Object.keys(pii_schemas(schema));
427
433
  }
428
434
  function pii_split(emitted, fields) {
429
435
  const data = { ...emitted.data };
@@ -1607,7 +1613,7 @@ var import_node_async_hooks = require("async_hooks");
1607
1613
  var scoped = new import_node_async_hooks.AsyncLocalStorage();
1608
1614
  var reacting = new import_node_async_hooks.AsyncLocalStorage();
1609
1615
  function make_run_scoped(bag) {
1610
- return bag ? (fn) => scoped.run(bag, fn) : (fn) => fn();
1616
+ return (fn) => scoped.run(bag, fn);
1611
1617
  }
1612
1618
  function current_ports() {
1613
1619
  return scoped.getStore();
@@ -1661,6 +1667,15 @@ var _cache = port(function cache(adapter) {
1661
1667
  var cache2 = ((adapter) => {
1662
1668
  return current_ports()?.cache ?? _cache(adapter);
1663
1669
  });
1670
+ var default_scope = () => DEFAULT_SCOPE;
1671
+ var DEFAULT_SCOPE = {
1672
+ get store() {
1673
+ return _store();
1674
+ },
1675
+ get cache() {
1676
+ return _cache();
1677
+ }
1678
+ };
1664
1679
  async function disposeAndExit(code = "EXIT") {
1665
1680
  if (code === "ERROR" && config().env === "production") {
1666
1681
  log().warn(
@@ -3509,18 +3524,83 @@ function close_correlation(correlator, actor) {
3509
3524
  });
3510
3525
  }
3511
3526
 
3512
- // src/internal/defer-config.ts
3527
+ // src/internal/date-reviver.ts
3513
3528
  var import_zod7 = require("zod");
3514
- var DeferDurationSchema = import_zod7.z.object({
3515
- days: import_zod7.z.number().positive().optional(),
3516
- hours: import_zod7.z.number().positive().optional(),
3517
- minutes: import_zod7.z.number().positive().optional()
3529
+ var def_of = (schema) => schema._zod?.def ?? schema.def;
3530
+ function variant_schema(schema) {
3531
+ const shape = def_of(schema)?.shape;
3532
+ if (!shape) {
3533
+ const dates = date_reviver_schema(schema);
3534
+ return { schema: dates ?? schema, dated: !!dates };
3535
+ }
3536
+ const next = {};
3537
+ let dated = false;
3538
+ for (const [key, field] of Object.entries(shape)) {
3539
+ const dates = date_reviver_schema(field);
3540
+ if (dates) dated = true;
3541
+ next[key] = (dates ?? field).optional();
3542
+ }
3543
+ return { schema: import_zod7.z.looseObject(next), dated };
3544
+ }
3545
+ function date_reviver_schema(schema) {
3546
+ const def = def_of(schema);
3547
+ if (!def) return void 0;
3548
+ const inner = () => date_reviver_schema(def.innerType);
3549
+ switch (def.type) {
3550
+ case "date":
3551
+ return import_zod7.z.coerce.date();
3552
+ case "object": {
3553
+ const shape = def.shape;
3554
+ if (!shape) return void 0;
3555
+ const dated = {};
3556
+ for (const [key, field] of Object.entries(shape)) {
3557
+ const dates = date_reviver_schema(field);
3558
+ if (dates) dated[key] = dates.optional();
3559
+ }
3560
+ return Object.keys(dated).length ? import_zod7.z.looseObject(dated) : void 0;
3561
+ }
3562
+ case "array": {
3563
+ const element = date_reviver_schema(def.element);
3564
+ return element && import_zod7.z.array(element);
3565
+ }
3566
+ case "tuple": {
3567
+ const items = def.items.map((i) => date_reviver_schema(i));
3568
+ return items.some(Boolean) ? import_zod7.z.tuple(items.map((i) => i ?? import_zod7.z.unknown())) : void 0;
3569
+ }
3570
+ case "record": {
3571
+ const value = date_reviver_schema(def.valueType);
3572
+ return value && import_zod7.z.record(import_zod7.z.string(), value);
3573
+ }
3574
+ case "union": {
3575
+ const variants = def.options.map(variant_schema);
3576
+ return variants.some((v) => v.dated) ? import_zod7.z.union(variants.map((v) => v.schema)) : void 0;
3577
+ }
3578
+ case "nullable":
3579
+ return inner()?.nullable();
3580
+ case "optional":
3581
+ case "nonoptional":
3582
+ case "readonly":
3583
+ case "default":
3584
+ case "prefault":
3585
+ case "catch":
3586
+ return inner();
3587
+ default:
3588
+ return void 0;
3589
+ }
3590
+ }
3591
+
3592
+ // src/internal/defer-config.ts
3593
+ var import_zod8 = require("zod");
3594
+ var DeferDurationSchema = import_zod8.z.object({
3595
+ days: import_zod8.z.number().positive().optional(),
3596
+ hours: import_zod8.z.number().positive().optional(),
3597
+ minutes: import_zod8.z.number().positive().optional()
3518
3598
  }).strict().refine((d) => d.days != null || d.hours != null || d.minutes != null, {
3519
3599
  message: "defer: a duration needs at least one of days, hours, or minutes"
3520
3600
  });
3521
- var DeferWhenSchema = import_zod7.z.object({
3601
+ var DeferWhenSchema = import_zod8.z.object({
3522
3602
  after: DeferDurationSchema.optional(),
3523
- at: import_zod7.z.date().optional()
3603
+ at: import_zod8.z.date().optional()
3524
3604
  }).strict().refine((w) => w.after === void 0 !== (w.at === void 0), {
3525
3605
  message: "defer: specify exactly one of `after` or `at`"
3526
3606
  });
@@ -5002,6 +5082,8 @@ var Act = class {
5002
5082
  * per-Act ports (ACT-501). No-op when the Act is unscoped — so the singleton
5003
5083
  * path keeps reading fresh `store()`/`cache()` per call, which matters for
5004
5084
  * tests that dispose and re-seed mid-suite. */
5085
+ /** This Act's ports: its own bag, or the singleton adapters. */
5086
+ _ports;
5005
5087
  _scoped;
5006
5088
  /**
5007
5089
  * Correlation-id generator for originating actions. Bound at
@@ -5080,7 +5162,8 @@ var Act = class {
5080
5162
  this._batch_handlers = batch_handlers;
5081
5163
  this._lanes = lanes;
5082
5164
  validate_only_lanes(options, lanes);
5083
- this._scoped = make_run_scoped(options.scoped);
5165
+ this._ports = options.scoped ?? default_scope();
5166
+ this._scoped = make_run_scoped(this._ports);
5084
5167
  this._correlator = options.correlator ?? default_correlator;
5085
5168
  this._es = build_es(this._logger, this._correlator, patch_fn);
5086
5169
  this._cd = build_drain(this._logger);
@@ -5109,7 +5192,7 @@ var Act = class {
5109
5192
  this._audit_deps = this._build_audit_deps();
5110
5193
  this._correlate = this._build_correlate(options, classification);
5111
5194
  this._settle = this._build_settle(options);
5112
- this._notify_disposer = this._wire_notify(options.scoped?.store ?? store2());
5195
+ this._notify_disposer = this._wire_notify(this._ports.store);
5113
5196
  register_weak_disposer(new WeakRef(this), (self) => self.shutdown());
5114
5197
  }
5115
5198
  /**
@@ -5358,13 +5441,13 @@ var Act = class {
5358
5441
  this._shutdown_promise = (async () => {
5359
5442
  this.stop_correlations();
5360
5443
  await this._scoped(() => this._correlate.release_correlation());
5444
+ const disposer = await this._notify_disposer;
5445
+ if (disposer) await disposer();
5361
5446
  this.stop_settling();
5362
5447
  this._breaker.stop();
5363
5448
  for (const c of this._drain_controllers.values()) c.stop();
5364
5449
  await this._await_inflight(options?.graceMs);
5365
5450
  this._emitter.removeAllListeners();
5366
- const disposer = await this._notify_disposer;
5367
- if (disposer) await disposer();
5368
5451
  })();
5369
5452
  }
5370
5453
  return this._shutdown_promise;
@@ -6362,7 +6445,7 @@ var Act = class {
6362
6445
  };
6363
6446
 
6364
6447
  // src/builders/merge.ts
6365
- var import_zod8 = require("zod");
6448
+ var import_zod9 = require("zod");
6366
6449
  function base_type_name(zodType) {
6367
6450
  let t = zodType;
6368
6451
  while (typeof t.unwrap === "function") {
@@ -6371,7 +6454,7 @@ function base_type_name(zodType) {
6371
6454
  return t.constructor.name;
6372
6455
  }
6373
6456
  function merge_schemas(existing, incoming, state_name) {
6374
- if (existing instanceof import_zod8.ZodObject && incoming instanceof import_zod8.ZodObject) {
6457
+ if (existing instanceof import_zod9.ZodObject && incoming instanceof import_zod9.ZodObject) {
6375
6458
  const existing_shape = existing.shape;
6376
6459
  const incoming_shape = incoming.shape;
6377
6460
  for (const key of Object.keys(incoming_shape)) {
@@ -6558,70 +6641,43 @@ function reaction_on(event, events, builder) {
6558
6641
  }
6559
6642
 
6560
6643
  // src/builders/event-builder.ts
6561
- var import_zod9 = require("zod");
6562
- var def_of = (schema) => schema._zod?.def ?? schema.def;
6563
- function to_read_schema(schema, found) {
6564
- const def = def_of(schema);
6565
- if (!def) return schema;
6566
- switch (def.type) {
6567
- case "date":
6568
- found.date = true;
6569
- return import_zod9.z.coerce.date();
6570
- case "object": {
6571
- const shape = def.shape;
6572
- if (!shape) return schema;
6573
- const next = {};
6574
- for (const [key, inner] of Object.entries(shape))
6575
- next[key] = to_read_schema(inner, found);
6576
- return import_zod9.z.looseObject(next);
6577
- }
6578
- case "array":
6579
- return import_zod9.z.array(to_read_schema(def.element, found));
6580
- case "record":
6581
- return import_zod9.z.record(
6582
- import_zod9.z.string(),
6583
- to_read_schema(def.valueType, found)
6584
- );
6585
- case "union":
6586
- return import_zod9.z.union(
6587
- def.options.map(
6588
- (o) => to_read_schema(o, found)
6589
- )
6590
- );
6591
- case "optional":
6592
- return to_read_schema(def.innerType, found).optional();
6593
- case "nullable":
6594
- return to_read_schema(def.innerType, found).nullable();
6595
- default:
6596
- return schema;
6597
- }
6598
- }
6644
+ var import_zod10 = require("zod");
6599
6645
  function event_tags(schema) {
6600
- const sensitive2 = [];
6601
- const collect = (node) => {
6602
- const shape = def_of(node)?.shape;
6603
- if (shape) {
6604
- for (const key of Object.keys(shape))
6605
- if (is_pii(shape[key])) sensitive2.push(key);
6606
- return;
6607
- }
6608
- const options = node.options;
6609
- if (Array.isArray(options)) for (const option of options) collect(option);
6646
+ const pii = pii_schemas(schema);
6647
+ const pii_dates = {};
6648
+ for (const [key, field] of Object.entries(pii)) {
6649
+ const dates = date_reviver_schema(field);
6650
+ if (dates) pii_dates[key] = dates.optional();
6651
+ }
6652
+ const data_reviver_schema = date_reviver_schema(schema);
6653
+ const revive = (schema2) => (data) => {
6654
+ const revived = schema2.safeParse(data);
6655
+ return revived.success ? revived.data : data;
6610
6656
  };
6611
- collect(schema);
6612
- const found = { date: false };
6613
- const read_schema = to_read_schema(schema, found);
6657
+ const dated_pii = Object.keys(pii_dates).length > 0;
6614
6658
  return {
6615
- sensitive: [...new Set(sensitive2)],
6616
- parse: found.date ? (data) => read_schema.parse(data) : void 0
6659
+ sensitive: Object.keys(pii),
6660
+ date_reviver: data_reviver_schema && revive(data_reviver_schema),
6661
+ pii_date_reviver: dated_pii ? revive(import_zod10.z.looseObject(pii_dates)) : void 0
6617
6662
  };
6618
6663
  }
6619
6664
  function make_event_reader(tags, disclosure, predicate = null) {
6620
- const { sensitive: sensitive2, parse: parse2 } = tags;
6621
- if (!parse2 && sensitive2.length === 0) return void 0;
6665
+ const { sensitive: sensitive2, date_reviver, pii_date_reviver } = tags;
6666
+ if (!date_reviver && sensitive2.length === 0) return void 0;
6622
6667
  const gate = sensitive2.length === 0 ? IDENTITY_GATE : disclosure === "strip" ? ((event) => pii_strip(event, sensitive2)) : make_gate(sensitive2, predicate);
6623
- if (!parse2) return gate;
6624
- return ((event, actor) => gate({ ...event, data: parse2(event.data) }, actor));
6668
+ if (!date_reviver) return gate;
6669
+ const revive_pii = disclosure === "redact" && predicate ? pii_date_reviver : void 0;
6670
+ return ((event, actor) => {
6671
+ const pii = event.pii;
6672
+ return gate(
6673
+ {
6674
+ ...event,
6675
+ data: date_reviver(event.data),
6676
+ ...revive_pii && actor && pii != null ? { pii: revive_pii(pii) } : {}
6677
+ },
6678
+ actor
6679
+ );
6680
+ });
6625
6681
  }
6626
6682
  function build_events(registry, states, lanes, owners) {
6627
6683
  const declared = /* @__PURE__ */ new Set([DEFAULT_LANE, ...lanes.map((l) => l.name)]);
@@ -7408,6 +7464,7 @@ function write_line(writer, line) {
7408
7464
  cache,
7409
7465
  config,
7410
7466
  dateReviver,
7467
+ default_scope,
7411
7468
  dispose,
7412
7469
  disposeAndExit,
7413
7470
  extend,