aifsmjs 0.5.5 → 0.5.8

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.
Files changed (59) hide show
  1. package/README.md +44 -513
  2. package/README_ZHTW.md +44 -505
  3. package/dist/chunk-2MME5V4F.cjs +384 -0
  4. package/dist/chunk-2MME5V4F.cjs.map +1 -0
  5. package/dist/chunk-3B2USJ3H.cjs +18 -0
  6. package/dist/chunk-3B2USJ3H.cjs.map +1 -0
  7. package/dist/chunk-A7U7QQL5.js +52 -0
  8. package/dist/chunk-A7U7QQL5.js.map +1 -0
  9. package/dist/chunk-CDK25FTD.cjs +59 -0
  10. package/dist/chunk-CDK25FTD.cjs.map +1 -0
  11. package/dist/chunk-FHTQ7LSQ.cjs +21 -0
  12. package/dist/chunk-FHTQ7LSQ.cjs.map +1 -0
  13. package/dist/chunk-I354FONA.cjs +153 -0
  14. package/dist/chunk-I354FONA.cjs.map +1 -0
  15. package/dist/chunk-JKZAOPQC.js +16 -0
  16. package/dist/chunk-JKZAOPQC.js.map +1 -0
  17. package/dist/chunk-NEJYZAKR.js +19 -0
  18. package/dist/chunk-NEJYZAKR.js.map +1 -0
  19. package/dist/chunk-PZ5AY32C.js +9 -0
  20. package/dist/chunk-PZ5AY32C.js.map +1 -0
  21. package/dist/chunk-Q7SFCCGT.cjs +11 -0
  22. package/dist/chunk-Q7SFCCGT.cjs.map +1 -0
  23. package/dist/chunk-VZCSHTOI.js +374 -0
  24. package/dist/chunk-VZCSHTOI.js.map +1 -0
  25. package/dist/chunk-ZLQ7HZCE.js +142 -0
  26. package/dist/chunk-ZLQ7HZCE.js.map +1 -0
  27. package/dist/effects/index.cjs +8 -14
  28. package/dist/effects/index.cjs.map +1 -1
  29. package/dist/effects/index.js +5 -14
  30. package/dist/effects/index.js.map +1 -1
  31. package/dist/guards/index.cjs +9 -13
  32. package/dist/guards/index.cjs.map +1 -1
  33. package/dist/guards/index.js +8 -12
  34. package/dist/guards/index.js.map +1 -1
  35. package/dist/index.cjs +101 -591
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.js +5 -571
  38. package/dist/index.js.map +1 -1
  39. package/dist/inspect/index.cjs +2 -0
  40. package/dist/inspect/index.cjs.map +1 -1
  41. package/dist/inspect/index.js +2 -0
  42. package/dist/inspect/index.js.map +1 -1
  43. package/dist/pbt/index.cjs +26 -525
  44. package/dist/pbt/index.cjs.map +1 -1
  45. package/dist/pbt/index.d.cts +7 -3
  46. package/dist/pbt/index.d.ts +7 -3
  47. package/dist/pbt/index.js +12 -511
  48. package/dist/pbt/index.js.map +1 -1
  49. package/dist/replay/index.cjs +9 -195
  50. package/dist/replay/index.cjs.map +1 -1
  51. package/dist/replay/index.js +5 -198
  52. package/dist/replay/index.js.map +1 -1
  53. package/dist/timer/index.cjs +30 -9
  54. package/dist/timer/index.cjs.map +1 -1
  55. package/dist/timer/index.js +30 -9
  56. package/dist/timer/index.js.map +1 -1
  57. package/llms-full.txt +107 -932
  58. package/llms.txt +8 -35
  59. package/package.json +5 -3
package/dist/pbt/index.js CHANGED
@@ -1,195 +1,11 @@
1
+ import { createRuntime, initialSnapshot } from '../chunk-VZCSHTOI.js';
2
+ import { replay } from '../chunk-NEJYZAKR.js';
3
+ import { step, mergeContext, normalizeTransitions } from '../chunk-ZLQ7HZCE.js';
4
+ import '../chunk-JKZAOPQC.js';
5
+ import '../chunk-A7U7QQL5.js';
6
+ import { __export } from '../chunk-PZ5AY32C.js';
1
7
  import * as fc2 from 'fast-check';
2
8
 
3
- var __defProp = Object.defineProperty;
4
- var __export = (target, all) => {
5
- for (var name in all)
6
- __defProp(target, name, { get: all[name], enumerable: true });
7
- };
8
-
9
- // src/effects/enqueuer.ts
10
- function createEnqueuer(sink) {
11
- return Object.freeze({
12
- effect(type, payload) {
13
- if (payload === void 0) {
14
- sink.push(Object.freeze({ type }));
15
- } else {
16
- sink.push(Object.freeze({ type, payload }));
17
- }
18
- }
19
- });
20
- }
21
-
22
- // src/fsm/evaluator.ts
23
- var UnknownGuardError = class extends Error {
24
- guardName;
25
- constructor(guardName) {
26
- super(`aifsmjs: guard "${guardName}" not found in implementations.guards`);
27
- this.name = "UnknownGuardError";
28
- this.guardName = guardName;
29
- }
30
- };
31
- var AsyncGuardError = class extends Error {
32
- guardName;
33
- constructor(guardName) {
34
- super(
35
- `aifsmjs: guard "${guardName}" must be sync; received a Promise. Async guards break determinism and replay. Move I/O into an effect.`
36
- );
37
- this.name = "AsyncGuardError";
38
- this.guardName = guardName;
39
- }
40
- };
41
- function isAsyncGuardFn(fn) {
42
- if (typeof fn !== "function") return false;
43
- return fn.constructor?.name === "AsyncFunction";
44
- }
45
- function isThenable(x) {
46
- return x !== null && (typeof x === "object" || typeof x === "function") && typeof x.then === "function";
47
- }
48
- function resolveGuard(ref, impl) {
49
- if (typeof ref === "function") return ref;
50
- const fn = impl.guards?.[ref];
51
- if (!fn) throw new UnknownGuardError(ref);
52
- return fn;
53
- }
54
- function evalGuard(ref, context, event, impl, value) {
55
- const fn = resolveGuard(ref, impl);
56
- const guardName = typeof ref === "string" ? ref : fn.name || "<inline>";
57
- if (isAsyncGuardFn(fn)) {
58
- throw new AsyncGuardError(guardName);
59
- }
60
- const args = { context, event };
61
- const guardsMap = impl.guards;
62
- if (guardsMap) args.guards = guardsMap;
63
- if (value !== void 0) args.value = value;
64
- const result = fn(args);
65
- if (isThenable(result)) {
66
- throw new AsyncGuardError(guardName);
67
- }
68
- return result;
69
- }
70
-
71
- // src/fsm/resolver.ts
72
- function normalizeTransition(entry) {
73
- return typeof entry === "string" ? { target: entry } : entry;
74
- }
75
- function normalizeTransitions(entry) {
76
- if (entry === void 0) return [];
77
- if (Array.isArray(entry)) {
78
- return entry.some((t) => typeof t === "string") ? entry.map((t) => normalizeTransition(t)) : entry;
79
- }
80
- return [normalizeTransition(entry)];
81
- }
82
-
83
- // src/fsm/snapshot.ts
84
- var IS_DEV = typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.NODE_ENV !== "production";
85
- function isPlainObject(value) {
86
- if (value === null || typeof value !== "object") return false;
87
- const proto = Object.getPrototypeOf(value);
88
- return proto === Object.prototype || proto === null;
89
- }
90
- function deepFreeze(value) {
91
- if (value === null || typeof value !== "object") return value;
92
- if (Object.isFrozen(value)) return value;
93
- Object.freeze(value);
94
- if (Array.isArray(value)) {
95
- for (const item of value) deepFreeze(item);
96
- } else if (isPlainObject(value)) {
97
- for (const key of Object.keys(value)) {
98
- deepFreeze(value[key]);
99
- }
100
- }
101
- return value;
102
- }
103
- function freezeSnapshot(snap) {
104
- return IS_DEV ? deepFreeze(snap) : Object.freeze(snap);
105
- }
106
-
107
- // src/fsm/updater.ts
108
- function isPlainRecord(value) {
109
- if (value === null || typeof value !== "object") return false;
110
- const proto = Object.getPrototypeOf(value);
111
- return proto === Object.prototype || proto === null;
112
- }
113
- function mergeContext(current, patch) {
114
- if (patch === void 0 || patch === null) return current;
115
- if (isPlainRecord(current) && isPlainRecord(patch)) {
116
- return { ...current, ...patch };
117
- }
118
- return patch;
119
- }
120
-
121
- // src/fsm/lifecycle.ts
122
- var UnknownActionError = class extends Error {
123
- actionName;
124
- constructor(actionName) {
125
- super(`aifsmjs: action "${actionName}" not found in implementations.actions`);
126
- this.name = "UnknownActionError";
127
- this.actionName = actionName;
128
- }
129
- };
130
- function resolveAction(ref, impl) {
131
- if (typeof ref === "function") return ref;
132
- const fn = impl.actions?.[ref];
133
- if (!fn) throw new UnknownActionError(ref);
134
- return fn;
135
- }
136
- function runActions(refs, ctx, event, impl, effectSink) {
137
- if (!refs || refs.length === 0) return ctx;
138
- const enqueue = createEnqueuer(effectSink);
139
- let current = ctx;
140
- for (const ref of refs) {
141
- const fn = resolveAction(ref, impl);
142
- const patch = fn({ context: current, event, enqueue });
143
- current = mergeContext(current, patch);
144
- }
145
- return current;
146
- }
147
- function pickTransition(candidates, ctx, event, impl, value) {
148
- for (const t of candidates) {
149
- if (!t.guard) return t;
150
- if (evalGuard(t.guard, ctx, event, impl, value)) return t;
151
- }
152
- return void 0;
153
- }
154
- function step(def, snapshot, event, impl) {
155
- if (snapshot.status === "final") {
156
- return Object.freeze({ snapshot, effects: [], changed: false });
157
- }
158
- const state = def.states[snapshot.value];
159
- if (!state) {
160
- return Object.freeze({ snapshot, effects: [], changed: false });
161
- }
162
- const candidateList = normalizeTransitions(state.on?.[event.type]);
163
- const chosen = pickTransition(candidateList, snapshot.context, event, impl, snapshot.value);
164
- if (!chosen) {
165
- return Object.freeze({ snapshot, effects: [], changed: false });
166
- }
167
- const isExternal = chosen.target !== void 0;
168
- const nextStateValue = chosen.target ?? snapshot.value;
169
- const nextState = def.states[nextStateValue];
170
- const effectSink = [];
171
- let ctx = snapshot.context;
172
- if (isExternal) {
173
- ctx = runActions(state.exit, ctx, event, impl, effectSink);
174
- }
175
- ctx = runActions(chosen.actions, ctx, event, impl, effectSink);
176
- if (isExternal && nextState) {
177
- ctx = runActions(nextState.entry, ctx, event, impl, effectSink);
178
- }
179
- const status = nextState?.final === true ? "final" : "active";
180
- const nextSnapshot = freezeSnapshot({
181
- value: nextStateValue,
182
- context: ctx,
183
- status
184
- });
185
- return Object.freeze({
186
- snapshot: nextSnapshot,
187
- effects: Object.freeze(effectSink.slice()),
188
- changed: true
189
- });
190
- }
191
-
192
- // src/pbt/commands.ts
193
9
  function initialModel(def) {
194
10
  return {
195
11
  value: def.initial,
@@ -248,327 +64,6 @@ __export(properties_exports, {
248
64
  snapshotAlwaysFrozen: () => snapshotAlwaysFrozen,
249
65
  unknownEventNoOp: () => unknownEventNoOp
250
66
  });
251
-
252
- // src/fsm/types.ts
253
- var RESET_EVENT_TYPE = "@@aifsmjs/RESET";
254
-
255
- // src/fsm/runtime.ts
256
- var RuntimeDisposedError = class extends Error {
257
- constructor() {
258
- super("aifsmjs: runtime has been disposed; send()/reset() are not allowed");
259
- this.name = "RuntimeDisposedError";
260
- }
261
- };
262
- var SubMachineError = class extends Error {
263
- parentState;
264
- phase;
265
- cause;
266
- constructor(parentState, phase, cause) {
267
- super(`aifsmjs: sub-machine ${phase} failed at parent state "${parentState}"`, { cause });
268
- this.name = "SubMachineError";
269
- this.parentState = parentState;
270
- this.phase = phase;
271
- this.cause = cause;
272
- }
273
- };
274
- var RESET_EVENT = Object.freeze({ type: RESET_EVENT_TYPE });
275
- function composeMiddleware(middleware) {
276
- return (ctx, finalNext) => {
277
- let index = -1;
278
- const dispatch = (i) => {
279
- if (i <= index) throw new Error("aifsmjs: next() called multiple times in middleware");
280
- index = i;
281
- const fn = middleware[i];
282
- if (!fn) {
283
- finalNext();
284
- return;
285
- }
286
- fn(ctx, () => dispatch(i + 1));
287
- };
288
- dispatch(0);
289
- };
290
- }
291
- function createRuntime(def, impl, opts = {}) {
292
- let snapshot = initialSnapshot(def);
293
- const listeners = /* @__PURE__ */ new Set();
294
- const middlewareChain = opts.middleware && opts.middleware.length > 0 ? composeMiddleware(opts.middleware) : void 0;
295
- const shouldDispatch = opts.dispatchEffects !== false;
296
- const controller = new AbortController();
297
- let disposed = false;
298
- let childRuntime;
299
- let childAbortCleanup;
300
- const eventListeners = {
301
- transition: /* @__PURE__ */ new Set(),
302
- error: /* @__PURE__ */ new Set(),
303
- dispose: /* @__PURE__ */ new Set()
304
- };
305
- const externalAbortCleanups = /* @__PURE__ */ new Set();
306
- function emit(type, payload) {
307
- for (const fn of eventListeners[type]) fn(payload);
308
- }
309
- function notify(committed) {
310
- const captured = committed ?? snapshot;
311
- for (const l of listeners) l(captured);
312
- }
313
- function runMiddleware(prev, event, effects, changed) {
314
- if (!middlewareChain) return;
315
- middlewareChain(deepFreeze({ prev, next: snapshot, event, effects, changed }), () => {
316
- });
317
- }
318
- function dispatchEffects(effects, context, event) {
319
- if (!impl.effects || effects.length === 0) return;
320
- for (const eff of effects) {
321
- const handler = impl.effects[eff.type];
322
- if (!handler) continue;
323
- const r = handler(eff, { context, event, signal: controller.signal });
324
- if (r instanceof Promise) {
325
- r.catch((err) => {
326
- emit("error", { error: err, event });
327
- });
328
- }
329
- }
330
- }
331
- function wireChildAbort(child) {
332
- if (controller.signal.aborted) {
333
- try {
334
- child.dispose();
335
- } catch {
336
- }
337
- return () => {
338
- };
339
- }
340
- const onAbort = () => {
341
- try {
342
- child.dispose();
343
- } catch {
344
- }
345
- };
346
- controller.signal.addEventListener("abort", onAbort, { once: true });
347
- return () => controller.signal.removeEventListener("abort", onAbort);
348
- }
349
- function findChosenIsExternal(value, event, context) {
350
- const state = def.states[value];
351
- if (!state?.on) return false;
352
- const list = normalizeTransitions(state.on[event.type]);
353
- if (list.length === 0) return false;
354
- for (const t of list) {
355
- if (!t.guard || evalGuard(t.guard, context, event, impl, value)) {
356
- return t.target !== void 0;
357
- }
358
- }
359
- return false;
360
- }
361
- function applySubLifecycle(prevValue, nextValue) {
362
- const prevStateDef = def.states[prevValue];
363
- const nextStateDef = def.states[nextValue];
364
- if (prevStateDef?.sub !== void 0 && childRuntime !== void 0) {
365
- const child = childRuntime;
366
- childRuntime = void 0;
367
- childAbortCleanup?.();
368
- childAbortCleanup = void 0;
369
- try {
370
- child.dispose();
371
- } catch (cause) {
372
- throw new SubMachineError(prevValue, "dispose", cause);
373
- }
374
- }
375
- if (nextStateDef?.sub !== void 0) {
376
- let newChild;
377
- try {
378
- newChild = createRuntime(nextStateDef.sub, nextStateDef.subImpl ?? {});
379
- } catch (cause) {
380
- throw new SubMachineError(nextValue, "init", cause);
381
- }
382
- childRuntime = newChild;
383
- childAbortCleanup = wireChildAbort(newChild);
384
- }
385
- }
386
- function send(event) {
387
- if (disposed) throw new RuntimeDisposedError();
388
- const prev = snapshot;
389
- const result = step(def, prev, event, impl);
390
- const isExternal = result.changed && (prev.value !== result.snapshot.value || findChosenIsExternal(prev.value, event, prev.context));
391
- if (result.changed && isExternal) applySubLifecycle(prev.value, result.snapshot.value);
392
- snapshot = result.snapshot;
393
- const committed = result.snapshot;
394
- runMiddleware(prev, event, result.effects, result.changed);
395
- if (shouldDispatch) dispatchEffects(result.effects, committed.context, event);
396
- if (result.changed) {
397
- notify(committed);
398
- emit("transition", {
399
- prev,
400
- next: committed,
401
- event,
402
- effects: result.effects,
403
- changed: true
404
- });
405
- }
406
- return snapshot;
407
- }
408
- function reset(event) {
409
- if (disposed) throw new RuntimeDisposedError();
410
- const prev = snapshot;
411
- const nextSnap = initialSnapshot(def);
412
- const changed = prev.value !== nextSnap.value;
413
- if (childRuntime) {
414
- const child = childRuntime;
415
- childRuntime = void 0;
416
- childAbortCleanup?.();
417
- childAbortCleanup = void 0;
418
- try {
419
- child.dispose();
420
- } catch (cause) {
421
- throw new SubMachineError(prev.value, "dispose", cause);
422
- }
423
- }
424
- const initStateDef = def.states[nextSnap.value];
425
- if (initStateDef?.sub) {
426
- let newChild;
427
- try {
428
- newChild = createRuntime(initStateDef.sub, initStateDef.subImpl ?? {});
429
- } catch (cause) {
430
- throw new SubMachineError(nextSnap.value, "init", cause);
431
- }
432
- childRuntime = newChild;
433
- childAbortCleanup = wireChildAbort(newChild);
434
- }
435
- snapshot = nextSnap;
436
- const triggerEvent = event ?? RESET_EVENT;
437
- runMiddleware(prev, triggerEvent, [], changed);
438
- if (changed) {
439
- notify();
440
- emit("transition", {
441
- prev,
442
- next: snapshot,
443
- event: triggerEvent,
444
- effects: [],
445
- changed: true
446
- });
447
- }
448
- return snapshot;
449
- }
450
- function can(event) {
451
- if (disposed || snapshot.status === "final") return false;
452
- const state = def.states[snapshot.value];
453
- if (!state) return false;
454
- const list = normalizeTransitions(state.on?.[event.type]);
455
- if (list.length === 0) return false;
456
- for (const t of list) {
457
- if (!t.guard) return true;
458
- if (evalGuard(t.guard, snapshot.context, event, impl, snapshot.value)) return true;
459
- }
460
- return false;
461
- }
462
- function on(type, listener, options) {
463
- if (disposed || options?.signal?.aborted) return () => {
464
- };
465
- const target = eventListeners[type];
466
- let detachAbort;
467
- const cleanup = () => {
468
- target.delete(wrapped);
469
- if (detachAbort) {
470
- detachAbort();
471
- externalAbortCleanups.delete(detachAbort);
472
- }
473
- };
474
- let wrapped = listener;
475
- if (options?.once) {
476
- wrapped = (payload) => {
477
- cleanup();
478
- listener(payload);
479
- };
480
- }
481
- target.add(wrapped);
482
- const signal = options?.signal;
483
- if (signal) {
484
- const onAbort = () => cleanup();
485
- signal.addEventListener("abort", onAbort, { once: true });
486
- detachAbort = () => signal.removeEventListener("abort", onAbort);
487
- externalAbortCleanups.add(detachAbort);
488
- }
489
- return cleanup;
490
- }
491
- function dispose() {
492
- if (disposed) return;
493
- disposed = true;
494
- if (childRuntime) {
495
- childAbortCleanup?.();
496
- childAbortCleanup = void 0;
497
- try {
498
- childRuntime.dispose();
499
- } catch {
500
- }
501
- childRuntime = void 0;
502
- }
503
- controller.abort();
504
- listeners.clear();
505
- emit("dispose", void 0);
506
- for (const set of Object.values(eventListeners)) set.clear();
507
- for (const cleanup of externalAbortCleanups) cleanup();
508
- externalAbortCleanups.clear();
509
- }
510
- const runtime = {
511
- getSnapshot: () => snapshot,
512
- snapshot: () => snapshot,
513
- send,
514
- can,
515
- reset,
516
- dispose,
517
- on,
518
- get disposed() {
519
- return disposed;
520
- },
521
- get signal() {
522
- return controller.signal;
523
- },
524
- subscribe(listener) {
525
- if (disposed) return () => {
526
- };
527
- listeners.add(listener);
528
- return () => listeners.delete(listener);
529
- },
530
- subRuntime: () => childRuntime,
531
- onTransition: (handler, options) => on("transition", handler, options)
532
- };
533
- const bootStateDef = def.states[snapshot.value];
534
- if (bootStateDef?.sub) {
535
- let newChild;
536
- try {
537
- newChild = createRuntime(bootStateDef.sub, bootStateDef.subImpl ?? {});
538
- } catch (cause) {
539
- throw new SubMachineError(snapshot.value, "init", cause);
540
- }
541
- childRuntime = newChild;
542
- childAbortCleanup = wireChildAbort(newChild);
543
- }
544
- return runtime;
545
- }
546
-
547
- // src/fsm/definition.ts
548
- function initialSnapshot(def) {
549
- const isFinal = def.states[def.initial]?.final === true;
550
- return freezeSnapshot({
551
- value: def.initial,
552
- context: def.context,
553
- status: isFinal ? "final" : "active"
554
- });
555
- }
556
-
557
- // src/replay/index.ts
558
- function replay(initial, events, def, impl) {
559
- let snapshot = initial;
560
- const effects = [];
561
- for (const event of events) {
562
- const r = step(def, snapshot, event, impl);
563
- snapshot = r.snapshot;
564
- if (r.effects.length > 0) {
565
- for (const eff of r.effects) effects.push(eff);
566
- }
567
- }
568
- return Object.freeze({ snapshot, effects: Object.freeze(effects.slice()) });
569
- }
570
-
571
- // src/pbt/properties.ts
572
67
  function buildAssertOpts(opts) {
573
68
  const out = {};
574
69
  if (opts?.numRuns !== void 0) out.numRuns = opts.numRuns;
@@ -636,13 +131,19 @@ function guardsFalseNoTransition(def, impl, eventArbitraries, opts) {
636
131
  ...impl,
637
132
  guards: blockedGuards
638
133
  };
134
+ const isFullyGuarded = (value, eventType) => {
135
+ const candidates = normalizeTransitions(def.states[value]?.on?.[eventType]);
136
+ return candidates.length > 0 && candidates.every((t) => t.guard !== void 0);
137
+ };
639
138
  fc2.assert(
640
139
  fc2.property(
641
140
  fc2.array(fc2.oneof(...Object.values(eventArbitraries)), { maxLength: 16 }),
642
141
  (events) => {
643
142
  let snap = initialSnapshot(def);
644
143
  for (const e of events) {
144
+ const fullyGuarded = isFullyGuarded(snap.value, e.type);
645
145
  const r = step(def, snap, e, blockedImpl);
146
+ if (fullyGuarded && r.changed !== false) return false;
646
147
  snap = r.snapshot;
647
148
  }
648
149
  return true;