@rotorsoft/act 1.17.0 → 1.18.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/.tsbuildinfo +1 -1
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/builders/act-builder.d.ts +3 -6
- package/dist/@types/builders/act-builder.d.ts.map +1 -1
- package/dist/@types/builders/slice-builder.d.ts +16 -8
- package/dist/@types/builders/slice-builder.d.ts.map +1 -1
- package/dist/@types/index.d.ts +1 -0
- package/dist/@types/index.d.ts.map +1 -1
- package/dist/@types/internal/builder-utils.d.ts +65 -0
- package/dist/@types/internal/builder-utils.d.ts.map +1 -0
- package/dist/@types/internal/defer-config.d.ts +64 -0
- package/dist/@types/internal/defer-config.d.ts.map +1 -0
- package/dist/@types/internal/defer-signal.d.ts +19 -11
- package/dist/@types/internal/defer-signal.d.ts.map +1 -1
- package/dist/@types/internal/index.d.ts +3 -2
- package/dist/@types/internal/index.d.ts.map +1 -1
- package/dist/@types/internal/reactions.d.ts.map +1 -1
- package/dist/@types/types/action.d.ts +27 -0
- package/dist/@types/types/action.d.ts.map +1 -1
- package/dist/index.cjs +267 -234
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +266 -234
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
DEFAULT_LANE: () => DEFAULT_LANE,
|
|
44
44
|
DEFAULT_MAX_SUBSCRIBED_STREAMS: () => DEFAULT_MAX_SUBSCRIBED_STREAMS,
|
|
45
45
|
DEFAULT_SETTLE_DEBOUNCE_MS: () => DEFAULT_SETTLE_DEBOUNCE_MS,
|
|
46
|
+
DeferSignal: () => DeferSignal,
|
|
46
47
|
Environments: () => Environments,
|
|
47
48
|
Errors: () => Errors,
|
|
48
49
|
EventMetaSchema: () => EventMetaSchema,
|
|
@@ -2130,13 +2131,258 @@ function classify_registry(registry, states) {
|
|
|
2130
2131
|
};
|
|
2131
2132
|
}
|
|
2132
2133
|
|
|
2133
|
-
// src/internal/
|
|
2134
|
+
// src/internal/defer-config.ts
|
|
2134
2135
|
var import_zod7 = require("zod");
|
|
2136
|
+
|
|
2137
|
+
// src/internal/defer-signal.ts
|
|
2138
|
+
var DeferSignal = class extends Error {
|
|
2139
|
+
/**
|
|
2140
|
+
* The unresolved schedule. The dispatcher turns this into an absolute
|
|
2141
|
+
* due-time by resolving it against the triggering event.
|
|
2142
|
+
*/
|
|
2143
|
+
when;
|
|
2144
|
+
constructor(when) {
|
|
2145
|
+
super("reaction deferred");
|
|
2146
|
+
this.name = "DeferSignal";
|
|
2147
|
+
this.when = when;
|
|
2148
|
+
}
|
|
2149
|
+
};
|
|
2150
|
+
|
|
2151
|
+
// src/internal/defer-config.ts
|
|
2152
|
+
var DeferDurationSchema = import_zod7.z.object({
|
|
2153
|
+
days: import_zod7.z.number().positive().optional(),
|
|
2154
|
+
hours: import_zod7.z.number().positive().optional(),
|
|
2155
|
+
minutes: import_zod7.z.number().positive().optional()
|
|
2156
|
+
}).strict().refine((d) => d.days != null || d.hours != null || d.minutes != null, {
|
|
2157
|
+
message: "defer: a duration needs at least one of days, hours, or minutes"
|
|
2158
|
+
});
|
|
2159
|
+
var DeferWhenSchema = import_zod7.z.object({
|
|
2160
|
+
after: DeferDurationSchema.optional(),
|
|
2161
|
+
at: import_zod7.z.date().optional()
|
|
2162
|
+
}).strict().refine((w) => w.after === void 0 !== (w.at === void 0), {
|
|
2163
|
+
message: "defer: specify exactly one of `after` or `at`"
|
|
2164
|
+
});
|
|
2165
|
+
function duration_ms(d) {
|
|
2166
|
+
return (d.days ?? 0) * 864e5 + (d.hours ?? 0) * 36e5 + (d.minutes ?? 0) * 6e4;
|
|
2167
|
+
}
|
|
2168
|
+
function resolve_defer_at(when, event) {
|
|
2169
|
+
const parsed = DeferWhenSchema.parse(when);
|
|
2170
|
+
if (parsed.after) return event.created.getTime() + duration_ms(parsed.after);
|
|
2171
|
+
return parsed.at.getTime();
|
|
2172
|
+
}
|
|
2173
|
+
function assert_defer_when(when) {
|
|
2174
|
+
DeferWhenSchema.parse(when);
|
|
2175
|
+
}
|
|
2176
|
+
function make_deferred(handler, schedule) {
|
|
2177
|
+
const call = handler;
|
|
2178
|
+
const deferred = async (event, stream, app) => {
|
|
2179
|
+
const when = typeof schedule === "function" ? schedule(event) : schedule;
|
|
2180
|
+
if (Date.now() < resolve_defer_at(when, event)) throw new DeferSignal(when);
|
|
2181
|
+
return call(event, stream, app);
|
|
2182
|
+
};
|
|
2183
|
+
Object.defineProperty(deferred, "name", { value: handler.name });
|
|
2184
|
+
return deferred;
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
// src/internal/merge.ts
|
|
2188
|
+
var import_zod8 = require("zod");
|
|
2189
|
+
function base_type_name(zodType) {
|
|
2190
|
+
let t = zodType;
|
|
2191
|
+
while (typeof t.unwrap === "function") {
|
|
2192
|
+
t = t.unwrap();
|
|
2193
|
+
}
|
|
2194
|
+
return t.constructor.name;
|
|
2195
|
+
}
|
|
2196
|
+
function merge_schemas(existing, incoming, state_name) {
|
|
2197
|
+
if (existing instanceof import_zod8.ZodObject && incoming instanceof import_zod8.ZodObject) {
|
|
2198
|
+
const existing_shape = existing.shape;
|
|
2199
|
+
const incoming_shape = incoming.shape;
|
|
2200
|
+
for (const key of Object.keys(incoming_shape)) {
|
|
2201
|
+
if (key in existing_shape) {
|
|
2202
|
+
const existing_base = base_type_name(existing_shape[key]);
|
|
2203
|
+
const incoming_base = base_type_name(incoming_shape[key]);
|
|
2204
|
+
if (existing_base !== incoming_base) {
|
|
2205
|
+
throw new Error(
|
|
2206
|
+
`Schema conflict in "${state_name}": key "${key}" has type "${existing_base}" but incoming partial declares "${incoming_base}"`
|
|
2207
|
+
);
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
return existing.extend(incoming_shape);
|
|
2212
|
+
}
|
|
2213
|
+
return existing;
|
|
2214
|
+
}
|
|
2215
|
+
function merge_inits(existing, incoming) {
|
|
2216
|
+
return () => ({ ...existing(), ...incoming() });
|
|
2217
|
+
}
|
|
2218
|
+
function register_state(state2, states, actions, events) {
|
|
2219
|
+
const existing = states.get(state2.name);
|
|
2220
|
+
if (existing) {
|
|
2221
|
+
merge_into_existing(state2, existing, states, actions, events);
|
|
2222
|
+
} else {
|
|
2223
|
+
register_new_state(state2, states, actions, events);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
function register_new_state(state2, states, actions, events) {
|
|
2227
|
+
states.set(state2.name, state2);
|
|
2228
|
+
for (const name of Object.keys(state2.actions)) {
|
|
2229
|
+
if (actions[name]) throw new Error(`Duplicate action "${name}"`);
|
|
2230
|
+
actions[name] = state2;
|
|
2231
|
+
}
|
|
2232
|
+
for (const name of Object.keys(state2.events)) {
|
|
2233
|
+
if (events[name]) throw new Error(`Duplicate event "${name}"`);
|
|
2234
|
+
events[name] = { schema: state2.events[name], reactions: /* @__PURE__ */ new Map() };
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
function merge_into_existing(state2, existing, states, actions, events) {
|
|
2238
|
+
for (const name of Object.keys(state2.actions)) {
|
|
2239
|
+
if (existing.actions[name] === state2.actions[name]) continue;
|
|
2240
|
+
if (actions[name]) throw new Error(`Duplicate action "${name}"`);
|
|
2241
|
+
}
|
|
2242
|
+
for (const name of Object.keys(state2.events)) {
|
|
2243
|
+
if (existing.events[name] === state2.events[name]) continue;
|
|
2244
|
+
if (existing.events[name]) {
|
|
2245
|
+
throw new Error(
|
|
2246
|
+
`Event "${name}" in state "${state2.name}" is declared with different Zod schemas across slices. Cross-slice event schemas must reference the same instance \u2014 extract a shared schema (e.g. \`export const ${name} = z.object({ ... })\` in a shared module) and import it in every slice that declares it.`
|
|
2247
|
+
);
|
|
2248
|
+
}
|
|
2249
|
+
if (events[name]) throw new Error(`Duplicate event "${name}"`);
|
|
2250
|
+
}
|
|
2251
|
+
const merged_patch = merge_patches(existing.patch, state2.patch, state2.name);
|
|
2252
|
+
const merged = {
|
|
2253
|
+
...existing,
|
|
2254
|
+
state: merge_schemas(existing.state, state2.state, state2.name),
|
|
2255
|
+
init: merge_inits(existing.init, state2.init),
|
|
2256
|
+
events: { ...existing.events, ...state2.events },
|
|
2257
|
+
actions: { ...existing.actions, ...state2.actions },
|
|
2258
|
+
patch: merged_patch,
|
|
2259
|
+
on: { ...existing.on, ...state2.on },
|
|
2260
|
+
given: { ...existing.given, ...state2.given },
|
|
2261
|
+
snap: state2.snap && existing.snap && state2.snap !== existing.snap ? (() => {
|
|
2262
|
+
throw new Error(
|
|
2263
|
+
`Duplicate snap strategy for state "${state2.name}"`
|
|
2264
|
+
);
|
|
2265
|
+
})() : state2.snap || existing.snap
|
|
2266
|
+
};
|
|
2267
|
+
states.set(state2.name, merged);
|
|
2268
|
+
for (const name of Object.keys(merged.actions)) {
|
|
2269
|
+
actions[name] = merged;
|
|
2270
|
+
}
|
|
2271
|
+
for (const name of Object.keys(state2.events)) {
|
|
2272
|
+
if (events[name]) continue;
|
|
2273
|
+
events[name] = { schema: state2.events[name], reactions: /* @__PURE__ */ new Map() };
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
function merge_patches(existing, incoming, state_name) {
|
|
2277
|
+
const merged = { ...existing };
|
|
2278
|
+
for (const name of Object.keys(incoming)) {
|
|
2279
|
+
const existing_p = existing[name];
|
|
2280
|
+
const incoming_p = incoming[name];
|
|
2281
|
+
if (!existing_p) {
|
|
2282
|
+
merged[name] = incoming_p;
|
|
2283
|
+
continue;
|
|
2284
|
+
}
|
|
2285
|
+
const existing_is_default = existing_p._passthrough;
|
|
2286
|
+
const incoming_is_default = incoming_p._passthrough;
|
|
2287
|
+
if (!existing_is_default && !incoming_is_default && existing_p !== incoming_p) {
|
|
2288
|
+
throw new Error(
|
|
2289
|
+
`Duplicate custom patch for event "${name}" in state "${state_name}"`
|
|
2290
|
+
);
|
|
2291
|
+
}
|
|
2292
|
+
if (existing_is_default && !incoming_is_default) {
|
|
2293
|
+
merged[name] = incoming_p;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
return merged;
|
|
2297
|
+
}
|
|
2298
|
+
function merge_event_register(target, source) {
|
|
2299
|
+
for (const [event_name, source_reg] of Object.entries(source)) {
|
|
2300
|
+
const target_reg = target[event_name];
|
|
2301
|
+
if (!target_reg) continue;
|
|
2302
|
+
for (const [name, reaction] of source_reg.reactions) {
|
|
2303
|
+
const existing = target_reg.reactions.get(name);
|
|
2304
|
+
if (existing !== void 0 && existing !== reaction)
|
|
2305
|
+
throw new Error(
|
|
2306
|
+
`Duplicate reaction "${name}" for event "${event_name}". Reaction handlers are keyed by function name; rename one of them.`
|
|
2307
|
+
);
|
|
2308
|
+
target_reg.reactions.set(name, reaction);
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
function merge_projection(proj, events) {
|
|
2313
|
+
for (const event_name of Object.keys(proj.events)) {
|
|
2314
|
+
const proj_register = proj.events[event_name];
|
|
2315
|
+
const existing = events[event_name];
|
|
2316
|
+
if (!existing) {
|
|
2317
|
+
events[event_name] = {
|
|
2318
|
+
schema: proj_register.schema,
|
|
2319
|
+
reactions: new Map(proj_register.reactions)
|
|
2320
|
+
};
|
|
2321
|
+
} else {
|
|
2322
|
+
for (const [name, reaction] of proj_register.reactions) {
|
|
2323
|
+
let key = name;
|
|
2324
|
+
while (existing.reactions.has(key)) key = `${key}_p`;
|
|
2325
|
+
existing.reactions.set(key, reaction);
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
var _this_ = ({ stream }) => ({
|
|
2331
|
+
source: stream,
|
|
2332
|
+
target: stream
|
|
2333
|
+
});
|
|
2334
|
+
|
|
2335
|
+
// src/internal/builder-utils.ts
|
|
2336
|
+
function register_lane(config2, lanes) {
|
|
2337
|
+
if (config2.name === DEFAULT_LANE)
|
|
2338
|
+
throw new Error(`Lane "${DEFAULT_LANE}" is reserved`);
|
|
2339
|
+
if (lanes.some((l) => l.name === config2.name))
|
|
2340
|
+
throw new Error(`Lane "${config2.name}" was already declared`);
|
|
2341
|
+
lanes.push(config2);
|
|
2342
|
+
}
|
|
2343
|
+
function reaction_on(event, events, builder) {
|
|
2344
|
+
const register = (handler, options, schedule) => {
|
|
2345
|
+
if (!handler.name)
|
|
2346
|
+
throw new Error(
|
|
2347
|
+
`Reaction handler for "${String(event)}" must be a named function`
|
|
2348
|
+
);
|
|
2349
|
+
if (events[event].reactions.has(handler.name))
|
|
2350
|
+
throw new Error(
|
|
2351
|
+
`Duplicate reaction "${handler.name}" for event "${String(event)}". Reaction handlers are keyed by function name; rename one of them.`
|
|
2352
|
+
);
|
|
2353
|
+
if (schedule && typeof schedule !== "function") assert_defer_when(schedule);
|
|
2354
|
+
const reaction = {
|
|
2355
|
+
handler: schedule ? make_deferred(handler, schedule) : handler,
|
|
2356
|
+
resolver: _this_,
|
|
2357
|
+
options: {
|
|
2358
|
+
blockOnError: options?.blockOnError ?? true,
|
|
2359
|
+
maxRetries: options?.maxRetries ?? 3,
|
|
2360
|
+
backoff: options?.backoff
|
|
2361
|
+
}
|
|
2362
|
+
};
|
|
2363
|
+
events[event].reactions.set(handler.name, reaction);
|
|
2364
|
+
return Object.assign(builder, {
|
|
2365
|
+
to(resolver) {
|
|
2366
|
+
reaction.resolver = typeof resolver === "string" ? { target: resolver } : resolver;
|
|
2367
|
+
return builder;
|
|
2368
|
+
}
|
|
2369
|
+
});
|
|
2370
|
+
};
|
|
2371
|
+
return {
|
|
2372
|
+
do: (handler, options) => register(handler, options),
|
|
2373
|
+
defer: (schedule) => ({
|
|
2374
|
+
do: (handler, options) => register(handler, options, schedule)
|
|
2375
|
+
})
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
// src/internal/circuit-breaker.ts
|
|
2380
|
+
var import_zod9 = require("zod");
|
|
2135
2381
|
var DEFAULT_CIRCUIT_FAILURE_THRESHOLD = 5;
|
|
2136
2382
|
var DEFAULT_CIRCUIT_COOLDOWN_MS = 3e4;
|
|
2137
|
-
var CircuitBreakerOptionsSchema =
|
|
2138
|
-
failureThreshold:
|
|
2139
|
-
cooldownMs:
|
|
2383
|
+
var CircuitBreakerOptionsSchema = import_zod9.z.object({
|
|
2384
|
+
failureThreshold: import_zod9.z.number().int().min(1).default(DEFAULT_CIRCUIT_FAILURE_THRESHOLD),
|
|
2385
|
+
cooldownMs: import_zod9.z.number().int().min(100).max(36e5).default(DEFAULT_CIRCUIT_COOLDOWN_MS)
|
|
2140
2386
|
});
|
|
2141
2387
|
var resolveCircuitBreakerConfig = (options) => CircuitBreakerOptionsSchema.parse(options ?? {});
|
|
2142
2388
|
var CircuitBreaker = class {
|
|
@@ -2566,17 +2812,6 @@ function close_correlation(correlator, actor) {
|
|
|
2566
2812
|
});
|
|
2567
2813
|
}
|
|
2568
2814
|
|
|
2569
|
-
// src/internal/defer-signal.ts
|
|
2570
|
-
var DeferSignal = class extends Error {
|
|
2571
|
-
/** Wall-clock time (ms since epoch) to re-visit the stream. */
|
|
2572
|
-
defer_at;
|
|
2573
|
-
constructor(defer_at) {
|
|
2574
|
-
super("reaction deferred");
|
|
2575
|
-
this.name = "DeferSignal";
|
|
2576
|
-
this.defer_at = defer_at;
|
|
2577
|
-
}
|
|
2578
|
-
};
|
|
2579
|
-
|
|
2580
2815
|
// src/internal/drain-cycle.ts
|
|
2581
2816
|
var import_node_crypto2 = require("crypto");
|
|
2582
2817
|
|
|
@@ -3423,154 +3658,6 @@ var DrainController = class {
|
|
|
3423
3658
|
}
|
|
3424
3659
|
};
|
|
3425
3660
|
|
|
3426
|
-
// src/internal/merge.ts
|
|
3427
|
-
var import_zod8 = require("zod");
|
|
3428
|
-
function base_type_name(zodType) {
|
|
3429
|
-
let t = zodType;
|
|
3430
|
-
while (typeof t.unwrap === "function") {
|
|
3431
|
-
t = t.unwrap();
|
|
3432
|
-
}
|
|
3433
|
-
return t.constructor.name;
|
|
3434
|
-
}
|
|
3435
|
-
function merge_schemas(existing, incoming, state_name) {
|
|
3436
|
-
if (existing instanceof import_zod8.ZodObject && incoming instanceof import_zod8.ZodObject) {
|
|
3437
|
-
const existing_shape = existing.shape;
|
|
3438
|
-
const incoming_shape = incoming.shape;
|
|
3439
|
-
for (const key of Object.keys(incoming_shape)) {
|
|
3440
|
-
if (key in existing_shape) {
|
|
3441
|
-
const existing_base = base_type_name(existing_shape[key]);
|
|
3442
|
-
const incoming_base = base_type_name(incoming_shape[key]);
|
|
3443
|
-
if (existing_base !== incoming_base) {
|
|
3444
|
-
throw new Error(
|
|
3445
|
-
`Schema conflict in "${state_name}": key "${key}" has type "${existing_base}" but incoming partial declares "${incoming_base}"`
|
|
3446
|
-
);
|
|
3447
|
-
}
|
|
3448
|
-
}
|
|
3449
|
-
}
|
|
3450
|
-
return existing.extend(incoming_shape);
|
|
3451
|
-
}
|
|
3452
|
-
return existing;
|
|
3453
|
-
}
|
|
3454
|
-
function merge_inits(existing, incoming) {
|
|
3455
|
-
return () => ({ ...existing(), ...incoming() });
|
|
3456
|
-
}
|
|
3457
|
-
function register_state(state2, states, actions, events) {
|
|
3458
|
-
const existing = states.get(state2.name);
|
|
3459
|
-
if (existing) {
|
|
3460
|
-
merge_into_existing(state2, existing, states, actions, events);
|
|
3461
|
-
} else {
|
|
3462
|
-
register_new_state(state2, states, actions, events);
|
|
3463
|
-
}
|
|
3464
|
-
}
|
|
3465
|
-
function register_new_state(state2, states, actions, events) {
|
|
3466
|
-
states.set(state2.name, state2);
|
|
3467
|
-
for (const name of Object.keys(state2.actions)) {
|
|
3468
|
-
if (actions[name]) throw new Error(`Duplicate action "${name}"`);
|
|
3469
|
-
actions[name] = state2;
|
|
3470
|
-
}
|
|
3471
|
-
for (const name of Object.keys(state2.events)) {
|
|
3472
|
-
if (events[name]) throw new Error(`Duplicate event "${name}"`);
|
|
3473
|
-
events[name] = { schema: state2.events[name], reactions: /* @__PURE__ */ new Map() };
|
|
3474
|
-
}
|
|
3475
|
-
}
|
|
3476
|
-
function merge_into_existing(state2, existing, states, actions, events) {
|
|
3477
|
-
for (const name of Object.keys(state2.actions)) {
|
|
3478
|
-
if (existing.actions[name] === state2.actions[name]) continue;
|
|
3479
|
-
if (actions[name]) throw new Error(`Duplicate action "${name}"`);
|
|
3480
|
-
}
|
|
3481
|
-
for (const name of Object.keys(state2.events)) {
|
|
3482
|
-
if (existing.events[name] === state2.events[name]) continue;
|
|
3483
|
-
if (existing.events[name]) {
|
|
3484
|
-
throw new Error(
|
|
3485
|
-
`Event "${name}" in state "${state2.name}" is declared with different Zod schemas across slices. Cross-slice event schemas must reference the same instance \u2014 extract a shared schema (e.g. \`export const ${name} = z.object({ ... })\` in a shared module) and import it in every slice that declares it.`
|
|
3486
|
-
);
|
|
3487
|
-
}
|
|
3488
|
-
if (events[name]) throw new Error(`Duplicate event "${name}"`);
|
|
3489
|
-
}
|
|
3490
|
-
const merged_patch = merge_patches(existing.patch, state2.patch, state2.name);
|
|
3491
|
-
const merged = {
|
|
3492
|
-
...existing,
|
|
3493
|
-
state: merge_schemas(existing.state, state2.state, state2.name),
|
|
3494
|
-
init: merge_inits(existing.init, state2.init),
|
|
3495
|
-
events: { ...existing.events, ...state2.events },
|
|
3496
|
-
actions: { ...existing.actions, ...state2.actions },
|
|
3497
|
-
patch: merged_patch,
|
|
3498
|
-
on: { ...existing.on, ...state2.on },
|
|
3499
|
-
given: { ...existing.given, ...state2.given },
|
|
3500
|
-
snap: state2.snap && existing.snap && state2.snap !== existing.snap ? (() => {
|
|
3501
|
-
throw new Error(
|
|
3502
|
-
`Duplicate snap strategy for state "${state2.name}"`
|
|
3503
|
-
);
|
|
3504
|
-
})() : state2.snap || existing.snap
|
|
3505
|
-
};
|
|
3506
|
-
states.set(state2.name, merged);
|
|
3507
|
-
for (const name of Object.keys(merged.actions)) {
|
|
3508
|
-
actions[name] = merged;
|
|
3509
|
-
}
|
|
3510
|
-
for (const name of Object.keys(state2.events)) {
|
|
3511
|
-
if (events[name]) continue;
|
|
3512
|
-
events[name] = { schema: state2.events[name], reactions: /* @__PURE__ */ new Map() };
|
|
3513
|
-
}
|
|
3514
|
-
}
|
|
3515
|
-
function merge_patches(existing, incoming, state_name) {
|
|
3516
|
-
const merged = { ...existing };
|
|
3517
|
-
for (const name of Object.keys(incoming)) {
|
|
3518
|
-
const existing_p = existing[name];
|
|
3519
|
-
const incoming_p = incoming[name];
|
|
3520
|
-
if (!existing_p) {
|
|
3521
|
-
merged[name] = incoming_p;
|
|
3522
|
-
continue;
|
|
3523
|
-
}
|
|
3524
|
-
const existing_is_default = existing_p._passthrough;
|
|
3525
|
-
const incoming_is_default = incoming_p._passthrough;
|
|
3526
|
-
if (!existing_is_default && !incoming_is_default && existing_p !== incoming_p) {
|
|
3527
|
-
throw new Error(
|
|
3528
|
-
`Duplicate custom patch for event "${name}" in state "${state_name}"`
|
|
3529
|
-
);
|
|
3530
|
-
}
|
|
3531
|
-
if (existing_is_default && !incoming_is_default) {
|
|
3532
|
-
merged[name] = incoming_p;
|
|
3533
|
-
}
|
|
3534
|
-
}
|
|
3535
|
-
return merged;
|
|
3536
|
-
}
|
|
3537
|
-
function merge_event_register(target, source) {
|
|
3538
|
-
for (const [event_name, source_reg] of Object.entries(source)) {
|
|
3539
|
-
const target_reg = target[event_name];
|
|
3540
|
-
if (!target_reg) continue;
|
|
3541
|
-
for (const [name, reaction] of source_reg.reactions) {
|
|
3542
|
-
const existing = target_reg.reactions.get(name);
|
|
3543
|
-
if (existing !== void 0 && existing !== reaction)
|
|
3544
|
-
throw new Error(
|
|
3545
|
-
`Duplicate reaction "${name}" for event "${event_name}". Reaction handlers are keyed by function name; rename one of them.`
|
|
3546
|
-
);
|
|
3547
|
-
target_reg.reactions.set(name, reaction);
|
|
3548
|
-
}
|
|
3549
|
-
}
|
|
3550
|
-
}
|
|
3551
|
-
function merge_projection(proj, events) {
|
|
3552
|
-
for (const event_name of Object.keys(proj.events)) {
|
|
3553
|
-
const proj_register = proj.events[event_name];
|
|
3554
|
-
const existing = events[event_name];
|
|
3555
|
-
if (!existing) {
|
|
3556
|
-
events[event_name] = {
|
|
3557
|
-
schema: proj_register.schema,
|
|
3558
|
-
reactions: new Map(proj_register.reactions)
|
|
3559
|
-
};
|
|
3560
|
-
} else {
|
|
3561
|
-
for (const [name, reaction] of proj_register.reactions) {
|
|
3562
|
-
let key = name;
|
|
3563
|
-
while (existing.reactions.has(key)) key = `${key}_p`;
|
|
3564
|
-
existing.reactions.set(key, reaction);
|
|
3565
|
-
}
|
|
3566
|
-
}
|
|
3567
|
-
}
|
|
3568
|
-
}
|
|
3569
|
-
var _this_ = ({ stream }) => ({
|
|
3570
|
-
source: stream,
|
|
3571
|
-
target: stream
|
|
3572
|
-
});
|
|
3573
|
-
|
|
3574
3661
|
// src/internal/reactions.ts
|
|
3575
3662
|
function finalize(lease, handled, at, error, options, logger, failed_at) {
|
|
3576
3663
|
if (!error) return { lease, handled, acked_at: at };
|
|
@@ -3627,7 +3714,12 @@ function build_handle(deps) {
|
|
|
3627
3714
|
handled++;
|
|
3628
3715
|
} catch (error) {
|
|
3629
3716
|
if (error instanceof DeferSignal)
|
|
3630
|
-
return {
|
|
3717
|
+
return {
|
|
3718
|
+
lease,
|
|
3719
|
+
handled,
|
|
3720
|
+
acked_at: at,
|
|
3721
|
+
defer: resolve_defer_at(error.when, event)
|
|
3722
|
+
};
|
|
3631
3723
|
if (error instanceof CloseSignal)
|
|
3632
3724
|
return {
|
|
3633
3725
|
lease,
|
|
@@ -3947,9 +4039,9 @@ var Act = class {
|
|
|
3947
4039
|
const aggregate = event.stream;
|
|
3948
4040
|
const config2 = this._autoclose_config;
|
|
3949
4041
|
if (!in_autoclose_window(config2.autocloseWindow, /* @__PURE__ */ new Date()))
|
|
3950
|
-
throw new DeferSignal(
|
|
3951
|
-
Date.now() + config2.autocloseCycleMinutes * 6e4
|
|
3952
|
-
);
|
|
4042
|
+
throw new DeferSignal({
|
|
4043
|
+
at: new Date(Date.now() + config2.autocloseCycleMinutes * 6e4)
|
|
4044
|
+
});
|
|
3953
4045
|
const stats = await store2().query_stats([aggregate], {
|
|
3954
4046
|
count: true,
|
|
3955
4047
|
exclude: [TOMBSTONE_EVENT]
|
|
@@ -3967,7 +4059,9 @@ var Act = class {
|
|
|
3967
4059
|
at: head.id
|
|
3968
4060
|
});
|
|
3969
4061
|
if (after_ms !== void 0)
|
|
3970
|
-
throw new DeferSignal(
|
|
4062
|
+
throw new DeferSignal({
|
|
4063
|
+
at: new Date(head.created.getTime() + after_ms)
|
|
4064
|
+
});
|
|
3971
4065
|
}
|
|
3972
4066
|
};
|
|
3973
4067
|
const key = `__autoclose_${st.name}`;
|
|
@@ -5068,41 +5162,10 @@ function act() {
|
|
|
5068
5162
|
},
|
|
5069
5163
|
withActor: () => builder,
|
|
5070
5164
|
withLane: (config2) => {
|
|
5071
|
-
|
|
5072
|
-
throw new Error(`Lane "${DEFAULT_LANE}" is reserved`);
|
|
5073
|
-
if (lanes.some((l) => l.name === config2.name))
|
|
5074
|
-
throw new Error(`Lane "${config2.name}" was already declared`);
|
|
5075
|
-
lanes.push(config2);
|
|
5165
|
+
register_lane(config2, lanes);
|
|
5076
5166
|
return builder;
|
|
5077
5167
|
},
|
|
5078
|
-
on: (event) => (
|
|
5079
|
-
do: (handler, options) => {
|
|
5080
|
-
const reaction = {
|
|
5081
|
-
handler,
|
|
5082
|
-
resolver: _this_,
|
|
5083
|
-
options: {
|
|
5084
|
-
blockOnError: options?.blockOnError ?? true,
|
|
5085
|
-
maxRetries: options?.maxRetries ?? 3,
|
|
5086
|
-
backoff: options?.backoff
|
|
5087
|
-
}
|
|
5088
|
-
};
|
|
5089
|
-
if (!handler.name)
|
|
5090
|
-
throw new Error(
|
|
5091
|
-
`Reaction handler for "${String(event)}" must be a named function`
|
|
5092
|
-
);
|
|
5093
|
-
if (registry.events[event].reactions.has(handler.name))
|
|
5094
|
-
throw new Error(
|
|
5095
|
-
`Duplicate reaction "${handler.name}" for event "${String(event)}". Reaction handlers are keyed by function name; rename one of them.`
|
|
5096
|
-
);
|
|
5097
|
-
registry.events[event].reactions.set(handler.name, reaction);
|
|
5098
|
-
return Object.assign(builder, {
|
|
5099
|
-
to(resolver) {
|
|
5100
|
-
reaction.resolver = typeof resolver === "string" ? { target: resolver } : resolver;
|
|
5101
|
-
return builder;
|
|
5102
|
-
}
|
|
5103
|
-
});
|
|
5104
|
-
}
|
|
5105
|
-
}),
|
|
5168
|
+
on: (event) => reaction_on(event, registry.events, builder),
|
|
5106
5169
|
build: (options) => {
|
|
5107
5170
|
if (!_built) {
|
|
5108
5171
|
for (const proj of pending_projections) {
|
|
@@ -5267,41 +5330,10 @@ function slice() {
|
|
|
5267
5330
|
return builder;
|
|
5268
5331
|
},
|
|
5269
5332
|
withLane: (config2) => {
|
|
5270
|
-
|
|
5271
|
-
throw new Error(`Lane "${DEFAULT_LANE}" is reserved`);
|
|
5272
|
-
if (lanes.some((l) => l.name === config2.name))
|
|
5273
|
-
throw new Error(`Lane "${config2.name}" was already declared`);
|
|
5274
|
-
lanes.push(config2);
|
|
5333
|
+
register_lane(config2, lanes);
|
|
5275
5334
|
return builder;
|
|
5276
5335
|
},
|
|
5277
|
-
on: (event) => (
|
|
5278
|
-
do: (handler, options) => {
|
|
5279
|
-
const reaction = {
|
|
5280
|
-
handler,
|
|
5281
|
-
resolver: _this_,
|
|
5282
|
-
options: {
|
|
5283
|
-
blockOnError: options?.blockOnError ?? true,
|
|
5284
|
-
maxRetries: options?.maxRetries ?? 3,
|
|
5285
|
-
backoff: options?.backoff
|
|
5286
|
-
}
|
|
5287
|
-
};
|
|
5288
|
-
if (!handler.name)
|
|
5289
|
-
throw new Error(
|
|
5290
|
-
`Reaction handler for "${String(event)}" must be a named function`
|
|
5291
|
-
);
|
|
5292
|
-
if (events[event].reactions.has(handler.name))
|
|
5293
|
-
throw new Error(
|
|
5294
|
-
`Duplicate reaction "${handler.name}" for event "${String(event)}". Reaction handlers are keyed by function name; rename one of them.`
|
|
5295
|
-
);
|
|
5296
|
-
events[event].reactions.set(handler.name, reaction);
|
|
5297
|
-
return Object.assign(builder, {
|
|
5298
|
-
to(resolver) {
|
|
5299
|
-
reaction.resolver = typeof resolver === "string" ? { target: resolver } : resolver;
|
|
5300
|
-
return builder;
|
|
5301
|
-
}
|
|
5302
|
-
});
|
|
5303
|
-
}
|
|
5304
|
-
}),
|
|
5336
|
+
on: (event) => reaction_on(event, events, builder),
|
|
5305
5337
|
build: () => ({
|
|
5306
5338
|
_tag: "Slice",
|
|
5307
5339
|
states,
|
|
@@ -5612,6 +5644,7 @@ function write_line(writer, line) {
|
|
|
5612
5644
|
DEFAULT_LANE,
|
|
5613
5645
|
DEFAULT_MAX_SUBSCRIBED_STREAMS,
|
|
5614
5646
|
DEFAULT_SETTLE_DEBOUNCE_MS,
|
|
5647
|
+
DeferSignal,
|
|
5615
5648
|
Environments,
|
|
5616
5649
|
Errors,
|
|
5617
5650
|
EventMetaSchema,
|