@plures/praxis 1.1.1 → 1.1.3

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 (33) hide show
  1. package/README.md +68 -7
  2. package/dist/browser/chunk-R45WXWKH.js +345 -0
  3. package/dist/browser/index.d.ts +171 -11
  4. package/dist/browser/index.js +279 -277
  5. package/dist/browser/integrations/svelte.d.ts +3 -1
  6. package/dist/browser/integrations/svelte.js +7 -0
  7. package/dist/browser/{engine-BjdqxeXG.d.ts → reactive-engine.svelte-C9OpcTHf.d.ts} +87 -1
  8. package/dist/node/chunk-R45WXWKH.js +345 -0
  9. package/dist/node/components/index.d.cts +2 -2
  10. package/dist/node/components/index.d.ts +2 -2
  11. package/dist/node/index.cjs +343 -8
  12. package/dist/node/index.d.cts +108 -15
  13. package/dist/node/index.d.ts +108 -15
  14. package/dist/node/index.js +279 -278
  15. package/dist/node/integrations/svelte.cjs +357 -2
  16. package/dist/node/integrations/svelte.d.cts +3 -1
  17. package/dist/node/integrations/svelte.d.ts +3 -1
  18. package/dist/node/integrations/svelte.js +6 -0
  19. package/dist/node/{engine-CVJobhHm.d.cts → reactive-engine.svelte-1M4m_C_v.d.cts} +87 -1
  20. package/dist/node/{engine-1iqLe6_P.d.ts → reactive-engine.svelte-ChNFn4Hj.d.ts} +87 -1
  21. package/dist/node/{terminal-adapter-XLtCjjb_.d.cts → terminal-adapter-CDzxoLKR.d.cts} +68 -1
  22. package/dist/node/{terminal-adapter-07HGftGQ.d.ts → terminal-adapter-CWka-yL8.d.ts} +68 -1
  23. package/package.json +3 -2
  24. package/src/__tests__/reactive-engine.test.ts +516 -0
  25. package/src/core/pluresdb/README.md +156 -0
  26. package/src/core/pluresdb/adapter.ts +165 -0
  27. package/src/core/pluresdb/index.ts +3 -3
  28. package/src/core/reactive-engine.svelte.ts +88 -19
  29. package/src/core/reactive-engine.ts +283 -30
  30. package/src/index.browser.ts +12 -0
  31. package/src/index.ts +12 -0
  32. package/src/integrations/pluresdb.ts +2 -2
  33. package/src/integrations/svelte.ts +8 -0
@@ -31,11 +31,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  ActorManager: () => ActorManager,
34
+ FrameworkAgnosticReactiveEngine: () => ReactiveLogicEngine2,
34
35
  InMemoryPraxisDB: () => InMemoryPraxisDB,
35
36
  LogicEngine: () => LogicEngine,
36
37
  PRAXIS_PATHS: () => PRAXIS_PATHS,
37
38
  PRAXIS_PROTOCOL_VERSION: () => PRAXIS_PROTOCOL_VERSION,
38
39
  PluresDBGenerator: () => PluresDBGenerator,
40
+ PluresDBPraxisAdapter: () => PluresDBPraxisAdapter,
39
41
  PraxisDBStore: () => PraxisDBStore,
40
42
  PraxisRegistry: () => PraxisRegistry,
41
43
  PraxisSchemaRegistry: () => PraxisSchemaRegistry,
@@ -50,14 +52,17 @@ __export(src_exports, {
50
52
  canvasToSchema: () => canvasToSchema,
51
53
  canvasToYaml: () => canvasToYaml,
52
54
  createCanvasEditor: () => createCanvasEditor,
55
+ createFrameworkAgnosticReactiveEngine: () => createReactiveEngine2,
53
56
  createInMemoryDB: () => createInMemoryDB,
54
57
  createIntrospector: () => createIntrospector,
55
58
  createMockExecutor: () => createMockExecutor,
56
59
  createMockTauriBridge: () => createMockTauriBridge,
60
+ createPluresDB: () => createPluresDB,
57
61
  createPluresDBAdapter: () => createPluresDBAdapter,
58
62
  createPluresDBGenerator: () => createPluresDBGenerator,
59
63
  createPraxisDBStore: () => createPraxisDBStore,
60
64
  createPraxisEngine: () => createPraxisEngine,
65
+ createReactiveEngine: () => createReactiveEngine,
61
66
  createSchemaRegistry: () => createSchemaRegistry,
62
67
  createSchemaTemplate: () => createSchemaTemplate,
63
68
  createStateDocsGenerator: () => createStateDocsGenerator,
@@ -360,9 +365,7 @@ function createPraxisEngine(options) {
360
365
  var $ = __toESM(require("svelte/internal/client"), 1);
361
366
  var ReactiveLogicEngine = class {
362
367
  #state = (
363
- // The single source of truth, reactive by default
364
- // We use $state.raw for things that shouldn't be deeply reactive if needed,
365
- // but for context we usually want deep reactivity.
368
+ // Use Svelte's $state rune for automatic reactivity
366
369
  $.state($.proxy({ context: {}, facts: [], meta: {} }))
367
370
  );
368
371
  get state() {
@@ -371,14 +374,26 @@ var ReactiveLogicEngine = class {
371
374
  set state(value) {
372
375
  $.set(this.#state, value, true);
373
376
  }
377
+ _engine;
374
378
  constructor(options) {
375
379
  this.state.context = options.initialContext;
376
380
  this.state.facts = options.initialFacts ?? [];
377
381
  this.state.meta = options.initialMeta ?? {};
382
+ if (options.registry) {
383
+ this._engine = createPraxisEngine({
384
+ initialContext: options.initialContext,
385
+ registry: options.registry
386
+ });
387
+ } else {
388
+ this._engine = createPraxisEngine({
389
+ initialContext: options.initialContext,
390
+ registry: new PraxisRegistry()
391
+ });
392
+ }
378
393
  }
379
394
  /**
380
- * Access the reactive context directly.
381
- * Consumers can use this in $derived() or $effect().
395
+ * Access the reactive context.
396
+ * In Svelte 5 components, changes to this object will automatically trigger updates.
382
397
  */
383
398
  get context() {
384
399
  return this.state.context;
@@ -389,9 +404,15 @@ var ReactiveLogicEngine = class {
389
404
  get facts() {
390
405
  return this.state.facts;
391
406
  }
407
+ /**
408
+ * Access the reactive metadata.
409
+ */
410
+ get meta() {
411
+ return this.state.meta;
412
+ }
392
413
  /**
393
414
  * Apply a mutation to the state.
394
- * This is the "Action" or "Rule" equivalent.
415
+ * Changes will automatically trigger Svelte reactivity.
395
416
  *
396
417
  * @param mutator A function that receives the state and modifies it.
397
418
  */
@@ -399,12 +420,234 @@ var ReactiveLogicEngine = class {
399
420
  mutator(this.state);
400
421
  }
401
422
  /**
402
- * Access the reactive meta.
423
+ * Process events through the logic engine and update reactive state.
424
+ *
425
+ * @param events Events to process
426
+ */
427
+ step(events) {
428
+ const result = this._engine.step(events);
429
+ this.state.context = result.state.context;
430
+ this.state.facts = result.state.facts;
431
+ this.state.meta = result.state.meta ?? {};
432
+ }
433
+ };
434
+ function createReactiveEngine(options) {
435
+ return new ReactiveLogicEngine(options);
436
+ }
437
+
438
+ // src/core/reactive-engine.ts
439
+ var ReactiveLogicEngine2 = class _ReactiveLogicEngine {
440
+ _state;
441
+ _subscribers = /* @__PURE__ */ new Set();
442
+ _contextProxy;
443
+ _factsProxy;
444
+ _metaProxy;
445
+ _batchDepth = 0;
446
+ _pendingNotification = false;
447
+ _proxyCache = /* @__PURE__ */ new WeakMap();
448
+ // Array methods that mutate the array
449
+ static ARRAY_MUTATORS = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"];
450
+ constructor(options) {
451
+ this._state = {
452
+ context: options.initialContext,
453
+ facts: options.initialFacts ?? [],
454
+ meta: options.initialMeta ?? {}
455
+ };
456
+ this._contextProxy = this._createReactiveProxy(this._state.context);
457
+ this._factsProxy = this._createReactiveProxy(this._state.facts);
458
+ this._metaProxy = this._createReactiveProxy(this._state.meta);
459
+ }
460
+ /**
461
+ * Create a reactive proxy that notifies subscribers on changes.
462
+ * Uses a WeakMap cache to avoid creating multiple proxies for the same object.
463
+ */
464
+ _createReactiveProxy(target) {
465
+ const cached = this._proxyCache.get(target);
466
+ if (cached) {
467
+ return cached;
468
+ }
469
+ const self = this;
470
+ const handler = {
471
+ get(obj, prop) {
472
+ const value = Reflect.get(obj, prop);
473
+ if (value && typeof value === "object") {
474
+ return self._createReactiveProxy(value);
475
+ }
476
+ if (Array.isArray(obj) && typeof value === "function") {
477
+ if (_ReactiveLogicEngine.ARRAY_MUTATORS.includes(prop)) {
478
+ return function(...args) {
479
+ const result = value.apply(obj, args);
480
+ self._notify();
481
+ return result;
482
+ };
483
+ }
484
+ }
485
+ return value;
486
+ },
487
+ set(obj, prop, value) {
488
+ const oldValue = obj[prop];
489
+ const result = Reflect.set(obj, prop, value);
490
+ if (oldValue !== value) {
491
+ self._notify();
492
+ }
493
+ return result;
494
+ },
495
+ deleteProperty(obj, prop) {
496
+ const result = Reflect.deleteProperty(obj, prop);
497
+ self._notify();
498
+ return result;
499
+ }
500
+ };
501
+ const proxy2 = new Proxy(target, handler);
502
+ this._proxyCache.set(target, proxy2);
503
+ return proxy2;
504
+ }
505
+ /**
506
+ * Notify all subscribers of state changes
507
+ */
508
+ _notify() {
509
+ if (this._batchDepth > 0) {
510
+ this._pendingNotification = true;
511
+ return;
512
+ }
513
+ const currentState = {
514
+ context: this._contextProxy,
515
+ facts: this._factsProxy,
516
+ meta: this._metaProxy
517
+ };
518
+ this._subscribers.forEach((callback) => {
519
+ try {
520
+ callback(currentState);
521
+ } catch (error) {
522
+ console.error("Error in reactive engine subscriber:", error);
523
+ }
524
+ });
525
+ }
526
+ /**
527
+ * Get the full state object
528
+ */
529
+ get state() {
530
+ return {
531
+ context: this._contextProxy,
532
+ facts: this._factsProxy,
533
+ meta: this._metaProxy
534
+ };
535
+ }
536
+ /**
537
+ * Access the reactive context.
538
+ * Changes to this object will trigger subscriber notifications.
539
+ */
540
+ get context() {
541
+ return this._contextProxy;
542
+ }
543
+ /**
544
+ * Access the reactive facts list.
545
+ * Changes to this array will trigger subscriber notifications.
546
+ */
547
+ get facts() {
548
+ return this._factsProxy;
549
+ }
550
+ /**
551
+ * Access the reactive metadata.
552
+ * Changes to this object will trigger subscriber notifications.
403
553
  */
404
554
  get meta() {
405
- return this.state.meta;
555
+ return this._metaProxy;
556
+ }
557
+ /**
558
+ * Apply a mutation to the state.
559
+ * This is the "Action" or "Rule" equivalent.
560
+ * Mutations are batched - notifications only happen once per apply call.
561
+ *
562
+ * @param mutator A function that receives the state and modifies it.
563
+ */
564
+ apply(mutator) {
565
+ this._batchDepth++;
566
+ try {
567
+ mutator({
568
+ context: this._contextProxy,
569
+ facts: this._factsProxy,
570
+ meta: this._metaProxy
571
+ });
572
+ } finally {
573
+ this._batchDepth--;
574
+ if (this._batchDepth === 0 && this._pendingNotification) {
575
+ this._pendingNotification = false;
576
+ this._notify();
577
+ }
578
+ }
579
+ }
580
+ /**
581
+ * Subscribe to state changes.
582
+ * Returns an unsubscribe function.
583
+ *
584
+ * @param callback Function to call when state changes
585
+ * @returns Unsubscribe function
586
+ */
587
+ subscribe(callback) {
588
+ this._subscribers.add(callback);
589
+ try {
590
+ callback({
591
+ context: this._contextProxy,
592
+ facts: this._factsProxy,
593
+ meta: this._metaProxy
594
+ });
595
+ } catch (error) {
596
+ console.error("Error in reactive engine subscriber:", error);
597
+ }
598
+ return () => {
599
+ this._subscribers.delete(callback);
600
+ };
601
+ }
602
+ /**
603
+ * Create a derived/computed value from the state.
604
+ * The selector function will be called whenever the state changes.
605
+ *
606
+ * @param selector Function to extract derived value from state
607
+ * @returns Object with subscribe method for reactive updates
608
+ */
609
+ $derived(selector) {
610
+ const subscribers = /* @__PURE__ */ new Set();
611
+ let currentValue = selector({
612
+ context: this._contextProxy,
613
+ facts: this._factsProxy,
614
+ meta: this._metaProxy
615
+ });
616
+ this.subscribe(() => {
617
+ const newValue = selector({
618
+ context: this._contextProxy,
619
+ facts: this._factsProxy,
620
+ meta: this._metaProxy
621
+ });
622
+ if (newValue !== currentValue) {
623
+ currentValue = newValue;
624
+ subscribers.forEach((callback) => {
625
+ try {
626
+ callback(currentValue);
627
+ } catch (error) {
628
+ console.error("Error in derived value subscriber:", error);
629
+ }
630
+ });
631
+ }
632
+ });
633
+ return {
634
+ subscribe: (callback) => {
635
+ subscribers.add(callback);
636
+ try {
637
+ callback(currentValue);
638
+ } catch (error) {
639
+ console.error("Error in derived value subscriber:", error);
640
+ }
641
+ return () => {
642
+ subscribers.delete(callback);
643
+ };
644
+ }
645
+ };
406
646
  }
407
647
  };
648
+ function createReactiveEngine2(options) {
649
+ return new ReactiveLogicEngine2(options);
650
+ }
408
651
 
409
652
  // src/core/actors.ts
410
653
  var ActorManager = class {
@@ -1634,6 +1877,93 @@ var InMemoryPraxisDB = class {
1634
1877
  function createInMemoryDB() {
1635
1878
  return new InMemoryPraxisDB();
1636
1879
  }
1880
+ var PluresDBPraxisAdapter = class {
1881
+ db;
1882
+ watchers = /* @__PURE__ */ new Map();
1883
+ pollIntervals = /* @__PURE__ */ new Map();
1884
+ lastValues = /* @__PURE__ */ new Map();
1885
+ pollInterval;
1886
+ constructor(config) {
1887
+ if ("get" in config && "put" in config) {
1888
+ this.db = config;
1889
+ this.pollInterval = 1e3;
1890
+ } else {
1891
+ this.db = config.db;
1892
+ this.pollInterval = config.pollInterval ?? 1e3;
1893
+ }
1894
+ }
1895
+ async get(key) {
1896
+ try {
1897
+ const value = await this.db.get(key);
1898
+ return value;
1899
+ } catch (error) {
1900
+ return void 0;
1901
+ }
1902
+ }
1903
+ async set(key, value) {
1904
+ await this.db.put(key, value);
1905
+ this.lastValues.set(key, value);
1906
+ const keyWatchers = this.watchers.get(key);
1907
+ if (keyWatchers) {
1908
+ for (const callback of keyWatchers) {
1909
+ callback(value);
1910
+ }
1911
+ }
1912
+ }
1913
+ watch(key, callback) {
1914
+ if (!this.watchers.has(key)) {
1915
+ this.watchers.set(key, /* @__PURE__ */ new Set());
1916
+ }
1917
+ const watchers = this.watchers.get(key);
1918
+ const wrappedCallback = (val) => callback(val);
1919
+ watchers.add(wrappedCallback);
1920
+ if (!this.pollIntervals.has(key)) {
1921
+ const interval = setInterval(async () => {
1922
+ try {
1923
+ const value = await this.db.get(key);
1924
+ const lastValue = this.lastValues.get(key);
1925
+ if (JSON.stringify(value) !== JSON.stringify(lastValue)) {
1926
+ this.lastValues.set(key, value);
1927
+ const currentWatchers = this.watchers.get(key);
1928
+ if (currentWatchers) {
1929
+ for (const cb of currentWatchers) {
1930
+ cb(value);
1931
+ }
1932
+ }
1933
+ }
1934
+ } catch (error) {
1935
+ }
1936
+ }, this.pollInterval);
1937
+ this.pollIntervals.set(key, interval);
1938
+ }
1939
+ return () => {
1940
+ watchers.delete(wrappedCallback);
1941
+ if (watchers.size === 0) {
1942
+ this.watchers.delete(key);
1943
+ const interval = this.pollIntervals.get(key);
1944
+ if (interval) {
1945
+ clearInterval(interval);
1946
+ this.pollIntervals.delete(key);
1947
+ }
1948
+ this.lastValues.delete(key);
1949
+ }
1950
+ };
1951
+ }
1952
+ /**
1953
+ * Clean up all resources
1954
+ */
1955
+ dispose() {
1956
+ for (const interval of this.pollIntervals.values()) {
1957
+ clearInterval(interval);
1958
+ }
1959
+ this.pollIntervals.clear();
1960
+ this.watchers.clear();
1961
+ this.lastValues.clear();
1962
+ }
1963
+ };
1964
+ function createPluresDB(config) {
1965
+ return new PluresDBPraxisAdapter(config);
1966
+ }
1637
1967
 
1638
1968
  // src/core/pluresdb/schema-registry.ts
1639
1969
  function getSchemaPath(schemaName) {
@@ -3185,11 +3515,13 @@ function generateTauriConfig(config) {
3185
3515
  // Annotate the CommonJS export names for ESM import in node:
3186
3516
  0 && (module.exports = {
3187
3517
  ActorManager,
3518
+ FrameworkAgnosticReactiveEngine,
3188
3519
  InMemoryPraxisDB,
3189
3520
  LogicEngine,
3190
3521
  PRAXIS_PATHS,
3191
3522
  PRAXIS_PROTOCOL_VERSION,
3192
3523
  PluresDBGenerator,
3524
+ PluresDBPraxisAdapter,
3193
3525
  PraxisDBStore,
3194
3526
  PraxisRegistry,
3195
3527
  PraxisSchemaRegistry,
@@ -3204,14 +3536,17 @@ function generateTauriConfig(config) {
3204
3536
  canvasToSchema,
3205
3537
  canvasToYaml,
3206
3538
  createCanvasEditor,
3539
+ createFrameworkAgnosticReactiveEngine,
3207
3540
  createInMemoryDB,
3208
3541
  createIntrospector,
3209
3542
  createMockExecutor,
3210
3543
  createMockTauriBridge,
3544
+ createPluresDB,
3211
3545
  createPluresDBAdapter,
3212
3546
  createPluresDBGenerator,
3213
3547
  createPraxisDBStore,
3214
3548
  createPraxisEngine,
3549
+ createReactiveEngine,
3215
3550
  createSchemaRegistry,
3216
3551
  createSchemaTemplate,
3217
3552
  createStateDocsGenerator,
@@ -1,42 +1,91 @@
1
1
  import { P as PraxisState, a as PraxisEvent, b as PraxisFact } from './protocol-Qek7ebBl.cjs';
2
2
  export { g as PRAXIS_PROTOCOL_VERSION, e as PraxisDiagnostics, d as PraxisStepConfig, f as PraxisStepFn, c as PraxisStepResult } from './protocol-Qek7ebBl.cjs';
3
- import { L as LogicEngine, P as PraxisRegistry, R as RuleDescriptor, C as ConstraintDescriptor, a as RuleFn, b as ConstraintFn, c as PraxisModule } from './engine-CVJobhHm.cjs';
4
- export { e as ConstraintId, f as PraxisEngineOptions, d as RuleId, g as createPraxisEngine } from './engine-CVJobhHm.cjs';
5
- import { P as PraxisDB, U as UnsubscribeFn } from './terminal-adapter-XLtCjjb_.cjs';
6
- export { C as CommandExecutor, I as InMemoryPraxisDB, T as TerminalAdapter, d as TerminalAdapterOptions, a as TerminalExecutionResult, b as TerminalNodeState, f as createInMemoryDB, e as createMockExecutor, c as createTerminalAdapter, r as runTerminalCommand } from './terminal-adapter-XLtCjjb_.cjs';
3
+ import { L as LogicEngine, P as PraxisRegistry, b as RuleDescriptor, C as ConstraintDescriptor, d as RuleFn, e as ConstraintFn, f as PraxisModule } from './reactive-engine.svelte-1M4m_C_v.cjs';
4
+ export { h as ConstraintId, i as PraxisEngineOptions, a as ReactiveEngineOptions, R as ReactiveLogicEngine, g as RuleId, j as createPraxisEngine, c as createReactiveEngine } from './reactive-engine.svelte-1M4m_C_v.cjs';
5
+ import { P as PraxisDB, U as UnsubscribeFn$1 } from './terminal-adapter-CDzxoLKR.cjs';
6
+ export { C as CommandExecutor, I as InMemoryPraxisDB, g as PluresDBAdapterConfig, f as PluresDBInstance, i as PluresDBPraxisAdapter, T as TerminalAdapter, d as TerminalAdapterOptions, a as TerminalExecutionResult, b as TerminalNodeState, h as createInMemoryDB, e as createMockExecutor, j as createPluresDB, c as createTerminalAdapter, r as runTerminalCommand } from './terminal-adapter-CDzxoLKR.cjs';
7
7
  import { PraxisSchema, ValidationResult, ModelDefinition, FieldDefinition, ComponentDefinition, LogicDefinition } from './schema.cjs';
8
8
  export { NodeBindings, NodeDefinition, OrchestrationDefinition, TerminalNodeProps, ValidationError, createSchemaTemplate, validateSchema } from './schema.cjs';
9
9
 
10
10
  /**
11
11
  * Praxis Reactive Logic Engine
12
12
  *
13
- * A Svelte 5 native implementation of the Praxis Logic Engine.
14
- * Uses Runes ($state, $derived, $effect) for fine-grained reactivity.
13
+ * A framework-agnostic reactive implementation of the Praxis Logic Engine.
14
+ * Uses JavaScript Proxies to provide reactivity without Svelte-specific primitives.
15
+ *
16
+ * This implementation provides:
17
+ * - Proxy-based state tracking for automatic reactivity
18
+ * - Subscription-based change notifications
19
+ * - Computed/derived values support
20
+ * - Compatible API with Svelte-based implementation
15
21
  */
16
22
  interface ReactiveEngineOptions<TContext> {
17
23
  initialContext: TContext;
18
24
  initialFacts?: any[];
19
25
  initialMeta?: Record<string, unknown>;
20
26
  }
27
+ /**
28
+ * Callback type for state change subscribers
29
+ */
30
+ type StateChangeCallback<TContext> = (state: {
31
+ context: TContext;
32
+ facts: any[];
33
+ meta: Record<string, unknown>;
34
+ }) => void;
35
+ /**
36
+ * Callback type for unsubscribe function
37
+ */
38
+ type UnsubscribeFn = () => void;
39
+ /**
40
+ * Framework-agnostic reactive logic engine using JavaScript Proxies
41
+ */
21
42
  declare class ReactiveLogicEngine<TContext extends object> {
22
- state: {
43
+ private _state;
44
+ private _subscribers;
45
+ private _contextProxy;
46
+ private _factsProxy;
47
+ private _metaProxy;
48
+ private _batchDepth;
49
+ private _pendingNotification;
50
+ private _proxyCache;
51
+ private static readonly ARRAY_MUTATORS;
52
+ constructor(options: ReactiveEngineOptions<TContext>);
53
+ /**
54
+ * Create a reactive proxy that notifies subscribers on changes.
55
+ * Uses a WeakMap cache to avoid creating multiple proxies for the same object.
56
+ */
57
+ private _createReactiveProxy;
58
+ /**
59
+ * Notify all subscribers of state changes
60
+ */
61
+ private _notify;
62
+ /**
63
+ * Get the full state object
64
+ */
65
+ get state(): {
23
66
  context: TContext;
24
67
  facts: any[];
25
68
  meta: Record<string, unknown>;
26
69
  };
27
- constructor(options: ReactiveEngineOptions<TContext>);
28
70
  /**
29
- * Access the reactive context directly.
30
- * Consumers can use this in $derived() or $effect().
71
+ * Access the reactive context.
72
+ * Changes to this object will trigger subscriber notifications.
31
73
  */
32
74
  get context(): TContext;
33
75
  /**
34
76
  * Access the reactive facts list.
77
+ * Changes to this array will trigger subscriber notifications.
35
78
  */
36
79
  get facts(): any[];
80
+ /**
81
+ * Access the reactive metadata.
82
+ * Changes to this object will trigger subscriber notifications.
83
+ */
84
+ get meta(): Record<string, unknown>;
37
85
  /**
38
86
  * Apply a mutation to the state.
39
87
  * This is the "Action" or "Rule" equivalent.
88
+ * Mutations are batched - notifications only happen once per apply call.
40
89
  *
41
90
  * @param mutator A function that receives the state and modifies it.
42
91
  */
@@ -46,10 +95,54 @@ declare class ReactiveLogicEngine<TContext extends object> {
46
95
  meta: Record<string, unknown>;
47
96
  }) => void): void;
48
97
  /**
49
- * Access the reactive meta.
98
+ * Subscribe to state changes.
99
+ * Returns an unsubscribe function.
100
+ *
101
+ * @param callback Function to call when state changes
102
+ * @returns Unsubscribe function
103
+ */
104
+ subscribe(callback: StateChangeCallback<TContext>): UnsubscribeFn;
105
+ /**
106
+ * Create a derived/computed value from the state.
107
+ * The selector function will be called whenever the state changes.
108
+ *
109
+ * @param selector Function to extract derived value from state
110
+ * @returns Object with subscribe method for reactive updates
50
111
  */
51
- get meta(): Record<string, unknown>;
112
+ $derived<TDerived>(selector: (state: {
113
+ context: TContext;
114
+ facts: any[];
115
+ meta: Record<string, unknown>;
116
+ }) => TDerived): {
117
+ subscribe: (callback: (value: TDerived) => void) => UnsubscribeFn;
118
+ };
52
119
  }
120
+ /**
121
+ * Create a new reactive logic engine instance.
122
+ *
123
+ * @param options Configuration options for the reactive engine
124
+ * @returns A new ReactiveLogicEngine instance
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const engine = createReactiveEngine({
129
+ * initialContext: { count: 0 },
130
+ * initialFacts: [],
131
+ * initialMeta: {}
132
+ * });
133
+ *
134
+ * // Subscribe to changes
135
+ * engine.subscribe((state) => {
136
+ * console.log('State changed:', state);
137
+ * });
138
+ *
139
+ * // Mutate state (will trigger subscribers)
140
+ * engine.apply((state) => {
141
+ * state.context.count++;
142
+ * });
143
+ * ```
144
+ */
145
+ declare function createReactiveEngine<TContext extends object>(options: ReactiveEngineOptions<TContext>): ReactiveLogicEngine<TContext>;
53
146
 
54
147
  /**
55
148
  * Actors System
@@ -634,7 +727,7 @@ declare class PraxisDBStore<TContext = unknown> {
634
727
  * @param callback Called when facts of this type change
635
728
  * @returns Unsubscribe function
636
729
  */
637
- watchFacts(factTag: string, callback: (facts: PraxisFact[]) => void): UnsubscribeFn;
730
+ watchFacts(factTag: string, callback: (facts: PraxisFact[]) => void): UnsubscribeFn$1;
638
731
  /**
639
732
  * Check constraints against the current state with new facts
640
733
  */
@@ -997,7 +1090,7 @@ declare function createPluresDBAdapter<TContext = unknown>(options: PluresDBAdap
997
1090
  * detach();
998
1091
  * ```
999
1092
  */
1000
- declare function attachToEngine<TContext = unknown>(store: PraxisDBStore<TContext>, engine: LogicEngine<TContext>): UnsubscribeFn;
1093
+ declare function attachToEngine<TContext = unknown>(store: PraxisDBStore<TContext>, engine: LogicEngine<TContext>): UnsubscribeFn$1;
1001
1094
 
1002
1095
  /**
1003
1096
  * Unum Integration
@@ -2576,4 +2669,4 @@ declare function attachTauriToEngine<TContext>(engine: LogicEngine<TContext>, ad
2576
2669
  */
2577
2670
  declare function generateTauriConfig(config: TauriAppConfig): Record<string, unknown>;
2578
2671
 
2579
- export { type ActivityState, type Actor, ActorManager, type CanvasDocument, type CanvasEdge, type CanvasEdgeStyle, type CanvasEditorConfig, type CanvasNode, type CanvasNodeStyle, ComponentDefinition, ConstraintDescriptor, ConstraintFn, type ConstraintNode, type ConstraintSchema, type DefineConstraintOptions, type DefineModuleOptions, type DefineRuleOptions, type EventDefinition, type EventStreamEntry, type FactDefinition, type GeneratedDoc, type GeneratedPluresDBFile, type GraphEdge, type GuardianError, type GuardianResult, type GuardianWarning, type LifecycleState, type LoaderOptions, type LoaderResult, LogicDefinition, LogicEngine, ModelDefinition, PRAXIS_PATHS, type PluresDBAdapter, type PluresDBAdapterOptions, PluresDBGenerator, type PluresDBGeneratorOptions, PraxisDB, PraxisDBStore, type PraxisDBStoreOptions, PraxisEvent, PraxisFact, PraxisModule, PraxisRegistry, PraxisSchema, PraxisSchemaRegistry, PraxisState, type ReactiveEngineOptions, ReactiveLogicEngine, type RegistryGraph, RegistryIntrospector, type RegistrySchema, type RegistryStats, RuleDescriptor, RuleFn, type RuleNode, type RuleSchema, type StateDoc, type StateDocsConfig, StateDocsGenerator, type StateMachineDoc, type StoredSchema, type TauriAppConfig, type TauriBridge, type TauriCommand, type TauriEvent, type TauriFS, type TauriFileEntry, type TauriMenuItem, type TauriNotification, type TauriNotificationOptions, type TauriPlugin, type TauriPraxisAdapter, type TauriSecurityConfig, type TauriTray, type TauriUpdateConfig, type TauriUpdateInfo, type TauriWindowConfig, type TransitionDoc, UnsubscribeFn, type UnumAdapter, type UnumAdapterConfig, type UnumChannel, type UnumIdentity, type UnumMessage, type UnumStore, ValidationResult, attachTauriToEngine, attachToEngine, attachUnumToEngine, canvasToMermaid, canvasToSchema, canvasToYaml, createCanvasEditor, createIntrospector, createMockTauriBridge, createPluresDBAdapter, createPluresDBGenerator, createPraxisDBStore, createSchemaRegistry, createStateDocsGenerator, createTauriPraxisAdapter, createTimerActor, createUnumAdapter, defineConstraint, defineEvent, defineFact, defineModule, defineRule, filterEvents, filterFacts, findEvent, findFact, generateDocs, generateId, generateTauriConfig, getEventPath, getFactPath, getSchemaPath, loadSchema, loadSchemaFromFile, loadSchemaFromJson, loadSchemaFromYaml, registerSchema, schemaToCanvas, validateForGeneration, validateWithGuardian };
2672
+ export { type ActivityState, type Actor, ActorManager, type CanvasDocument, type CanvasEdge, type CanvasEdgeStyle, type CanvasEditorConfig, type CanvasNode, type CanvasNodeStyle, ComponentDefinition, ConstraintDescriptor, ConstraintFn, type ConstraintNode, type ConstraintSchema, type DefineConstraintOptions, type DefineModuleOptions, type DefineRuleOptions, type EventDefinition, type EventStreamEntry, type FactDefinition, ReactiveLogicEngine as FrameworkAgnosticReactiveEngine, type ReactiveEngineOptions as FrameworkAgnosticReactiveEngineOptions, type GeneratedDoc, type GeneratedPluresDBFile, type GraphEdge, type GuardianError, type GuardianResult, type GuardianWarning, type LifecycleState, type LoaderOptions, type LoaderResult, LogicDefinition, LogicEngine, ModelDefinition, PRAXIS_PATHS, type PluresDBAdapter, type PluresDBAdapterOptions, PluresDBGenerator, type PluresDBGeneratorOptions, PraxisDB, PraxisDBStore, type PraxisDBStoreOptions, PraxisEvent, PraxisFact, PraxisModule, PraxisRegistry, PraxisSchema, PraxisSchemaRegistry, PraxisState, type RegistryGraph, RegistryIntrospector, type RegistrySchema, type RegistryStats, RuleDescriptor, RuleFn, type RuleNode, type RuleSchema, type StateChangeCallback, type StateDoc, type StateDocsConfig, StateDocsGenerator, type StateMachineDoc, type StoredSchema, type TauriAppConfig, type TauriBridge, type TauriCommand, type TauriEvent, type TauriFS, type TauriFileEntry, type TauriMenuItem, type TauriNotification, type TauriNotificationOptions, type TauriPlugin, type TauriPraxisAdapter, type TauriSecurityConfig, type TauriTray, type TauriUpdateConfig, type TauriUpdateInfo, type TauriWindowConfig, type TransitionDoc, UnsubscribeFn$1 as UnsubscribeFn, type UnumAdapter, type UnumAdapterConfig, type UnumChannel, type UnumIdentity, type UnumMessage, type UnumStore, ValidationResult, attachTauriToEngine, attachToEngine, attachUnumToEngine, canvasToMermaid, canvasToSchema, canvasToYaml, createCanvasEditor, createReactiveEngine as createFrameworkAgnosticReactiveEngine, createIntrospector, createMockTauriBridge, createPluresDBAdapter, createPluresDBGenerator, createPraxisDBStore, createSchemaRegistry, createStateDocsGenerator, createTauriPraxisAdapter, createTimerActor, createUnumAdapter, defineConstraint, defineEvent, defineFact, defineModule, defineRule, filterEvents, filterFacts, findEvent, findFact, generateDocs, generateId, generateTauriConfig, getEventPath, getFactPath, getSchemaPath, loadSchema, loadSchemaFromFile, loadSchemaFromJson, loadSchemaFromYaml, registerSchema, schemaToCanvas, validateForGeneration, validateWithGuardian };