@rotorsoft/act 1.31.5 → 1.31.6
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.d.ts.map +1 -1
- package/dist/@types/builders/act-builder.d.ts +1 -1
- package/dist/@types/builders/act-builder.d.ts.map +1 -1
- package/dist/@types/builders/event-builder.d.ts +115 -0
- package/dist/@types/builders/event-builder.d.ts.map +1 -0
- package/dist/@types/csv.d.ts.map +1 -1
- package/dist/@types/internal/index.d.ts +1 -1
- package/dist/@types/internal/index.d.ts.map +1 -1
- package/dist/@types/internal/sensitive.d.ts +12 -0
- package/dist/@types/internal/sensitive.d.ts.map +1 -1
- package/dist/@types/types/registry.d.ts +4 -2
- package/dist/@types/types/registry.d.ts.map +1 -1
- package/dist/@types/types/schemas.d.ts +0 -1
- package/dist/@types/types/schemas.d.ts.map +1 -1
- package/dist/@types/utils.d.ts +8 -26
- package/dist/@types/utils.d.ts.map +1 -1
- package/dist/{chunk-TOJ5DZ5B.js → chunk-D5MBFIKL.js} +2 -1
- package/dist/chunk-D5MBFIKL.js.map +1 -0
- package/dist/{chunk-GQYI2NMQ.js → chunk-IO2OOCOR.js} +2 -2
- package/dist/chunk-IO2OOCOR.js.map +1 -0
- package/dist/index.cjs +158 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +161 -86
- package/dist/index.js.map +1 -1
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.js +2 -2
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-GQYI2NMQ.js.map +0 -1
- package/dist/chunk-TOJ5DZ5B.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
sleep,
|
|
25
25
|
store,
|
|
26
26
|
validate
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-IO2OOCOR.js";
|
|
28
28
|
import {
|
|
29
29
|
ActorSchema,
|
|
30
30
|
CausationEventSchema,
|
|
@@ -45,12 +45,13 @@ import {
|
|
|
45
45
|
TargetSchema,
|
|
46
46
|
ValidationError,
|
|
47
47
|
ZodEmpty,
|
|
48
|
+
is_pii,
|
|
48
49
|
make_gate,
|
|
49
50
|
pii_fields,
|
|
50
51
|
pii_split,
|
|
51
52
|
pii_strip,
|
|
52
53
|
sensitive
|
|
53
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-D5MBFIKL.js";
|
|
54
55
|
|
|
55
56
|
// src/signals.ts
|
|
56
57
|
process.once("SIGINT", async (arg) => {
|
|
@@ -3875,10 +3876,9 @@ var Act = class {
|
|
|
3875
3876
|
async query_array(query) {
|
|
3876
3877
|
return this._scoped(async () => {
|
|
3877
3878
|
const events = [];
|
|
3878
|
-
await store().query(
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
);
|
|
3879
|
+
await store().query((e) => {
|
|
3880
|
+
events.push(this.registry.query_gate(e.name)(e));
|
|
3881
|
+
}, query);
|
|
3882
3882
|
return events;
|
|
3883
3883
|
});
|
|
3884
3884
|
}
|
|
@@ -4788,6 +4788,144 @@ function reaction_on(event, events, builder) {
|
|
|
4788
4788
|
};
|
|
4789
4789
|
}
|
|
4790
4790
|
|
|
4791
|
+
// src/builders/event-builder.ts
|
|
4792
|
+
import { z as z4 } from "zod";
|
|
4793
|
+
var def_of = (schema) => schema._zod?.def ?? schema.def;
|
|
4794
|
+
function to_read_schema(schema, found) {
|
|
4795
|
+
const def = def_of(schema);
|
|
4796
|
+
if (!def) return schema;
|
|
4797
|
+
switch (def.type) {
|
|
4798
|
+
case "date":
|
|
4799
|
+
found.date = true;
|
|
4800
|
+
return z4.coerce.date();
|
|
4801
|
+
case "object": {
|
|
4802
|
+
const shape = def.shape;
|
|
4803
|
+
if (!shape) return schema;
|
|
4804
|
+
const next = {};
|
|
4805
|
+
for (const [key, inner] of Object.entries(shape))
|
|
4806
|
+
next[key] = to_read_schema(inner, found);
|
|
4807
|
+
return z4.looseObject(next);
|
|
4808
|
+
}
|
|
4809
|
+
case "array":
|
|
4810
|
+
return z4.array(to_read_schema(def.element, found));
|
|
4811
|
+
case "record":
|
|
4812
|
+
return z4.record(
|
|
4813
|
+
z4.string(),
|
|
4814
|
+
to_read_schema(def.valueType, found)
|
|
4815
|
+
);
|
|
4816
|
+
case "union":
|
|
4817
|
+
return z4.union(
|
|
4818
|
+
def.options.map(
|
|
4819
|
+
(o) => to_read_schema(o, found)
|
|
4820
|
+
)
|
|
4821
|
+
);
|
|
4822
|
+
case "optional":
|
|
4823
|
+
return to_read_schema(def.innerType, found).optional();
|
|
4824
|
+
case "nullable":
|
|
4825
|
+
return to_read_schema(def.innerType, found).nullable();
|
|
4826
|
+
default:
|
|
4827
|
+
return schema;
|
|
4828
|
+
}
|
|
4829
|
+
}
|
|
4830
|
+
function event_tags(schema) {
|
|
4831
|
+
const sensitive2 = [];
|
|
4832
|
+
const collect = (node) => {
|
|
4833
|
+
const shape = def_of(node)?.shape;
|
|
4834
|
+
if (shape) {
|
|
4835
|
+
for (const key of Object.keys(shape))
|
|
4836
|
+
if (is_pii(shape[key])) sensitive2.push(key);
|
|
4837
|
+
return;
|
|
4838
|
+
}
|
|
4839
|
+
const options = node.options;
|
|
4840
|
+
if (Array.isArray(options)) for (const option of options) collect(option);
|
|
4841
|
+
};
|
|
4842
|
+
collect(schema);
|
|
4843
|
+
const found = { date: false };
|
|
4844
|
+
const read_schema = to_read_schema(schema, found);
|
|
4845
|
+
return {
|
|
4846
|
+
sensitive: [...new Set(sensitive2)],
|
|
4847
|
+
parse: found.date ? (data) => read_schema.parse(data) : void 0
|
|
4848
|
+
};
|
|
4849
|
+
}
|
|
4850
|
+
function make_event_reader(tags, disclosure, predicate = null) {
|
|
4851
|
+
const { sensitive: sensitive2, parse: parse2 } = tags;
|
|
4852
|
+
if (!parse2 && sensitive2.length === 0) return void 0;
|
|
4853
|
+
const gate = sensitive2.length === 0 ? IDENTITY_GATE : disclosure === "strip" ? ((event) => pii_strip(event, sensitive2)) : make_gate(sensitive2, predicate);
|
|
4854
|
+
if (!parse2) return gate;
|
|
4855
|
+
return ((event, actor) => gate({ ...event, data: parse2(event.data) }, actor));
|
|
4856
|
+
}
|
|
4857
|
+
function build_events(registry, states, lanes, owners) {
|
|
4858
|
+
const declared = /* @__PURE__ */ new Set([DEFAULT_LANE, ...lanes.map((l) => l.name)]);
|
|
4859
|
+
const lane_errors = [];
|
|
4860
|
+
const tags = /* @__PURE__ */ new Map();
|
|
4861
|
+
const sensitive2 = /* @__PURE__ */ new Map();
|
|
4862
|
+
const query_readers = /* @__PURE__ */ new Map();
|
|
4863
|
+
const handler_readers = /* @__PURE__ */ new Map();
|
|
4864
|
+
for (const [event_name, def] of Object.entries(
|
|
4865
|
+
registry.events
|
|
4866
|
+
)) {
|
|
4867
|
+
for (const [handler_name, reaction] of def.reactions) {
|
|
4868
|
+
if (typeof reaction.resolver === "function") continue;
|
|
4869
|
+
const resolver = reaction.resolver;
|
|
4870
|
+
const claimed = owners.batch_handlers.has(resolver.target) || owners.fold_targets.has(resolver.target);
|
|
4871
|
+
if (claimed && !owners.projection_reactions.has(reaction))
|
|
4872
|
+
throw new Error(
|
|
4873
|
+
`Reaction on target "${resolver.target}" conflicts with the projection that already serves it \u2014 a target is served by one batch handler or one state projection, and a reaction to it would never run`
|
|
4874
|
+
);
|
|
4875
|
+
if (resolver.lane && !declared.has(resolver.lane))
|
|
4876
|
+
lane_errors.push(
|
|
4877
|
+
`Reaction "${handler_name}" on "${event_name}" targets undeclared lane "${resolver.lane}". Declared lanes: ${[...declared].map((l) => `"${l}"`).join(", ")}. Add \`.withLane({ name: "${resolver.lane}", ... })\` to act() or correct the .to() declaration.`
|
|
4878
|
+
);
|
|
4879
|
+
}
|
|
4880
|
+
const event = event_tags(def.schema);
|
|
4881
|
+
tags.set(event_name, event);
|
|
4882
|
+
if (event.sensitive.length > 0) sensitive2.set(event_name, event.sensitive);
|
|
4883
|
+
const query_reader = make_event_reader(event, "redact", null);
|
|
4884
|
+
if (query_reader) query_readers.set(event_name, query_reader);
|
|
4885
|
+
const handler_reader = make_event_reader(event, "strip");
|
|
4886
|
+
if (handler_reader) {
|
|
4887
|
+
handler_readers.set(event_name, handler_reader);
|
|
4888
|
+
for (const [name, reaction] of def.reactions) {
|
|
4889
|
+
const inner = reaction.handler;
|
|
4890
|
+
const wrapped = (evt, stream, app) => inner(handler_reader(evt), stream, app);
|
|
4891
|
+
Object.defineProperty(wrapped, "name", { value: inner.name });
|
|
4892
|
+
reaction.handler = wrapped;
|
|
4893
|
+
def.reactions.set(name, reaction);
|
|
4894
|
+
}
|
|
4895
|
+
}
|
|
4896
|
+
}
|
|
4897
|
+
if (lane_errors.length > 0) throw new Error(lane_errors[0]);
|
|
4898
|
+
for (const state2 of states.values()) {
|
|
4899
|
+
const state_fields = /* @__PURE__ */ new Map();
|
|
4900
|
+
for (const event_name of Object.keys(state2.events)) {
|
|
4901
|
+
const fields = sensitive2.get(event_name);
|
|
4902
|
+
if (fields) state_fields.set(event_name, fields);
|
|
4903
|
+
}
|
|
4904
|
+
if (state_fields.size > 0) {
|
|
4905
|
+
if (state2.snap)
|
|
4906
|
+
throw new Error(
|
|
4907
|
+
`State "${state2.name}" cannot snapshot \u2014 events {${[...state_fields.keys()].join(", ")}} carry sensitive fields. Snapshots write derived state into __snapshot__.data, which forget_pii cannot reach. Remove .snap() or remove sensitive(...) markers.`
|
|
4908
|
+
);
|
|
4909
|
+
state2.pii_aware = true;
|
|
4910
|
+
state2.message = (validated) => {
|
|
4911
|
+
const fields = state_fields.get(validated.name);
|
|
4912
|
+
return fields ? pii_split(validated, fields) : validated;
|
|
4913
|
+
};
|
|
4914
|
+
}
|
|
4915
|
+
const readers = /* @__PURE__ */ new Map();
|
|
4916
|
+
for (const event_name of Object.keys(state2.events)) {
|
|
4917
|
+
const event = tags.get(event_name);
|
|
4918
|
+
const reader = event && make_event_reader(event, "redact", state2.disclose ?? null);
|
|
4919
|
+
if (reader) readers.set(event_name, reader);
|
|
4920
|
+
}
|
|
4921
|
+
const snap2 = make_event_reader(event_tags(state2.state), "redact", null);
|
|
4922
|
+
if (snap2) readers.set(SNAP_EVENT, snap2);
|
|
4923
|
+
if (readers.size === 0) continue;
|
|
4924
|
+
state2.view = (event, actor) => (readers.get(event.name) ?? IDENTITY_GATE)(event, actor);
|
|
4925
|
+
}
|
|
4926
|
+
return { sensitive: sensitive2, query_readers, handler_readers };
|
|
4927
|
+
}
|
|
4928
|
+
|
|
4791
4929
|
// src/builders/act-builder.ts
|
|
4792
4930
|
function register_batch_handler(proj, batch_handlers) {
|
|
4793
4931
|
if (!proj.batchHandler || !proj.target) return;
|
|
@@ -4799,25 +4937,10 @@ function register_batch_handler(proj, batch_handlers) {
|
|
|
4799
4937
|
}
|
|
4800
4938
|
batch_handlers.set(proj.target, proj.batchHandler);
|
|
4801
4939
|
}
|
|
4802
|
-
function validate_lane_references(registry, lanes) {
|
|
4803
|
-
const declared = /* @__PURE__ */ new Set([DEFAULT_LANE, ...lanes.map((l) => l.name)]);
|
|
4804
|
-
for (const [event_name, def] of Object.entries(registry.events)) {
|
|
4805
|
-
const entry = def;
|
|
4806
|
-
for (const [handlerName, reaction] of entry.reactions) {
|
|
4807
|
-
const resolver = reaction.resolver;
|
|
4808
|
-
if (typeof resolver === "function") continue;
|
|
4809
|
-
const lane = resolver.lane;
|
|
4810
|
-
if (lane && !declared.has(lane)) {
|
|
4811
|
-
throw new Error(
|
|
4812
|
-
`Reaction "${handlerName}" on "${event_name}" targets undeclared lane "${lane}". Declared lanes: ${[...declared].map((l) => `"${l}"`).join(", ")}. Add \`.withLane({ name: "${lane}", ... })\` to act() or correct the .to() declaration.`
|
|
4813
|
-
);
|
|
4814
|
-
}
|
|
4815
|
-
}
|
|
4816
|
-
}
|
|
4817
|
-
}
|
|
4818
4940
|
function act() {
|
|
4819
4941
|
const states = /* @__PURE__ */ new Map();
|
|
4820
4942
|
const _sf = /* @__PURE__ */ new Map();
|
|
4943
|
+
const _hr = /* @__PURE__ */ new Map();
|
|
4821
4944
|
const _qg = /* @__PURE__ */ new Map();
|
|
4822
4945
|
const _dp = /* @__PURE__ */ new Map();
|
|
4823
4946
|
const _de = /* @__PURE__ */ new Map();
|
|
@@ -4848,13 +4971,10 @@ function act() {
|
|
|
4848
4971
|
const fold_specs = [];
|
|
4849
4972
|
const lanes = [];
|
|
4850
4973
|
let _built = false;
|
|
4851
|
-
const
|
|
4974
|
+
const read_wrap = (original) => {
|
|
4852
4975
|
const wrapped = async (events, stream) => {
|
|
4853
|
-
const
|
|
4854
|
-
|
|
4855
|
-
return f ? pii_strip(e, f) : e;
|
|
4856
|
-
});
|
|
4857
|
-
return original(stripped, stream);
|
|
4976
|
+
const read = events.map((e) => _hr.get(e.name)?.(e) ?? e);
|
|
4977
|
+
return original(read, stream);
|
|
4858
4978
|
};
|
|
4859
4979
|
const reset = original[FOLD_RESET];
|
|
4860
4980
|
if (reset) Object.defineProperty(wrapped, FOLD_RESET, { value: reset });
|
|
@@ -4865,14 +4985,14 @@ function act() {
|
|
|
4865
4985
|
for (const spec of fold_specs) {
|
|
4866
4986
|
handlers.set(
|
|
4867
4987
|
spec.target,
|
|
4868
|
-
|
|
4988
|
+
read_wrap(
|
|
4869
4989
|
make_fold_handler(
|
|
4870
4990
|
spec.merged,
|
|
4871
4991
|
spec.flush,
|
|
4872
4992
|
spec.config,
|
|
4873
4993
|
patch_fn,
|
|
4874
4994
|
// Head loads strip sensitive keys like the warm path (#1320).
|
|
4875
|
-
|
|
4995
|
+
registry.sensitive_fields
|
|
4876
4996
|
)
|
|
4877
4997
|
)
|
|
4878
4998
|
);
|
|
@@ -4990,67 +5110,22 @@ function act() {
|
|
|
4990
5110
|
config: fold.config
|
|
4991
5111
|
});
|
|
4992
5112
|
}
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
);
|
|
5002
|
-
}
|
|
5003
|
-
}
|
|
5113
|
+
const built = build_events(registry, states, lanes, {
|
|
5114
|
+
batch_handlers,
|
|
5115
|
+
fold_targets: new Set(fold_specs.map((f) => f.target)),
|
|
5116
|
+
projection_reactions
|
|
5117
|
+
});
|
|
5118
|
+
for (const [name, fields] of built.sensitive) _sf.set(name, fields);
|
|
5119
|
+
for (const [name, gate] of built.query_readers) _qg.set(name, gate);
|
|
5120
|
+
for (const [name, gate] of built.handler_readers) _hr.set(name, gate);
|
|
5004
5121
|
finalize_deprecations();
|
|
5005
|
-
validate_lane_references(registry, lanes);
|
|
5006
|
-
for (const [event_name, reg] of Object.entries(
|
|
5007
|
-
registry.events
|
|
5008
|
-
)) {
|
|
5009
|
-
const fields = pii_fields(reg.schema);
|
|
5010
|
-
if (fields.length === 0) continue;
|
|
5011
|
-
_sf.set(event_name, fields);
|
|
5012
|
-
_qg.set(event_name, make_gate(fields, null));
|
|
5013
|
-
for (const [name, reaction] of reg.reactions) {
|
|
5014
|
-
const inner = reaction.handler;
|
|
5015
|
-
const wrapped = (event, stream, app) => inner(pii_strip(event, fields), stream, app);
|
|
5016
|
-
Object.defineProperty(wrapped, "name", { value: inner.name });
|
|
5017
|
-
reaction.handler = wrapped;
|
|
5018
|
-
reg.reactions.set(name, reaction);
|
|
5019
|
-
}
|
|
5020
|
-
}
|
|
5021
5122
|
for (const state2 of states.values()) {
|
|
5022
5123
|
if (state2.disclose) _dp.set(state2.name, state2.disclose);
|
|
5023
5124
|
if (state2.autoclose) _ac.set(state2.name, state2.autoclose);
|
|
5024
5125
|
if (state2.archive) _aa.set(state2.name, state2.archive);
|
|
5025
|
-
const fields_by_event = /* @__PURE__ */ new Map();
|
|
5026
|
-
for (const event_name of Object.keys(state2.events)) {
|
|
5027
|
-
const fields = _sf.get(event_name);
|
|
5028
|
-
if (fields) fields_by_event.set(event_name, fields);
|
|
5029
|
-
}
|
|
5030
|
-
if (fields_by_event.size === 0) continue;
|
|
5031
|
-
if (state2.snap) {
|
|
5032
|
-
const offending = [...fields_by_event.keys()];
|
|
5033
|
-
throw new Error(
|
|
5034
|
-
`State "${state2.name}" cannot snapshot \u2014 events {${offending.join(", ")}} carry sensitive fields. Snapshots write derived state into __snapshot__.data, which forget_pii cannot reach. Remove .snap() or remove sensitive(...) markers.`
|
|
5035
|
-
);
|
|
5036
|
-
}
|
|
5037
|
-
const disclose = state2.disclose ?? null;
|
|
5038
|
-
state2.pii_aware = true;
|
|
5039
|
-
const view_gates = /* @__PURE__ */ new Map();
|
|
5040
|
-
for (const [event_name, fields] of fields_by_event) {
|
|
5041
|
-
view_gates.set(event_name, make_gate(fields, disclose));
|
|
5042
|
-
}
|
|
5043
|
-
state2.view = (event, actor) => (view_gates.get(event.name) ?? IDENTITY_GATE)(
|
|
5044
|
-
event,
|
|
5045
|
-
actor
|
|
5046
|
-
);
|
|
5047
|
-
state2.message = (validated) => {
|
|
5048
|
-
const fields = fields_by_event.get(validated.name);
|
|
5049
|
-
return fields ? pii_split(validated, fields) : validated;
|
|
5050
|
-
};
|
|
5051
5126
|
}
|
|
5052
5127
|
for (const [target, original] of batch_handlers) {
|
|
5053
|
-
batch_handlers.set(target,
|
|
5128
|
+
batch_handlers.set(target, read_wrap(original));
|
|
5054
5129
|
}
|
|
5055
5130
|
synthesize_autoclose_reactions(
|
|
5056
5131
|
registry,
|
|
@@ -5409,11 +5484,11 @@ var CsvFile = class {
|
|
|
5409
5484
|
// payload must not depend on whether it came back through a store or
|
|
5410
5485
|
// through a CSV restore (#1399). The `created` column below has
|
|
5411
5486
|
// always been parsed explicitly; the JSON columns were missed.
|
|
5412
|
-
data: JSON.parse(fields[2]
|
|
5487
|
+
data: JSON.parse(fields[2]),
|
|
5413
5488
|
stream: fields[3],
|
|
5414
5489
|
version: Number.parseInt(fields[4], 10),
|
|
5415
5490
|
created: new Date(fields[5]),
|
|
5416
|
-
meta: JSON.parse(fields[6]
|
|
5491
|
+
meta: JSON.parse(fields[6])
|
|
5417
5492
|
};
|
|
5418
5493
|
await Promise.resolve(callback(event));
|
|
5419
5494
|
count++;
|