@state-flow/core 1.0.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.mjs ADDED
@@ -0,0 +1,1458 @@
1
+ var __typeError = (msg) => {
2
+ throw TypeError(msg);
3
+ };
4
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
7
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
8
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
9
+
10
+ // src/package-json.ts
11
+ var package_json_default = { name: "@state-flow/core", version: "1.0.0", commit: "6b8863c9d96e7ff65eaf983b247f122628b986d5", branch: "HEAD" };
12
+
13
+ // src/flow.ts
14
+ import { EventEmitter } from "events";
15
+
16
+ // src/logger.ts
17
+ var STACKTRACE_VIEWER_URL = "https://stacktrace.pirogov.dev/";
18
+ var dispatchContextProvider = null;
19
+ function setGlobalDispatchContextProvider(provider) {
20
+ dispatchContextProvider = provider;
21
+ return () => {
22
+ if (dispatchContextProvider === provider) {
23
+ dispatchContextProvider = null;
24
+ }
25
+ };
26
+ }
27
+ function getGlobalDispatchContext() {
28
+ if (dispatchContextProvider == null) {
29
+ return null;
30
+ }
31
+ try {
32
+ return dispatchContextProvider();
33
+ } catch {
34
+ return null;
35
+ }
36
+ }
37
+ var globalLogHandlers = /* @__PURE__ */ new Set();
38
+ function addGlobalLogHandler(handler) {
39
+ globalLogHandlers.add(handler);
40
+ return () => {
41
+ globalLogHandlers.delete(handler);
42
+ };
43
+ }
44
+ function withGlobalLogHandlers(handlers) {
45
+ if (globalLogHandlers.size === 0) {
46
+ return handlers;
47
+ }
48
+ return [...handlers, ...globalLogHandlers];
49
+ }
50
+ var consoleSilencedOverride = null;
51
+ function isConsoleSilenced() {
52
+ if (consoleSilencedOverride !== null) {
53
+ return consoleSilencedOverride;
54
+ }
55
+ return typeof process !== "undefined" && process.env?.VITEST != null;
56
+ }
57
+ function setConsoleLogSilenced(silenced) {
58
+ consoleSilencedOverride = silenced;
59
+ }
60
+ var consoleLogHandler = (entry) => {
61
+ if (isConsoleSilenced()) {
62
+ return;
63
+ }
64
+ const logs = {};
65
+ entry.stateChanges.reduce((l, r) => {
66
+ var _a;
67
+ l[_a = r.stateName] ?? (l[_a] = []);
68
+ l[r.stateName].push(`State: ${r.oldState} => ${r.newState}`);
69
+ return l;
70
+ }, logs);
71
+ entry.handlerResults.reduce((l, r) => {
72
+ var _a;
73
+ l[_a = r.stateName] ?? (l[_a] = []);
74
+ l[r.stateName].push(` ${r.type} ${r.handlerName}() => ${r.result}`);
75
+ return l;
76
+ }, logs);
77
+ entry.observers.reduce((l, r) => {
78
+ var _a;
79
+ l[_a = r.stateName] ?? (l[_a] = []);
80
+ l[r.stateName].push(` observed by ${r.observerName}() => ${r.needObserve}`);
81
+ return l;
82
+ }, logs);
83
+ console.groupCollapsed(entry.message);
84
+ for (const [, rows] of Object.entries(logs)) {
85
+ for (const row of rows) {
86
+ console.log(row);
87
+ }
88
+ }
89
+ if (entry.enqueuedSignals.length > 0) {
90
+ console.log("\nEnqueued Signals:");
91
+ for (const enq of entry.enqueuedSignals) {
92
+ console.log(` ${enq.signal} (from ${enq.fromHandler})`);
93
+ }
94
+ }
95
+ console.log("\nFinal States:");
96
+ Object.entries(entry.finalStates).forEach(([name, state]) => {
97
+ console.debug(` ${name}: ${state}`);
98
+ });
99
+ if (entry.stacktrace != null) {
100
+ console.log("\nStacktrace:");
101
+ console.log(`${STACKTRACE_VIEWER_URL}#${btoa(JSON.stringify(entry.stacktrace))}`);
102
+ }
103
+ console.groupEnd();
104
+ };
105
+ function emitGrouped(handlers, label, entries, context = null) {
106
+ if (entries.length === 0) {
107
+ return;
108
+ }
109
+ if (isConsoleSilenced()) {
110
+ for (const entry of entries) {
111
+ entry.groupLabel = label;
112
+ if (context != null) {
113
+ entry.dispatchContext = context;
114
+ }
115
+ for (const handler of handlers) {
116
+ handler(entry);
117
+ }
118
+ }
119
+ return;
120
+ }
121
+ console.group(context != null ? `${label} \u27F5 ${context}` : label);
122
+ try {
123
+ for (const entry of entries) {
124
+ entry.groupLabel = label;
125
+ if (context != null) {
126
+ entry.dispatchContext = context;
127
+ }
128
+ for (const handler of handlers) {
129
+ handler(entry);
130
+ }
131
+ }
132
+ } finally {
133
+ console.groupEnd();
134
+ }
135
+ }
136
+
137
+ // src/symbols.ts
138
+ var SIGNAL = /* @__PURE__ */ Symbol.for("SIGNAL");
139
+ var DEF = /* @__PURE__ */ Symbol.for("DEF");
140
+ var IS_INITIAL = /* @__PURE__ */ Symbol.for("IS_INITIAL");
141
+ var VARIANT = /* @__PURE__ */ Symbol.for("VARIANT");
142
+ var SIGNALS = /* @__PURE__ */ Symbol.for("SIGNALS");
143
+ var HANDLERS = /* @__PURE__ */ Symbol.for("HANDLERS");
144
+ var STRING_REPR = /* @__PURE__ */ Symbol.for("STRING_REPR");
145
+ var PARSER = /* @__PURE__ */ Symbol.for("PARSER");
146
+ if (typeof Symbol.dispose === "undefined") {
147
+ Object.defineProperty(Symbol, "dispose", { value: /* @__PURE__ */ Symbol.for("dispose") });
148
+ }
149
+ if (typeof Symbol.asyncDispose === "undefined") {
150
+ Object.defineProperty(Symbol, "asyncDispose", { value: /* @__PURE__ */ Symbol.for("asyncDispose") });
151
+ }
152
+
153
+ // src/utils.ts
154
+ function buildName(ctx, func) {
155
+ let fnName = null;
156
+ let ctxName = null;
157
+ if (func != null) {
158
+ fnName = Symbol.toStringTag in func && func[Symbol.toStringTag] !== "AsyncFunction" ? func[Symbol.toStringTag] : func.name;
159
+ }
160
+ if (ctx != null && typeof ctx === "object") {
161
+ ctxName = Symbol.toStringTag in ctx ? ctx[Symbol.toStringTag] : ctx.constructor.name;
162
+ }
163
+ if (ctxName == null) {
164
+ return String(fnName);
165
+ } else if (fnName == null) {
166
+ return String(ctxName);
167
+ }
168
+ if (String(fnName).startsWith(String(ctxName))) {
169
+ return String(fnName);
170
+ }
171
+ return `${ctxName}.${fnName}`;
172
+ }
173
+ var StateFlowError = class extends Error {
174
+ constructor(message, inner = null) {
175
+ super(message);
176
+ this.name = "StateFlowError";
177
+ if (inner != null) {
178
+ this.stack = inner.stack;
179
+ }
180
+ }
181
+ };
182
+ var urlRegex = /(https?:\/\/[^:]+(?::\d+)?(?:\/[^:]*)*?):(\d+):(\d+)/g;
183
+ function parseCompactStacktrace(stacktrace) {
184
+ if (stacktrace == null) {
185
+ return null;
186
+ }
187
+ const urlMap = /* @__PURE__ */ new Map();
188
+ const urls = [];
189
+ const compactFrames = [];
190
+ const matches = stacktrace.matchAll(urlRegex);
191
+ for (const match of matches) {
192
+ const [, url, lineStr, columnStr] = match;
193
+ if (!urlMap.has(url)) {
194
+ urlMap.set(url, urls.length);
195
+ urls.push(url);
196
+ }
197
+ const urlIndex = urlMap.get(url);
198
+ const line = parseInt(lineStr, 10);
199
+ const column = parseInt(columnStr, 10);
200
+ compactFrames.push([urlIndex, line, column]);
201
+ }
202
+ if (compactFrames.length === 0) {
203
+ return null;
204
+ }
205
+ return [urls, compactFrames];
206
+ }
207
+ var maxArrayItems = 10;
208
+ var maxStringLen = 25;
209
+ var abbreviate = true;
210
+ var inlineSingleArrays = true;
211
+ var maxDepth = 3;
212
+ var SPACES_REGEX = /\s/;
213
+ var BRACKETS_REGEX = /[{}[\]=]/;
214
+ function isObject(val) {
215
+ return val !== null && typeof val === "object" && !Array.isArray(val);
216
+ }
217
+ function isPlainObject(val) {
218
+ if (!isObject(val)) {
219
+ return false;
220
+ }
221
+ const proto = Object.getPrototypeOf(val);
222
+ return proto === null || proto === Object.prototype;
223
+ }
224
+ function getClassName(val) {
225
+ const proto = Object.getPrototypeOf(val);
226
+ if (proto?.constructor?.name != null) {
227
+ return proto.constructor.name;
228
+ }
229
+ return "Object";
230
+ }
231
+ function flattenPath(val, path = [], depthBudget = maxDepth) {
232
+ if (isPlainObject(val) && depthBudget > 0) {
233
+ const keys = Reflect.ownKeys(val).filter((k) => typeof k === "string");
234
+ if (keys.length === 1) {
235
+ const key = keys[0];
236
+ if (key !== void 0) {
237
+ const nextVal = Reflect.get(val, key);
238
+ return flattenPath(nextVal, [...path, key], depthBudget - 1);
239
+ }
240
+ }
241
+ }
242
+ return { path, value: val };
243
+ }
244
+ function serializeValue(val, depth = 0) {
245
+ if (val === null) {
246
+ return abbreviate ? "N" : "null";
247
+ }
248
+ if (val === void 0) {
249
+ return abbreviate ? "U" : "undefined";
250
+ }
251
+ if (typeof val === "boolean") {
252
+ return abbreviate ? val ? "T" : "F" : String(val);
253
+ }
254
+ if (typeof val === "number") {
255
+ return String(val);
256
+ }
257
+ if (typeof val === "string") {
258
+ let str = val;
259
+ if (maxStringLen && str.length > maxStringLen) {
260
+ str = `${str.slice(0, maxStringLen)}\u2026`;
261
+ }
262
+ const hasSpaces = SPACES_REGEX.test(str);
263
+ const hasSpecialChars = BRACKETS_REGEX.test(str);
264
+ if (hasSpaces || hasSpecialChars) {
265
+ return `'${str.replace(/'/g, "\\'")}'`;
266
+ }
267
+ return str;
268
+ }
269
+ if (Array.isArray(val)) {
270
+ if (inlineSingleArrays && val.length === 1) {
271
+ const first = val[0];
272
+ if (first === null || first === void 0 || typeof first === "number" || typeof first === "boolean" || typeof first === "string") {
273
+ return serializeValue(first, depth + 1);
274
+ }
275
+ }
276
+ let items = val;
277
+ let truncated = false;
278
+ if (maxArrayItems && val.length > maxArrayItems) {
279
+ items = val.slice(0, maxArrayItems);
280
+ truncated = true;
281
+ }
282
+ const serialized = items.map((item) => {
283
+ if (isPlainObject(item)) {
284
+ if (depth >= maxDepth) {
285
+ return "{...}";
286
+ }
287
+ const depthBudget = maxDepth - depth - 1;
288
+ const entries = Reflect.ownKeys(item).filter((k) => typeof k === "string").map((k) => {
289
+ const v = Reflect.get(item, k);
290
+ const { path, value } = flattenPath(v, [], depthBudget);
291
+ const fullPath = path.length > 0 ? `${k}.${path.join(".")}` : k;
292
+ return `${fullPath}=${serializeValue(value, depth + 1 + path.length)}`;
293
+ });
294
+ return entries.length === 1 ? entries[0] : `{${entries.join(" ")}}`;
295
+ }
296
+ return serializeValue(item, depth + 1);
297
+ });
298
+ const result = serialized.join(" ");
299
+ return `[${result}${truncated ? ` \u2026+${val.length - maxArrayItems}` : ""}]`;
300
+ }
301
+ if (isObject(val)) {
302
+ if (val instanceof Date) {
303
+ return val.toISOString();
304
+ }
305
+ if (Reflect.has(val, Symbol.toPrimitive) && !Reflect.has(val, VARIANT)) {
306
+ return String(val);
307
+ }
308
+ if (val instanceof Map) {
309
+ if (depth >= maxDepth) {
310
+ return `Map(${val.size}){...}`;
311
+ }
312
+ let entries2 = [...val.entries()];
313
+ const dropped = maxArrayItems ? entries2.length - maxArrayItems : 0;
314
+ if (dropped > 0) {
315
+ entries2 = entries2.slice(0, maxArrayItems);
316
+ }
317
+ const body = entries2.map(([k, v]) => `${serializeValue(k, depth + 1)}=${serializeValue(v, depth + 1)}`);
318
+ return `Map(${val.size}){${body.join(" ")}${dropped > 0 ? ` \u2026+${dropped}` : ""}}`;
319
+ }
320
+ if (val instanceof Set) {
321
+ if (depth >= maxDepth) {
322
+ return `Set(${val.size}){...}`;
323
+ }
324
+ let items = [...val.values()];
325
+ const dropped = maxArrayItems ? items.length - maxArrayItems : 0;
326
+ if (dropped > 0) {
327
+ items = items.slice(0, maxArrayItems);
328
+ }
329
+ const body = items.map((item) => serializeValue(item, depth + 1));
330
+ return `Set(${val.size}){${body.join(" ")}${dropped > 0 ? ` \u2026+${dropped}` : ""}}`;
331
+ }
332
+ if (val instanceof Error) {
333
+ let message = val.message;
334
+ if (maxStringLen && message.length > maxStringLen) {
335
+ message = `${message.slice(0, maxStringLen)}\u2026`;
336
+ }
337
+ return `${val.name}(${message})`;
338
+ }
339
+ if (val instanceof RegExp) {
340
+ return String(val);
341
+ }
342
+ if (val instanceof ArrayBuffer) {
343
+ return `ArrayBuffer(${val.byteLength})`;
344
+ }
345
+ if (ArrayBuffer.isView(val)) {
346
+ const length = val.length ?? val.byteLength;
347
+ return `${getClassName(val)}(${length})`;
348
+ }
349
+ if (typeof val.type === "string" && getClassName(val).endsWith("Event")) {
350
+ return `${getClassName(val)}(${val.type})`;
351
+ }
352
+ if (getClassName(val) === "URL" && typeof val.href === "string") {
353
+ return serializeValue(val.href, depth);
354
+ }
355
+ if (!isPlainObject(val)) {
356
+ const className = getClassName(val);
357
+ return `{${className}}`;
358
+ }
359
+ if (depth >= maxDepth) {
360
+ return "{...}";
361
+ }
362
+ const depthBudget = maxDepth - depth - 1;
363
+ const entries = Reflect.ownKeys(val).filter((k) => typeof k === "string").map((k) => {
364
+ const v = Reflect.get(val, k);
365
+ const { path, value } = flattenPath(v, [], depthBudget);
366
+ const fullPath = path.length > 0 ? `${k}.${path.join(".")}` : k;
367
+ return `${fullPath}=${serializeValue(value, depth + 1 + path.length)}`;
368
+ });
369
+ return depth === 0 ? entries.join(" ") : `{${entries.join(" ")}}`;
370
+ }
371
+ return String(val);
372
+ }
373
+ function serializeDebug(obj) {
374
+ if (obj == null) {
375
+ return "";
376
+ }
377
+ return serializeValue(obj);
378
+ }
379
+
380
+ // src/result.ts
381
+ var ResultKind = /* @__PURE__ */ ((ResultKind2) => {
382
+ ResultKind2[ResultKind2["OK"] = 0] = "OK";
383
+ ResultKind2[ResultKind2["Ignored"] = 1] = "Ignored";
384
+ ResultKind2[ResultKind2["InTransition"] = 2] = "InTransition";
385
+ ResultKind2[ResultKind2["Rejected"] = 3] = "Rejected";
386
+ ResultKind2[ResultKind2["Error"] = 4] = "Error";
387
+ return ResultKind2;
388
+ })(ResultKind || {});
389
+ var _executors, _enqueued, _promise, _expectedKinds, _timestamps, _signal, _handler, _state, _stacktrace, _meta, _Result_instances, assertExpected_fn;
390
+ var _Result = class _Result {
391
+ /**
392
+ * Internal constructor of Result
393
+ *
394
+ * @param kind
395
+ * @param data
396
+ * @param msg
397
+ * @param ts
398
+ * @private
399
+ * @internal
400
+ */
401
+ constructor(kind, data, msg, ts = Date.now()) {
402
+ this.kind = kind;
403
+ this.data = data;
404
+ this.msg = msg;
405
+ __privateAdd(this, _Result_instances);
406
+ // a list of transitioning result promises
407
+ __privateAdd(this, _executors, []);
408
+ // signals to dispatch after this result completes successfully
409
+ __privateAdd(this, _enqueued, []);
410
+ // cached promise for current result
411
+ __privateAdd(this, _promise, null);
412
+ // kinds the caller asserted via expect() on an InTransition result.
413
+ // The assertion is deferred to the FINAL resolved result and enforced in done().
414
+ __privateAdd(this, _expectedKinds, null);
415
+ // contexts for logging purposes
416
+ __privateAdd(this, _timestamps, [Date.now(), Date.now()]);
417
+ __privateAdd(this, _signal, null);
418
+ __privateAdd(this, _handler, null);
419
+ __privateAdd(this, _state, null);
420
+ __privateAdd(this, _stacktrace, null);
421
+ __privateAdd(this, _meta, null);
422
+ __privateSet(this, _timestamps, [ts, ts]);
423
+ if (kind === 2 /* InTransition */) {
424
+ __privateGet(this, _executors).push(data);
425
+ }
426
+ Object.freeze(this);
427
+ }
428
+ get startedAt() {
429
+ return __privateGet(this, _timestamps)[0];
430
+ }
431
+ get finishedAt() {
432
+ return __privateGet(this, _timestamps)[1];
433
+ }
434
+ get stacktrace() {
435
+ return __privateGet(this, _stacktrace);
436
+ }
437
+ in(...args) {
438
+ return args.includes(this.kind);
439
+ }
440
+ /**
441
+ * Returns a promise with result
442
+ * Useful for `InTransition` kind results
443
+ * For all other kinds it wraps "this" object
444
+ */
445
+ async done() {
446
+ if (this.kind === 2 /* InTransition */ && __privateGet(this, _meta)?.transitioning != null && typeof __privateGet(this, _meta).transitioning !== "boolean") {
447
+ return __privateMethod(this, _Result_instances, assertExpected_fn).call(this, await __privateGet(this, _meta).transitioning);
448
+ }
449
+ const result = await this.waitAll();
450
+ if (__privateGet(this, _meta)?.transitioning != null) {
451
+ await __privateGet(this, _meta).transitioning;
452
+ }
453
+ return __privateMethod(this, _Result_instances, assertExpected_fn).call(this, result);
454
+ }
455
+ /**
456
+ * Error object for `Error` results
457
+ * Or null for all other kinds of results
458
+ */
459
+ get error() {
460
+ if (this.msg instanceof Error) {
461
+ return this.msg;
462
+ }
463
+ return null;
464
+ }
465
+ /**
466
+ * Message string for `Ignored` or `Rejected` kinds
467
+ * Or null for all other kinds of results
468
+ */
469
+ get message() {
470
+ if (typeof this.msg === "string" && this.msg !== "") {
471
+ return this.msg;
472
+ }
473
+ return null;
474
+ }
475
+ /**
476
+ * Signals enqueued for dispatch after this result completes successfully
477
+ */
478
+ get enqueuedSignals() {
479
+ return __privateGet(this, _enqueued);
480
+ }
481
+ /**
482
+ * @internal
483
+ * @private
484
+ */
485
+ waitAll() {
486
+ if (__privateGet(this, _promise) == null) {
487
+ if (this.kind === 2 /* InTransition */) {
488
+ __privateSet(this, _promise, Promise.all(__privateGet(this, _executors)).then(mergeResults).then((res) => res.kind === 2 /* InTransition */ ? res.waitAll() : res).then((res) => res.withTimestamps(...__privateGet(this, _timestamps), Date.now())));
489
+ } else {
490
+ __privateSet(this, _promise, Promise.resolve(this));
491
+ }
492
+ }
493
+ return __privateGet(this, _promise);
494
+ }
495
+ /**
496
+ * Creates `Ignored` result with explanation message
497
+ *
498
+ * @param message explanation message
499
+ */
500
+ static ignore(message) {
501
+ return new _Result(1 /* Ignored */, null, message);
502
+ }
503
+ /**
504
+ * Creates `Ok` result without any messages
505
+ */
506
+ static ok(data = null) {
507
+ return new _Result(0 /* OK */, data, "");
508
+ }
509
+ /**
510
+ * Creates `Ok` result with a new state
511
+ * Used in a flow handlers
512
+ *
513
+ * @param data a new state
514
+ */
515
+ static state(data) {
516
+ return new _Result(0 /* OK */, data, "");
517
+ }
518
+ /**
519
+ * Creates `Ok` result that enqueues a follow-up signal for dispatch
520
+ * after the current dispatch completes successfully.
521
+ * If the enqueued signal fails, the entire chain is rolled back.
522
+ *
523
+ * @param signal - Signal to dispatch after current dispatch succeeds
524
+ */
525
+ static enqueue(signal) {
526
+ const result = new _Result(0 /* OK */, null, "");
527
+ __privateSet(result, _enqueued, [signal]);
528
+ return result;
529
+ }
530
+ /**
531
+ * Creates a new `InTransition` result with using async callback
532
+ * and timeout for executing it.
533
+ *
534
+ * @param asyncFn
535
+ * @param timeout
536
+ */
537
+ static transition(asyncFn, timeout = 500) {
538
+ const ts = Date.now();
539
+ return new _Result(
540
+ 2 /* InTransition */,
541
+ withTimeout(
542
+ asyncFn().catch((err) => _Result.error(err)),
543
+ timeout
544
+ ),
545
+ "",
546
+ ts
547
+ );
548
+ }
549
+ /**
550
+ * Creates a new `Rejected` result with explanation message
551
+ *
552
+ * @param message
553
+ */
554
+ static reject(message) {
555
+ return new _Result(3 /* Rejected */, null, message);
556
+ }
557
+ static error(error) {
558
+ if (error instanceof Error) {
559
+ return new _Result(4 /* Error */, null, error);
560
+ }
561
+ return new _Result(4 /* Error */, null, new Error(String(error)));
562
+ }
563
+ expect(...kinds) {
564
+ if (this.kind === 2 /* InTransition */) {
565
+ __privateSet(this, _expectedKinds, kinds);
566
+ return this;
567
+ }
568
+ if (!kinds.includes(this.kind)) {
569
+ throw new StateFlowError(
570
+ buildErrorMessages(this.kind, this.error, this.message, __privateGet(this, _signal), __privateGet(this, _handler), __privateGet(this, _state)),
571
+ this.error
572
+ );
573
+ }
574
+ return this;
575
+ }
576
+ /**
577
+ * @internal
578
+ */
579
+ withTimestamps(...ts) {
580
+ __privateSet(this, _timestamps, [Math.min(...ts), Math.max(...ts)]);
581
+ return this;
582
+ }
583
+ /**
584
+ * @internal
585
+ * @param signal
586
+ */
587
+ withSignal(signal) {
588
+ __privateSet(this, _signal, signal);
589
+ return this;
590
+ }
591
+ /**
592
+ * @internal
593
+ * @param name
594
+ */
595
+ withHandlerName(name) {
596
+ __privateSet(this, _handler, name);
597
+ return this;
598
+ }
599
+ withStacktrace(stack) {
600
+ __privateSet(this, _stacktrace, Array.isArray(stack) ? stack : parseCompactStacktrace(stack));
601
+ return this;
602
+ }
603
+ /**
604
+ * @internal
605
+ * @param state
606
+ */
607
+ withStateUpdating(state) {
608
+ __privateSet(this, _state, state);
609
+ return this;
610
+ }
611
+ withMeta(meta) {
612
+ __privateSet(this, _meta, meta);
613
+ return this;
614
+ }
615
+ /**
616
+ * @internal
617
+ */
618
+ withEnqueued(signals) {
619
+ __privateSet(this, _enqueued, signals);
620
+ return this;
621
+ }
622
+ /**
623
+ * @internal
624
+ * @param other
625
+ */
626
+ merge(other) {
627
+ const combinedEnqueued = [...__privateGet(this, _enqueued), ...__privateGet(other, _enqueued)];
628
+ if (this.kind === other.kind) {
629
+ switch (this.kind) {
630
+ case 1 /* Ignored */:
631
+ return _Result.ignore(mergeStrings(this.msg, other.msg)).withTimestamps(...__privateGet(this, _timestamps), ...__privateGet(other, _timestamps)).withSignal(__privateGet(this, _signal)).withHandlerName(__privateGet(this, _handler)).withStateUpdating(__privateGet(this, _state)).withStacktrace(__privateGet(this, _stacktrace)).withEnqueued(combinedEnqueued);
632
+ case 0 /* OK */:
633
+ return this.withTimestamps(...__privateGet(this, _timestamps), ...__privateGet(other, _timestamps)).withEnqueued(combinedEnqueued);
634
+ case 2 /* InTransition */:
635
+ __privateGet(this, _executors).push(...__privateGet(other, _executors));
636
+ __privateSet(this, _enqueued, combinedEnqueued);
637
+ return this;
638
+ case 3 /* Rejected */:
639
+ return this.withTimestamps(...__privateGet(this, _timestamps), ...__privateGet(other, _timestamps)).withEnqueued(combinedEnqueued);
640
+ case 4 /* Error */: {
641
+ const msg = [this.data, other.data].filter((m) => m !== "").map((e) => String(e)).filter((m) => m !== "").join("; ");
642
+ return _Result.error(new StateFlowError(msg)).withTimestamps(...__privateGet(this, _timestamps), ...__privateGet(other, _timestamps)).withSignal(__privateGet(this, _signal)).withHandlerName(__privateGet(this, _handler)).withStateUpdating(__privateGet(this, _state)).withStacktrace(__privateGet(this, _stacktrace)).withEnqueued(combinedEnqueued);
643
+ }
644
+ default:
645
+ throw new Error(`unknown state result: ${this.kind}`);
646
+ }
647
+ }
648
+ const choose = (a, b) => {
649
+ switch (a.kind) {
650
+ case 1 /* Ignored */:
651
+ return b;
652
+ case 2 /* InTransition */:
653
+ __privateGet(a, _executors).push(b.waitAll());
654
+ return a;
655
+ case 3 /* Rejected */:
656
+ case 4 /* Error */:
657
+ return a;
658
+ default:
659
+ return null;
660
+ }
661
+ };
662
+ return (choose(this, other) ?? choose(other, this) ?? this).withTimestamps(...__privateGet(this, _timestamps), ...__privateGet(other, _timestamps)).withSignal(__privateGet(this, _signal)).withHandlerName(__privateGet(this, _handler)).withStateUpdating(__privateGet(this, _state)).withStacktrace(__privateGet(this, _stacktrace)).withEnqueued(combinedEnqueued);
663
+ }
664
+ [Symbol.toStringTag]() {
665
+ if (__privateGet(this, _enqueued).length > 0) {
666
+ return `Result.Enqueue(${__privateGet(this, _enqueued).map(String).join(", ")})`;
667
+ }
668
+ return `Result.${ResultKind[this.kind]}()`;
669
+ }
670
+ [Symbol.toPrimitive]() {
671
+ if (__privateGet(this, _enqueued).length > 0) {
672
+ return `Enqueue(${__privateGet(this, _enqueued).map(String).join(", ")})`;
673
+ }
674
+ if (this.kind === 4 /* Error */) {
675
+ return this.error != null ? String(this.error) : ResultKind[this.kind];
676
+ }
677
+ return `${ResultKind[this.kind]}${this.message != null ? `: ${this.message}` : ""}`;
678
+ }
679
+ };
680
+ _executors = new WeakMap();
681
+ _enqueued = new WeakMap();
682
+ _promise = new WeakMap();
683
+ _expectedKinds = new WeakMap();
684
+ _timestamps = new WeakMap();
685
+ _signal = new WeakMap();
686
+ _handler = new WeakMap();
687
+ _state = new WeakMap();
688
+ _stacktrace = new WeakMap();
689
+ _meta = new WeakMap();
690
+ _Result_instances = new WeakSet();
691
+ /**
692
+ * Applies a previously-stored expect() assertion (from an InTransition
693
+ * result) to the FINAL resolved result. Throws if the final kind is not
694
+ * allowed. No-op when no expectation was registered.
695
+ * @internal
696
+ */
697
+ assertExpected_fn = function(final) {
698
+ if (__privateGet(this, _expectedKinds) == null) {
699
+ return final;
700
+ }
701
+ if (!__privateGet(this, _expectedKinds).includes(final.kind)) {
702
+ throw new StateFlowError(
703
+ buildErrorMessages(
704
+ final.kind,
705
+ final.error,
706
+ final.message,
707
+ __privateGet(final, _signal) ?? __privateGet(this, _signal),
708
+ __privateGet(final, _handler) ?? __privateGet(this, _handler),
709
+ __privateGet(final, _state) ?? __privateGet(this, _state)
710
+ ),
711
+ final.error
712
+ );
713
+ }
714
+ return final;
715
+ };
716
+ var Result = _Result;
717
+ function mergeStrings(a, b) {
718
+ if (a == null && b == null) {
719
+ return "";
720
+ }
721
+ if (a == null || a === "") {
722
+ return String(b);
723
+ }
724
+ if (b == null || b === "") {
725
+ return String(a);
726
+ }
727
+ return `${a}; ${b}`;
728
+ }
729
+ function withTimeout(promise, timeout) {
730
+ return new Promise((resolve, reject) => {
731
+ const timer = setTimeout(() => {
732
+ resolve(Result.error(new Error("timeout")));
733
+ }, timeout);
734
+ promise.then(
735
+ (res) => {
736
+ clearTimeout(timer);
737
+ resolve(res);
738
+ },
739
+ (err) => {
740
+ clearTimeout(timer);
741
+ reject(err);
742
+ }
743
+ );
744
+ });
745
+ }
746
+ function buildErrorMessages(got, error, message, signal = null, handler = null, stateUpd = null) {
747
+ let msg;
748
+ if (signal != null) {
749
+ msg = `[SF] Signal '${String(signal)}' `;
750
+ } else {
751
+ msg = "[SF] Result ";
752
+ }
753
+ if (handler != null) {
754
+ msg += `in handler '${handler}()' `;
755
+ }
756
+ switch (got) {
757
+ case 3 /* Rejected */:
758
+ msg += "was rejected";
759
+ break;
760
+ case 4 /* Error */:
761
+ msg += "thrown an error";
762
+ break;
763
+ case 2 /* InTransition */:
764
+ msg += "was in transition";
765
+ break;
766
+ case 0 /* OK */:
767
+ msg += "was ok";
768
+ break;
769
+ default:
770
+ msg += "was ignored";
771
+ }
772
+ if (stateUpd != null) {
773
+ msg += ` while tried to ${stateUpd}`;
774
+ }
775
+ if (error != null) {
776
+ msg += `: ${error}`;
777
+ }
778
+ if (message != null) {
779
+ msg += `: Message: ${message}`;
780
+ }
781
+ return msg;
782
+ }
783
+ var dispatchCounter = 0;
784
+ var ResultCollector = class {
785
+ constructor(flowName, signal, duringTransition = false) {
786
+ this.results = [];
787
+ this.entry = {
788
+ message: "",
789
+ flowName,
790
+ signal: String(signal),
791
+ isAsync: false,
792
+ startTime: Date.now(),
793
+ dispatchOrder: ++dispatchCounter,
794
+ finalStates: {},
795
+ stateChanges: [],
796
+ handlerResults: [],
797
+ observers: [],
798
+ enqueuedSignals: [],
799
+ stacktrace: null,
800
+ finalResult: ""
801
+ };
802
+ if (duringTransition) {
803
+ this.entry.duringTransition = true;
804
+ }
805
+ }
806
+ merge() {
807
+ if (this.results.length === 1 && this.results[0] != null) {
808
+ return this.results[0];
809
+ }
810
+ const final = mergeResults(this.results);
811
+ this.results = [final];
812
+ return final;
813
+ }
814
+ push(val) {
815
+ const res = val instanceof Result ? val : Result.error(val);
816
+ this.results.push(res);
817
+ }
818
+ logStateChange(stateName, oldState, newState) {
819
+ this.entry.stateChanges.push({
820
+ stateName,
821
+ oldState: String(oldState),
822
+ newState: String(newState)
823
+ });
824
+ }
825
+ logHandler(stateName, type, handlerName, result) {
826
+ this.entry.handlerResults.push({
827
+ type,
828
+ handlerName,
829
+ stateName,
830
+ result: String(result)
831
+ });
832
+ }
833
+ logEnqueue(signal, handlerName) {
834
+ this.entry.enqueuedSignals.push({ signal, fromHandler: handlerName });
835
+ }
836
+ logObserver(stateName, observerName, needObserve) {
837
+ this.entry.observers.push({
838
+ stateName,
839
+ observerName,
840
+ needObserve
841
+ });
842
+ }
843
+ async finish(snapshot, result) {
844
+ this.entry.stacktrace = result.stacktrace;
845
+ let finalResult = result;
846
+ if (result.kind === 2 /* InTransition */) {
847
+ const startTime = this.entry.startTime;
848
+ finalResult = await result.waitAll();
849
+ this.entry.isAsync = true;
850
+ this.entry.duration = Date.now() - startTime;
851
+ }
852
+ this.entry.finalStates = Object.fromEntries(Object.entries(snapshot).map(([k, v]) => [k, String(v)]));
853
+ this.entry.finalResult = String(finalResult);
854
+ const timing = this.entry.duration != null ? `[${this.entry.duration}ms] ` : "";
855
+ const stale = this.entry.duringTransition ? "(during transition) " : "";
856
+ this.entry.message = `[SF/${this.entry.flowName}] ${this.entry.signal} - ${this.entry.isAsync ? "async " : ""}${timing}${stale}${this.entry.finalResult}`;
857
+ return this.entry;
858
+ }
859
+ };
860
+ function mergeResults(results, ignoreMessage = "") {
861
+ return results.reduce((l, r) => r.merge(l), Result.ignore(ignoreMessage));
862
+ }
863
+
864
+ // src/state.ts
865
+ function isState(state) {
866
+ return typeof state === "object" && state != null && VARIANT in state;
867
+ }
868
+ function isStateDef(obj) {
869
+ return obj != null && typeof obj === "function" && SIGNALS in obj;
870
+ }
871
+ function isStateInstance(obj, name) {
872
+ if (obj == null || typeof obj !== "object" || !(VARIANT in obj) || !(Symbol.toStringTag in obj)) {
873
+ return false;
874
+ }
875
+ return String(obj[Symbol.toStringTag]).startsWith(name);
876
+ }
877
+ function stateAccepts(state, signalName) {
878
+ return signalName in state[VARIANT][HANDLERS];
879
+ }
880
+ function stateVar(obj) {
881
+ if (obj == null || typeof obj !== "object" || !(VARIANT in obj)) {
882
+ throw new StateFlowError("Not a state");
883
+ }
884
+ return obj[VARIANT];
885
+ }
886
+ function getInitialState(def) {
887
+ const svar = Object.values(def).find((x) => x[IS_INITIAL]);
888
+ if (svar == null) {
889
+ throw new StateFlowError("Initial state variant not found");
890
+ }
891
+ return svar;
892
+ }
893
+ function getName(def) {
894
+ return def[Symbol.toStringTag];
895
+ }
896
+ function factory(value, props) {
897
+ const name = String(value);
898
+ const inst = value[DEF][PARSER](props);
899
+ Object.defineProperties(inst, {
900
+ [Symbol.toStringTag]: { value: name, writable: false, configurable: false, enumerable: false },
901
+ [Symbol.toPrimitive]: {
902
+ value: () => `${name}(${value[DEF][STRING_REPR](inst)})`,
903
+ writable: false,
904
+ configurable: false,
905
+ enumerable: false
906
+ },
907
+ [VARIANT]: { value, writable: false, configurable: false, enumerable: false }
908
+ });
909
+ return Object.freeze(inst);
910
+ }
911
+ function extract(name, ctx) {
912
+ if (ctx == null || typeof ctx !== "object" || !(name in ctx)) {
913
+ throw new StateFlowError("State Flow object not found");
914
+ }
915
+ const state = Reflect.get(ctx, name);
916
+ if (!isStateInstance(state, name)) {
917
+ throw new StateFlowError(`State not found: ${name}`);
918
+ }
919
+ return state;
920
+ }
921
+ var _signals, _variants, _parser, _stringRepr, _name;
922
+ var StateBuilder = class {
923
+ constructor() {
924
+ __privateAdd(this, _signals);
925
+ __privateAdd(this, _variants, []);
926
+ __privateAdd(this, _parser, (v) => ({ ...v }));
927
+ __privateAdd(this, _stringRepr, (v) => serializeDebug(v));
928
+ __privateAdd(this, _name, "");
929
+ }
930
+ name(name) {
931
+ const self = this;
932
+ __privateSet(self, _name, name);
933
+ return self;
934
+ }
935
+ signals(signals) {
936
+ const self = this;
937
+ __privateSet(self, _signals, signals);
938
+ return self;
939
+ }
940
+ variant(variant, isInitial = false) {
941
+ const self = this;
942
+ if (isInitial && __privateGet(self, _variants).some(([_, i]) => i)) {
943
+ throw new StateFlowError("Only one initial state variant is allowed");
944
+ }
945
+ __privateGet(self, _variants).push([variant, isInitial]);
946
+ return self;
947
+ }
948
+ parser(func) {
949
+ __privateSet(this, _parser, func);
950
+ return this;
951
+ }
952
+ stringRepr(func) {
953
+ __privateSet(this, _stringRepr, func);
954
+ return this;
955
+ }
956
+ build() {
957
+ const signals = __privateGet(this, _signals);
958
+ const name = __privateGet(this, _name);
959
+ if (signals == null) {
960
+ throw new StateFlowError("Signals were not provided");
961
+ }
962
+ if (name === "") {
963
+ throw new StateFlowError("Name was not provided");
964
+ }
965
+ if (__privateGet(this, _variants).length === 0) {
966
+ throw new StateFlowError("No state variants are defined");
967
+ }
968
+ const def = extract.bind(null, name);
969
+ Object.assign(def, Object.fromEntries(__privateGet(this, _variants).map(([v, i]) => this.buildFactories(def, v, i))));
970
+ Object.defineProperties(def, {
971
+ [Symbol.toStringTag]: { value: __privateGet(this, _name), enumerable: false, configurable: false, writable: false },
972
+ [Symbol.toPrimitive]: { value: () => __privateGet(this, _name), enumerable: false, configurable: false, writable: false },
973
+ [SIGNALS]: { value: signals, enumerable: false, configurable: false, writable: false },
974
+ [PARSER]: { value: __privateGet(this, _parser), enumerable: false, configurable: false, writable: false },
975
+ [STRING_REPR]: { value: __privateGet(this, _stringRepr), enumerable: false, configurable: false, writable: false }
976
+ });
977
+ return Object.freeze(def);
978
+ }
979
+ buildFactories(def, variant, isInitial) {
980
+ const fn = Object.defineProperties(
981
+ function stateFactory(props) {
982
+ return factory(fn, props);
983
+ },
984
+ {
985
+ [Symbol.toStringTag]: { value: variant, enumerable: false, writable: false, configurable: false },
986
+ [Symbol.toPrimitive]: {
987
+ value: () => `${String(def)}.${String(variant)}`,
988
+ enumerable: false,
989
+ writable: false,
990
+ configurable: false
991
+ },
992
+ [DEF]: { value: def, enumerable: false, writable: false, configurable: false },
993
+ [HANDLERS]: { value: {}, enumerable: false, writable: false, configurable: false },
994
+ [IS_INITIAL]: { value: isInitial, enumerable: false, writable: false, configurable: false }
995
+ }
996
+ );
997
+ return [variant, fn];
998
+ }
999
+ };
1000
+ _signals = new WeakMap();
1001
+ _variants = new WeakMap();
1002
+ _parser = new WeakMap();
1003
+ _stringRepr = new WeakMap();
1004
+ _name = new WeakMap();
1005
+ function defineState() {
1006
+ return new StateBuilder();
1007
+ }
1008
+ function defineFlow(state, handlers) {
1009
+ if (Object.isFrozen(state[HANDLERS])) {
1010
+ throw new StateFlowError(`Flow is already defined: ${String(state)}`);
1011
+ }
1012
+ Object.assign(state[HANDLERS], handlers);
1013
+ Object.freeze(state[HANDLERS]);
1014
+ }
1015
+ function handleSignal(state, signal, ctx) {
1016
+ const signalName = signal[Symbol.toStringTag];
1017
+ if (!stateAccepts(state, signalName)) {
1018
+ return Result.ignore("");
1019
+ }
1020
+ const handler = state[VARIANT][HANDLERS][signalName];
1021
+ try {
1022
+ const result = handler(state, signal, ctx);
1023
+ if (result instanceof Result) {
1024
+ return result;
1025
+ }
1026
+ if (isState(result)) {
1027
+ return Result.state(result);
1028
+ }
1029
+ return Result.state(state[VARIANT](result));
1030
+ } catch (err) {
1031
+ return Result.error(err);
1032
+ }
1033
+ }
1034
+
1035
+ // src/flow.ts
1036
+ var managementStateMap = /* @__PURE__ */ new WeakMap();
1037
+ var observersMap = /* @__PURE__ */ new WeakMap();
1038
+ var currentRC = {
1039
+ ref: null,
1040
+ set(rc) {
1041
+ this.ref = rc;
1042
+ },
1043
+ clear() {
1044
+ this.ref = null;
1045
+ }
1046
+ };
1047
+ function eventKey(kind, state) {
1048
+ return `${kind}:${state}`;
1049
+ }
1050
+ function stateMeta(target) {
1051
+ const meta = managementStateMap.get(target);
1052
+ if (meta == null) {
1053
+ throw new StateFlowError(`${buildName(target)} doesn't contains state flows`);
1054
+ }
1055
+ return meta;
1056
+ }
1057
+ function addStateHandler(emitter, kind, stateVar2, cb, ctx) {
1058
+ const wrapper = (state, snapshot, stateUpd, collector) => {
1059
+ const handlerName = buildName(ctx, cb);
1060
+ try {
1061
+ const res = cb.apply(ctx, [state, snapshot]);
1062
+ if (!(res instanceof Result)) {
1063
+ throw new StateFlowError(`Handler '${handlerName}' returned not result`);
1064
+ }
1065
+ collector?.logHandler(String(stateVar2[DEF]), kind, handlerName, res);
1066
+ collector?.push(res.withHandlerName(handlerName).withStateUpdating(stateUpd));
1067
+ } catch (err) {
1068
+ collector?.logHandler(String(stateVar2[DEF]), kind, handlerName, err);
1069
+ collector?.push(Result.error(err).withHandlerName(handlerName).withStateUpdating(stateUpd));
1070
+ }
1071
+ };
1072
+ emitter.on(eventKey(kind, String(stateVar2)), wrapper);
1073
+ }
1074
+ function applyFlow(target, states, initializer, config = {}) {
1075
+ for (const def of states) {
1076
+ if (!isStateDef(def)) {
1077
+ throw new StateFlowError("Incorrect state definition");
1078
+ }
1079
+ const name = getName(def);
1080
+ const st = target[name];
1081
+ if (st == null) {
1082
+ throw new StateFlowError(`State object ${name} not found`);
1083
+ }
1084
+ Object.defineProperty(target, name, { value: getInitialState(def)(st) });
1085
+ }
1086
+ const logHandlers = config.logHandlers?.length ? config.logHandlers : [consoleLogHandler];
1087
+ const emitter = new EventEmitter();
1088
+ managementStateMap.set(target, {
1089
+ emitter,
1090
+ logHandlers,
1091
+ states,
1092
+ transitioning: null,
1093
+ lockHolder: null,
1094
+ lockQueue: [],
1095
+ logGroup: null,
1096
+ name: String(Symbol.toStringTag in target ? target[Symbol.toStringTag] : target.constructor.name)
1097
+ });
1098
+ initializer({
1099
+ addEnterHandler: addStateHandler.bind(null, emitter, "enter"),
1100
+ addUpdateHandler: addStateHandler.bind(null, emitter, "update"),
1101
+ addExitHandler: addStateHandler.bind(null, emitter, "exit"),
1102
+ addRollbackHandler: addStateHandler.bind(null, emitter, "rollback")
1103
+ });
1104
+ }
1105
+ function prepareSnapshot(target) {
1106
+ const meta = managementStateMap.get(target);
1107
+ if (meta == null) {
1108
+ return {};
1109
+ }
1110
+ return Object.fromEntries(
1111
+ meta.states.map((s) => [s[Symbol.toStringTag], Reflect.get(target, s[Symbol.toStringTag])])
1112
+ );
1113
+ }
1114
+ function dispatch(target, signal, mute = false) {
1115
+ const meta = stateMeta(target);
1116
+ if (meta.lockHolder != null) {
1117
+ throw new StateFlowError("Lock is held. Use `await using send = lock(target)` for queued access");
1118
+ }
1119
+ if (meta.transitioning != null) {
1120
+ throw new StateFlowError("States are in transitioning. Use `await sync(obj)` or await a previous result");
1121
+ }
1122
+ const chainSnapshot = prepareSnapshot(target);
1123
+ const result = dispatchCore(target, signal, meta, mute);
1124
+ return processEnqueueChain(target, result, meta, chainSnapshot, mute);
1125
+ }
1126
+ async function lock(target, label) {
1127
+ const meta = stateMeta(target);
1128
+ const id = /* @__PURE__ */ Symbol("lock");
1129
+ const dispatchContext = label != null ? getGlobalDispatchContext() : null;
1130
+ const lockRequestedAt = dispatchContext != null ? Date.now() : 0;
1131
+ if (meta.lockHolder != null || meta.lockQueue.length > 0) {
1132
+ await new Promise((resolve) => meta.lockQueue.push({ id, resolve }));
1133
+ } else {
1134
+ meta.lockHolder = id;
1135
+ }
1136
+ await sync(target);
1137
+ if (label != null) {
1138
+ const lockWaitMs = dispatchContext != null ? Date.now() - lockRequestedAt : 0;
1139
+ const context = dispatchContext != null && lockWaitMs >= 5 ? `${dispatchContext} [lock ${lockWaitMs}ms]` : dispatchContext;
1140
+ meta.logGroup = { label, pending: [], context };
1141
+ }
1142
+ let chainSnapshot = null;
1143
+ const dispose = async () => {
1144
+ if (meta.lockHolder !== id) {
1145
+ return;
1146
+ }
1147
+ if (meta.transitioning instanceof Promise) {
1148
+ await meta.transitioning;
1149
+ }
1150
+ chainSnapshot = null;
1151
+ const group = meta.logGroup;
1152
+ if (group != null) {
1153
+ meta.logGroup = null;
1154
+ const settled = await Promise.allSettled(group.pending);
1155
+ const entries = [];
1156
+ for (const outcome of settled) {
1157
+ if (outcome.status === "fulfilled") {
1158
+ entries.push(outcome.value);
1159
+ }
1160
+ }
1161
+ emitGrouped(withGlobalLogHandlers(meta.logHandlers), group.label, entries, group.context);
1162
+ }
1163
+ const next = meta.lockQueue.shift();
1164
+ if (next) {
1165
+ meta.lockHolder = next.id;
1166
+ next.resolve();
1167
+ } else {
1168
+ meta.lockHolder = null;
1169
+ }
1170
+ };
1171
+ const send = Object.assign(
1172
+ (signal, mute = false) => {
1173
+ if (meta.lockHolder !== id) {
1174
+ throw new StateFlowError("Lock has been released");
1175
+ }
1176
+ if (chainSnapshot == null) {
1177
+ chainSnapshot = prepareSnapshot(target);
1178
+ }
1179
+ const result = dispatchCore(target, signal, meta, mute);
1180
+ return processEnqueueChain(target, result, meta, chainSnapshot, mute);
1181
+ },
1182
+ { [Symbol.asyncDispose]: dispose }
1183
+ );
1184
+ return send;
1185
+ }
1186
+ function dispatchCore(target, signal, meta, mute) {
1187
+ const st = new Error().stack;
1188
+ const collector = new ResultCollector(meta.name, signal, meta.transitioning != null);
1189
+ let result = Result.ignore("");
1190
+ let snapshot = prepareSnapshot(target);
1191
+ try {
1192
+ result = prepareStatesAfterSignal(target, signal, meta.states, collector);
1193
+ if (!result.in(0 /* OK */) || result.data == null) {
1194
+ return result.withSignal(signal).withStacktrace(st ?? null);
1195
+ }
1196
+ const processResult = result.data;
1197
+ snapshot = processResult.snapshot;
1198
+ for (const kind of ["exit", "update", "enter"]) {
1199
+ processHandlers(kind, meta.emitter, processResult[kind], snapshot, collector);
1200
+ result = collector.merge();
1201
+ if (result.in(3 /* Rejected */, 4 /* Error */)) {
1202
+ processHandlers("rollback", meta.emitter, processResult.rollback, prepareSnapshot(target), collector);
1203
+ return result.withSignal(signal).withStacktrace(st ?? null);
1204
+ }
1205
+ }
1206
+ result = result.merge(Result.ok());
1207
+ for (const enqueued of result.enqueuedSignals) {
1208
+ collector.logEnqueue(String(enqueued), result.message ?? "handler");
1209
+ }
1210
+ if (result.enqueuedSignals.length > 1) {
1211
+ console.warn(
1212
+ `[SF/${meta.name}] ${String(signal)}: ${result.enqueuedSignals.length} signals were enqueued in a single dispatch cycle by different handlers (${result.enqueuedSignals.map(String).join(", ")}). Only ONE enqueue per cycle (the self-terminating record chain) is supported; co-enqueuing from multiple handlers is unsupported and may not behave as expected.`
1213
+ );
1214
+ }
1215
+ if (result.kind !== 2 /* InTransition */) {
1216
+ meta.transitioning = true;
1217
+ applyState(target, snapshot, collector);
1218
+ } else {
1219
+ meta.transitioning = result.withMeta(meta).waitAll().then((res) => {
1220
+ meta.transitioning = null;
1221
+ if (res.kind === 0 /* OK */) {
1222
+ const preTransitionSnap = res.enqueuedSignals.length > 0 ? prepareSnapshot(target) : null;
1223
+ applyState(target, snapshot, collector);
1224
+ if (preTransitionSnap && res.enqueuedSignals.length > 0) {
1225
+ const enqResult = processEnqueueChain(target, res, meta, preTransitionSnap, mute);
1226
+ if (enqResult.in(3 /* Rejected */, 4 /* Error */)) {
1227
+ return enqResult;
1228
+ }
1229
+ }
1230
+ } else if (res.in(3 /* Rejected */, 4 /* Error */)) {
1231
+ processHandlers("rollback", meta.emitter, processResult.rollback, prepareSnapshot(target), collector);
1232
+ }
1233
+ return res;
1234
+ });
1235
+ }
1236
+ return result.withMeta(meta).withSignal(signal).withStacktrace(st ?? null);
1237
+ } finally {
1238
+ if (meta.transitioning === true) {
1239
+ meta.transitioning = null;
1240
+ }
1241
+ if (!mute) {
1242
+ const finished = collector.finish(snapshot, result);
1243
+ const group = meta.logGroup;
1244
+ if (group != null) {
1245
+ group.pending.push(finished);
1246
+ } else {
1247
+ finished.then((entry) => {
1248
+ withGlobalLogHandlers(meta.logHandlers).forEach((handler) => {
1249
+ handler(entry);
1250
+ });
1251
+ }).catch(() => {
1252
+ });
1253
+ }
1254
+ }
1255
+ }
1256
+ }
1257
+ function processEnqueueChain(target, result, meta, chainSnapshot, mute) {
1258
+ let current = result;
1259
+ while (current.enqueuedSignals.length > 0) {
1260
+ const signals = [...current.enqueuedSignals];
1261
+ for (const signal of signals) {
1262
+ const enqResult = dispatchCore(target, signal, meta, mute);
1263
+ if (enqResult.in(3 /* Rejected */, 4 /* Error */)) {
1264
+ rollbackToSnapshot(target, chainSnapshot);
1265
+ return enqResult;
1266
+ }
1267
+ current = enqResult;
1268
+ }
1269
+ }
1270
+ return current;
1271
+ }
1272
+ function rollbackToSnapshot(target, snapshot) {
1273
+ for (const [key, value] of Object.entries(snapshot)) {
1274
+ Reflect.set(target, key, value);
1275
+ }
1276
+ }
1277
+ function prepareStatesAfterSignal(target, signal, states, collector) {
1278
+ const processResult = {
1279
+ snapshot: Object.fromEntries(states.map((s) => [s[Symbol.toStringTag], s(target)])),
1280
+ enter: [],
1281
+ update: [],
1282
+ exit: [],
1283
+ rollback: []
1284
+ };
1285
+ const results = [];
1286
+ const unhandled = [];
1287
+ for (const def of states) {
1288
+ const name = getName(def);
1289
+ const oldState = def(target);
1290
+ if (!stateAccepts(oldState, signal[Symbol.toStringTag])) {
1291
+ unhandled.push(String(oldState[Symbol.toStringTag]));
1292
+ }
1293
+ const result = handleSignal(oldState, signal, processResult.snapshot);
1294
+ switch (result.kind) {
1295
+ // state was successfully changed
1296
+ case 0 /* OK */: {
1297
+ const newState = result.data;
1298
+ const desc = `'${oldState}->${newState}'`;
1299
+ processResult.snapshot[name] = newState;
1300
+ collector.logStateChange(def[Symbol.toStringTag], oldState, newState);
1301
+ if (newState[VARIANT] === oldState[VARIANT]) {
1302
+ processResult.update.push([newState, `update ${desc}`]);
1303
+ } else {
1304
+ processResult.enter.push([newState, `enter to ${desc}`]);
1305
+ processResult.exit.push([oldState, `exit from ${desc}`]);
1306
+ }
1307
+ processResult.rollback.push([oldState, `rollback ${desc}`]);
1308
+ break;
1309
+ }
1310
+ // the signal was ignored completely
1311
+ case 1 /* Ignored */:
1312
+ processResult.snapshot[name] = oldState;
1313
+ break;
1314
+ // got incorrect result
1315
+ case 2 /* InTransition */:
1316
+ return Result.error(new StateFlowError("Transition is not allowed in flow handlers")).withSignal(
1317
+ signal
1318
+ );
1319
+ // Error or Rejected are left
1320
+ default:
1321
+ return result;
1322
+ }
1323
+ results.push(result);
1324
+ }
1325
+ const final = mergeResults(results);
1326
+ if (final.kind !== 0 /* OK */) {
1327
+ if (final.kind === 1 /* Ignored */ && final.message == null && unhandled.length === states.length) {
1328
+ return Result.ignore(`no handler in ${unhandled.join(", ")}`);
1329
+ }
1330
+ return final;
1331
+ }
1332
+ return Result.ok(processResult);
1333
+ }
1334
+ function applyState(target, snapshot, rc) {
1335
+ const meta = stateMeta(target);
1336
+ currentRC.set(rc);
1337
+ for (const [key, value] of Object.entries(snapshot)) {
1338
+ if (value !== Reflect.get(target, key)) {
1339
+ meta.emitter.emit(eventKey("observe", String(value[VARIANT])), Reflect.get(target, key), value);
1340
+ Reflect.set(target, key, value);
1341
+ }
1342
+ }
1343
+ currentRC.clear();
1344
+ }
1345
+ function processHandlers(kind, emitter, states, snapshot, collector) {
1346
+ for (const [state, desc] of states) {
1347
+ const key = eventKey(kind, String(state[VARIANT]));
1348
+ emitter.emit(key, snapshot[state[VARIANT][DEF][Symbol.toStringTag]], snapshot, desc, collector);
1349
+ }
1350
+ }
1351
+ async function sync(target) {
1352
+ const meta = stateMeta(target);
1353
+ const transitioning = meta.transitioning;
1354
+ if (transitioning instanceof Promise) {
1355
+ return new Promise((r) => {
1356
+ const wait = () => {
1357
+ if (meta.transitioning == null) {
1358
+ r();
1359
+ return;
1360
+ }
1361
+ transitioning.finally(() => setTimeout(wait, 0)).catch(() => {
1362
+ });
1363
+ };
1364
+ wait();
1365
+ });
1366
+ }
1367
+ }
1368
+ function observe(target, stateVariants, handlerFn, compareFn = (a, b) => a !== b, ctx) {
1369
+ const meta = stateMeta(target);
1370
+ for (const stateVar2 of stateVariants) {
1371
+ subscribe(meta.emitter, stateVar2, compareFn, handlerFn, ctx);
1372
+ }
1373
+ return {
1374
+ [Symbol.dispose]: () => {
1375
+ for (const stateVar2 of stateVariants) {
1376
+ unsubscribe(meta.emitter, stateVar2, handlerFn);
1377
+ }
1378
+ }
1379
+ };
1380
+ }
1381
+ function subscribe(emitter, stateVar2, cmpFn, hdlFn, ctx) {
1382
+ const key = eventKey("observe", String(stateVar2));
1383
+ const cb = (a, b) => {
1384
+ const needObserve = cmpFn(a, b);
1385
+ currentRC.ref?.logObserver(String(stateVar2[DEF]), buildName(ctx, hdlFn), needObserve);
1386
+ if (needObserve) {
1387
+ setTimeout(() => hdlFn(b), 0);
1388
+ }
1389
+ };
1390
+ emitter.on(key, cb);
1391
+ observersMap.set(hdlFn, [...observersMap.get(hdlFn) ?? [], cb]);
1392
+ }
1393
+ function unsubscribe(emitter, stateVar2, hdlFn) {
1394
+ const key = eventKey("observe", String(stateVar2));
1395
+ const cbs = observersMap.get(hdlFn);
1396
+ cbs?.forEach((cb) => {
1397
+ emitter.off(key, cb);
1398
+ });
1399
+ }
1400
+ function disposeFlow(target) {
1401
+ const meta = stateMeta(target);
1402
+ meta.emitter.removeAllListeners();
1403
+ Reflect.deleteProperty(meta, "emitter");
1404
+ for (const state of meta.states) {
1405
+ Reflect.deleteProperty(target, state[Symbol.toStringTag]);
1406
+ }
1407
+ }
1408
+
1409
+ // src/signal.ts
1410
+ function defineSignal(name, stringRepr = (args) => serializeDebug(args)) {
1411
+ const fn = (p) => {
1412
+ return Object.freeze({
1413
+ ...p,
1414
+ [SIGNAL]: true,
1415
+ [Symbol.toStringTag]: name,
1416
+ [Symbol.toPrimitive]: () => `${name}{${stringRepr(p)}}`
1417
+ });
1418
+ };
1419
+ Reflect.defineProperty(fn, Symbol.toStringTag, {
1420
+ value: name,
1421
+ writable: false,
1422
+ configurable: false,
1423
+ enumerable: false
1424
+ });
1425
+ return fn;
1426
+ }
1427
+
1428
+ // src/index.ts
1429
+ globalThis.__STATE_FLOW__ ?? (globalThis.__STATE_FLOW__ = {
1430
+ version: `${package_json_default.version} (${package_json_default.branch} <${package_json_default.commit}>)`
1431
+ });
1432
+ export {
1433
+ PARSER,
1434
+ Result,
1435
+ ResultCollector,
1436
+ ResultKind,
1437
+ SIGNALS,
1438
+ STRING_REPR,
1439
+ StateFlowError,
1440
+ VARIANT,
1441
+ addGlobalLogHandler,
1442
+ applyFlow,
1443
+ consoleLogHandler,
1444
+ defineFlow,
1445
+ defineSignal,
1446
+ defineState,
1447
+ dispatch,
1448
+ disposeFlow,
1449
+ isState,
1450
+ lock,
1451
+ observe,
1452
+ serializeDebug,
1453
+ setConsoleLogSilenced,
1454
+ setGlobalDispatchContextProvider,
1455
+ stateVar,
1456
+ sync
1457
+ };
1458
+ //# sourceMappingURL=index.mjs.map