@plures/praxis 1.1.2 → 1.2.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.
Files changed (49) hide show
  1. package/FRAMEWORK.md +106 -15
  2. package/README.md +275 -53
  3. package/dist/browser/adapter-TM4IS5KT.js +12 -0
  4. package/dist/browser/chunk-JQ64KMLN.js +141 -0
  5. package/dist/browser/chunk-LE2ZJYFC.js +154 -0
  6. package/dist/browser/chunk-VOMLVI6V.js +197 -0
  7. package/dist/browser/engine-YJZV4SLD.js +8 -0
  8. package/dist/browser/index.d.ts +300 -11
  9. package/dist/browser/index.js +334 -325
  10. package/dist/browser/integrations/svelte.d.ts +3 -1
  11. package/dist/browser/integrations/svelte.js +8 -0
  12. package/dist/browser/{engine-BjdqxeXG.d.ts → reactive-engine.svelte-C9OpcTHf.d.ts} +87 -1
  13. package/dist/node/adapter-K6DOX6XS.js +13 -0
  14. package/dist/node/chunk-JQ64KMLN.js +141 -0
  15. package/dist/node/chunk-LE2ZJYFC.js +154 -0
  16. package/dist/node/chunk-S54337I5.js +446 -0
  17. package/dist/node/chunk-VOMLVI6V.js +197 -0
  18. package/dist/node/cli/index.cjs +1444 -889
  19. package/dist/node/cli/index.js +9 -0
  20. package/dist/node/components/index.d.cts +2 -2
  21. package/dist/node/components/index.d.ts +2 -2
  22. package/dist/node/docs-JFNYTOJA.js +102 -0
  23. package/dist/node/engine-2DQBKBJC.js +9 -0
  24. package/dist/node/index.cjs +747 -234
  25. package/dist/node/index.d.cts +237 -15
  26. package/dist/node/index.d.ts +237 -15
  27. package/dist/node/index.js +339 -767
  28. package/dist/node/integrations/svelte.cjs +357 -2
  29. package/dist/node/integrations/svelte.d.cts +3 -1
  30. package/dist/node/integrations/svelte.d.ts +3 -1
  31. package/dist/node/integrations/svelte.js +7 -0
  32. package/dist/node/{engine-CVJobhHm.d.cts → reactive-engine.svelte-1M4m_C_v.d.cts} +87 -1
  33. package/dist/node/{engine-1iqLe6_P.d.ts → reactive-engine.svelte-ChNFn4Hj.d.ts} +87 -1
  34. package/dist/node/{terminal-adapter-XLtCjjb_.d.cts → terminal-adapter-CDzxoLKR.d.cts} +68 -1
  35. package/dist/node/{terminal-adapter-07HGftGQ.d.ts → terminal-adapter-CWka-yL8.d.ts} +68 -1
  36. package/package.json +3 -2
  37. package/src/__tests__/reactive-engine.test.ts +516 -0
  38. package/src/cli/commands/docs.ts +147 -0
  39. package/src/cli/index.ts +21 -0
  40. package/src/core/pluresdb/README.md +156 -0
  41. package/src/core/pluresdb/adapter.ts +165 -0
  42. package/src/core/pluresdb/index.ts +3 -3
  43. package/src/core/reactive-engine.svelte.ts +93 -19
  44. package/src/core/reactive-engine.ts +284 -22
  45. package/src/index.browser.ts +16 -0
  46. package/src/index.ts +16 -0
  47. package/src/integrations/pluresdb.ts +2 -2
  48. package/src/integrations/svelte.ts +8 -0
  49. package/src/integrations/unified.ts +350 -0
@@ -1,3 +1,14 @@
1
+ import {
2
+ InMemoryPraxisDB,
3
+ PluresDBPraxisAdapter,
4
+ createInMemoryDB,
5
+ createPluresDB
6
+ } from "./chunk-JQ64KMLN.js";
7
+ import {
8
+ StateDocsGenerator,
9
+ createStateDocsGenerator,
10
+ generateDocs
11
+ } from "./chunk-S54337I5.js";
1
12
  import {
2
13
  canvasToMermaid,
3
14
  canvasToSchema,
@@ -6,6 +17,11 @@ import {
6
17
  schemaToCanvas,
7
18
  validateWithGuardian
8
19
  } from "./chunk-SRM3OPPM.js";
20
+ import {
21
+ PraxisRegistry,
22
+ ReactiveLogicEngine,
23
+ createReactiveEngine
24
+ } from "./chunk-LE2ZJYFC.js";
9
25
  import {
10
26
  TerminalAdapter,
11
27
  createMockExecutor,
@@ -27,320 +43,226 @@ import {
27
43
  createSchemaTemplate,
28
44
  validateSchema
29
45
  } from "./chunk-UATVJBNV.js";
46
+ import {
47
+ LogicEngine,
48
+ PRAXIS_PROTOCOL_VERSION,
49
+ createPraxisEngine
50
+ } from "./chunk-VOMLVI6V.js";
30
51
  import "./chunk-QGM4M3NI.js";
31
52
 
32
- // src/core/protocol.ts
33
- var PRAXIS_PROTOCOL_VERSION = "1.0.0";
34
-
35
- // src/core/rules.ts
36
- var PraxisRegistry = class {
37
- rules = /* @__PURE__ */ new Map();
38
- constraints = /* @__PURE__ */ new Map();
39
- /**
40
- * Register a rule
41
- */
42
- registerRule(descriptor) {
43
- if (this.rules.has(descriptor.id)) {
44
- throw new Error(`Rule with id "${descriptor.id}" already registered`);
45
- }
46
- this.rules.set(descriptor.id, descriptor);
47
- }
48
- /**
49
- * Register a constraint
50
- */
51
- registerConstraint(descriptor) {
52
- if (this.constraints.has(descriptor.id)) {
53
- throw new Error(`Constraint with id "${descriptor.id}" already registered`);
54
- }
55
- this.constraints.set(descriptor.id, descriptor);
56
- }
57
- /**
58
- * Register a module (all its rules and constraints)
59
- */
60
- registerModule(module) {
61
- for (const rule of module.rules) {
62
- this.registerRule(rule);
63
- }
64
- for (const constraint of module.constraints) {
65
- this.registerConstraint(constraint);
66
- }
67
- }
68
- /**
69
- * Get a rule by ID
70
- */
71
- getRule(id) {
72
- return this.rules.get(id);
73
- }
74
- /**
75
- * Get a constraint by ID
76
- */
77
- getConstraint(id) {
78
- return this.constraints.get(id);
79
- }
80
- /**
81
- * Get all registered rule IDs
82
- */
83
- getRuleIds() {
84
- return Array.from(this.rules.keys());
85
- }
86
- /**
87
- * Get all registered constraint IDs
88
- */
89
- getConstraintIds() {
90
- return Array.from(this.constraints.keys());
91
- }
92
- /**
93
- * Get all rules
94
- */
95
- getAllRules() {
96
- return Array.from(this.rules.values());
97
- }
98
- /**
99
- * Get all constraints
100
- */
101
- getAllConstraints() {
102
- return Array.from(this.constraints.values());
103
- }
104
- };
105
-
106
- // src/core/engine.ts
107
- function safeClone(value) {
108
- if (value === null || typeof value !== "object") {
109
- return value;
110
- }
111
- if (typeof globalThis.structuredClone === "function") {
112
- try {
113
- return globalThis.structuredClone(value);
114
- } catch {
115
- }
116
- }
117
- if (Array.isArray(value)) {
118
- return [...value];
119
- }
120
- return { ...value };
121
- }
122
- var LogicEngine = class {
123
- state;
124
- registry;
53
+ // src/core/reactive-engine.ts
54
+ var ReactiveLogicEngine2 = class _ReactiveLogicEngine {
55
+ _state;
56
+ _subscribers = /* @__PURE__ */ new Set();
57
+ _contextProxy;
58
+ _factsProxy;
59
+ _metaProxy;
60
+ _batchDepth = 0;
61
+ _pendingNotification = false;
62
+ _proxyCache = /* @__PURE__ */ new WeakMap();
63
+ // Array methods that mutate the array
64
+ static ARRAY_MUTATORS = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"];
125
65
  constructor(options) {
126
- this.registry = options.registry;
127
- this.state = {
66
+ this._state = {
128
67
  context: options.initialContext,
129
68
  facts: options.initialFacts ?? [],
130
- meta: options.initialMeta ?? {},
131
- protocolVersion: PRAXIS_PROTOCOL_VERSION
132
- };
133
- }
134
- /**
135
- * Get the current state (immutable copy)
136
- */
137
- getState() {
138
- return {
139
- context: safeClone(this.state.context),
140
- facts: [...this.state.facts],
141
- meta: this.state.meta ? safeClone(this.state.meta) : void 0,
142
- protocolVersion: this.state.protocolVersion
69
+ meta: options.initialMeta ?? {}
143
70
  };
71
+ this._contextProxy = this._createReactiveProxy(this._state.context);
72
+ this._factsProxy = this._createReactiveProxy(this._state.facts);
73
+ this._metaProxy = this._createReactiveProxy(this._state.meta);
144
74
  }
145
75
  /**
146
- * Get the current context
76
+ * Create a reactive proxy that notifies subscribers on changes.
77
+ * Uses a WeakMap cache to avoid creating multiple proxies for the same object.
147
78
  */
148
- getContext() {
149
- return safeClone(this.state.context);
150
- }
151
- /**
152
- * Get current facts
153
- */
154
- getFacts() {
155
- return [...this.state.facts];
156
- }
157
- /**
158
- * Process events through the engine.
159
- * Applies all registered rules and checks all registered constraints.
160
- *
161
- * @param events Events to process
162
- * @returns Result with new state and diagnostics
163
- */
164
- step(events) {
165
- const config = {
166
- ruleIds: this.registry.getRuleIds(),
167
- constraintIds: this.registry.getConstraintIds()
79
+ _createReactiveProxy(target) {
80
+ const cached = this._proxyCache.get(target);
81
+ if (cached) {
82
+ return cached;
83
+ }
84
+ const self = this;
85
+ const handler = {
86
+ get(obj, prop) {
87
+ const value = Reflect.get(obj, prop);
88
+ if (value && typeof value === "object") {
89
+ return self._createReactiveProxy(value);
90
+ }
91
+ if (Array.isArray(obj) && typeof value === "function") {
92
+ if (_ReactiveLogicEngine.ARRAY_MUTATORS.includes(prop)) {
93
+ return function(...args) {
94
+ const result = value.apply(obj, args);
95
+ self._notify();
96
+ return result;
97
+ };
98
+ }
99
+ }
100
+ return value;
101
+ },
102
+ set(obj, prop, value) {
103
+ const oldValue = obj[prop];
104
+ const result = Reflect.set(obj, prop, value);
105
+ if (oldValue !== value) {
106
+ self._notify();
107
+ }
108
+ return result;
109
+ },
110
+ deleteProperty(obj, prop) {
111
+ const result = Reflect.deleteProperty(obj, prop);
112
+ self._notify();
113
+ return result;
114
+ }
168
115
  };
169
- return this.stepWithConfig(events, config);
116
+ const proxy = new Proxy(target, handler);
117
+ this._proxyCache.set(target, proxy);
118
+ return proxy;
170
119
  }
171
120
  /**
172
- * Process events with specific rule and constraint configuration.
173
- *
174
- * @param events Events to process
175
- * @param config Step configuration
176
- * @returns Result with new state and diagnostics
121
+ * Notify all subscribers of state changes
177
122
  */
178
- stepWithConfig(events, config) {
179
- const diagnostics = [];
180
- let newState = { ...this.state };
181
- const newFacts = [];
182
- for (const ruleId of config.ruleIds) {
183
- const rule = this.registry.getRule(ruleId);
184
- if (!rule) {
185
- diagnostics.push({
186
- kind: "rule-error",
187
- message: `Rule "${ruleId}" not found in registry`,
188
- data: { ruleId }
189
- });
190
- continue;
191
- }
192
- try {
193
- const ruleFacts = rule.impl(newState, events);
194
- newFacts.push(...ruleFacts);
195
- } catch (error) {
196
- diagnostics.push({
197
- kind: "rule-error",
198
- message: `Error executing rule "${ruleId}": ${error instanceof Error ? error.message : String(error)}`,
199
- data: { ruleId, error }
200
- });
201
- }
123
+ _notify() {
124
+ if (this._batchDepth > 0) {
125
+ this._pendingNotification = true;
126
+ return;
202
127
  }
203
- newState = {
204
- ...newState,
205
- facts: [...newState.facts, ...newFacts]
128
+ const currentState = {
129
+ context: this._contextProxy,
130
+ facts: this._factsProxy,
131
+ meta: this._metaProxy
206
132
  };
207
- for (const constraintId of config.constraintIds) {
208
- const constraint = this.registry.getConstraint(constraintId);
209
- if (!constraint) {
210
- diagnostics.push({
211
- kind: "constraint-violation",
212
- message: `Constraint "${constraintId}" not found in registry`,
213
- data: { constraintId }
214
- });
215
- continue;
216
- }
133
+ this._subscribers.forEach((callback) => {
217
134
  try {
218
- const result = constraint.impl(newState);
219
- if (result === false) {
220
- diagnostics.push({
221
- kind: "constraint-violation",
222
- message: `Constraint "${constraintId}" violated`,
223
- data: { constraintId, description: constraint.description }
224
- });
225
- } else if (typeof result === "string") {
226
- diagnostics.push({
227
- kind: "constraint-violation",
228
- message: result,
229
- data: { constraintId, description: constraint.description }
230
- });
231
- }
135
+ callback(currentState);
232
136
  } catch (error) {
233
- diagnostics.push({
234
- kind: "constraint-violation",
235
- message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
236
- data: { constraintId, error }
237
- });
137
+ console.error("Error in reactive engine subscriber:", error);
238
138
  }
239
- }
240
- this.state = newState;
241
- return {
242
- state: newState,
243
- diagnostics
244
- };
245
- }
246
- /**
247
- * Update the context directly (for exceptional cases).
248
- * Generally, context should be updated through rules.
249
- *
250
- * @param updater Function that produces new context from old context
251
- */
252
- updateContext(updater) {
253
- this.state = {
254
- ...this.state,
255
- context: updater(this.state.context)
256
- };
257
- }
258
- /**
259
- * Add facts directly (for exceptional cases).
260
- * Generally, facts should be added through rules.
261
- *
262
- * @param facts Facts to add
263
- */
264
- addFacts(facts) {
265
- this.state = {
266
- ...this.state,
267
- facts: [...this.state.facts, ...facts]
268
- };
269
- }
270
- /**
271
- * Clear all facts
272
- */
273
- clearFacts() {
274
- this.state = {
275
- ...this.state,
276
- facts: []
277
- };
139
+ });
278
140
  }
279
141
  /**
280
- * Reset the engine to initial state
142
+ * Get the full state object
281
143
  */
282
- reset(options) {
283
- this.state = {
284
- context: options.initialContext,
285
- facts: options.initialFacts ?? [],
286
- meta: options.initialMeta ?? {},
287
- protocolVersion: PRAXIS_PROTOCOL_VERSION
288
- };
289
- }
290
- };
291
- function createPraxisEngine(options) {
292
- return new LogicEngine(options);
293
- }
294
-
295
- // src/core/reactive-engine.svelte.ts
296
- import * as $ from "svelte/internal/client";
297
- var ReactiveLogicEngine = class {
298
- #state = (
299
- // The single source of truth, reactive by default
300
- // We use $state.raw for things that shouldn't be deeply reactive if needed,
301
- // but for context we usually want deep reactivity.
302
- $.state($.proxy({ context: {}, facts: [], meta: {} }))
303
- );
304
144
  get state() {
305
- return $.get(this.#state);
306
- }
307
- set state(value) {
308
- $.set(this.#state, value, true);
309
- }
310
- constructor(options) {
311
- this.state.context = options.initialContext;
312
- this.state.facts = options.initialFacts ?? [];
313
- this.state.meta = options.initialMeta ?? {};
145
+ return {
146
+ context: this._contextProxy,
147
+ facts: this._factsProxy,
148
+ meta: this._metaProxy
149
+ };
314
150
  }
315
151
  /**
316
- * Access the reactive context directly.
317
- * Consumers can use this in $derived() or $effect().
152
+ * Access the reactive context.
153
+ * Changes to this object will trigger subscriber notifications.
318
154
  */
319
155
  get context() {
320
- return this.state.context;
156
+ return this._contextProxy;
321
157
  }
322
158
  /**
323
159
  * Access the reactive facts list.
160
+ * Changes to this array will trigger subscriber notifications.
324
161
  */
325
162
  get facts() {
326
- return this.state.facts;
163
+ return this._factsProxy;
164
+ }
165
+ /**
166
+ * Access the reactive metadata.
167
+ * Changes to this object will trigger subscriber notifications.
168
+ */
169
+ get meta() {
170
+ return this._metaProxy;
327
171
  }
328
172
  /**
329
173
  * Apply a mutation to the state.
330
174
  * This is the "Action" or "Rule" equivalent.
175
+ * Mutations are batched - notifications only happen once per apply call.
331
176
  *
332
177
  * @param mutator A function that receives the state and modifies it.
333
178
  */
334
179
  apply(mutator) {
335
- mutator(this.state);
180
+ this._batchDepth++;
181
+ try {
182
+ mutator({
183
+ context: this._contextProxy,
184
+ facts: this._factsProxy,
185
+ meta: this._metaProxy
186
+ });
187
+ } finally {
188
+ this._batchDepth--;
189
+ if (this._batchDepth === 0 && this._pendingNotification) {
190
+ this._pendingNotification = false;
191
+ this._notify();
192
+ }
193
+ }
336
194
  }
337
195
  /**
338
- * Access the reactive meta.
196
+ * Subscribe to state changes.
197
+ * Returns an unsubscribe function.
198
+ *
199
+ * @param callback Function to call when state changes
200
+ * @returns Unsubscribe function
339
201
  */
340
- get meta() {
341
- return this.state.meta;
202
+ subscribe(callback) {
203
+ this._subscribers.add(callback);
204
+ try {
205
+ callback({
206
+ context: this._contextProxy,
207
+ facts: this._factsProxy,
208
+ meta: this._metaProxy
209
+ });
210
+ } catch (error) {
211
+ console.error("Error in reactive engine subscriber:", error);
212
+ }
213
+ return () => {
214
+ this._subscribers.delete(callback);
215
+ };
216
+ }
217
+ /**
218
+ * Create a derived/computed value from the state.
219
+ * The selector function will be called whenever the state changes.
220
+ *
221
+ * @param selector Function to extract derived value from state
222
+ * @returns Object with subscribe method for reactive updates
223
+ */
224
+ $derived(selector) {
225
+ const subscribers = /* @__PURE__ */ new Set();
226
+ let currentValue = selector({
227
+ context: this._contextProxy,
228
+ facts: this._factsProxy,
229
+ meta: this._metaProxy
230
+ });
231
+ this.subscribe(() => {
232
+ const newValue = selector({
233
+ context: this._contextProxy,
234
+ facts: this._factsProxy,
235
+ meta: this._metaProxy
236
+ });
237
+ if (newValue !== currentValue) {
238
+ currentValue = newValue;
239
+ subscribers.forEach((callback) => {
240
+ try {
241
+ callback(currentValue);
242
+ } catch (error) {
243
+ console.error("Error in derived value subscriber:", error);
244
+ }
245
+ });
246
+ }
247
+ });
248
+ return {
249
+ subscribe: (callback) => {
250
+ subscribers.add(callback);
251
+ try {
252
+ callback(currentValue);
253
+ } catch (error) {
254
+ console.error("Error in derived value subscriber:", error);
255
+ }
256
+ return () => {
257
+ subscribers.delete(callback);
258
+ };
259
+ }
260
+ };
342
261
  }
343
262
  };
263
+ function createReactiveEngine2(options) {
264
+ return new ReactiveLogicEngine2(options);
265
+ }
344
266
 
345
267
  // src/core/actors.ts
346
268
  var ActorManager = class {
@@ -429,7 +351,7 @@ var ActorManager = class {
429
351
  /**
430
352
  * Notify active actors of a state change
431
353
  */
432
- async notifyStateChange(state2) {
354
+ async notifyStateChange(state) {
433
355
  if (!this.engine) {
434
356
  return;
435
357
  }
@@ -437,7 +359,7 @@ var ActorManager = class {
437
359
  for (const actorId of this.activeActors) {
438
360
  const actor = this.actors.get(actorId);
439
361
  if (actor?.onStateChange) {
440
- const result = actor.onStateChange(state2, this.engine);
362
+ const result = actor.onStateChange(state, this.engine);
441
363
  if (result instanceof Promise) {
442
364
  promises.push(result);
443
365
  }
@@ -915,14 +837,14 @@ var PraxisDBStore = class {
915
837
  async checkConstraints(newFacts) {
916
838
  const constraints = this.registry.getAllConstraints();
917
839
  const errors = [];
918
- const state2 = {
840
+ const state = {
919
841
  context: this.context,
920
842
  facts: newFacts,
921
843
  meta: {}
922
844
  };
923
845
  for (const constraint of constraints) {
924
846
  try {
925
- const result = constraint.impl(state2);
847
+ const result = constraint.impl(state);
926
848
  if (result === false) {
927
849
  errors.push(`Constraint "${constraint.id}" violated`);
928
850
  } else if (typeof result === "string") {
@@ -956,7 +878,7 @@ var PraxisDBStore = class {
956
878
  */
957
879
  async triggerRulesForEvents(events) {
958
880
  const rules = this.registry.getAllRules();
959
- const state2 = {
881
+ const state = {
960
882
  context: this.context,
961
883
  facts: [],
962
884
  meta: {}
@@ -964,7 +886,7 @@ var PraxisDBStore = class {
964
886
  const derivedFacts = [];
965
887
  for (const rule of rules) {
966
888
  try {
967
- const facts = rule.impl(state2, events);
889
+ const facts = rule.impl(state, events);
968
890
  derivedFacts.push(...facts);
969
891
  } catch (error) {
970
892
  this.onRuleError(rule.id, error);
@@ -1006,54 +928,6 @@ function createPraxisDBStore(db, registry, initialContext, onRuleError) {
1006
928
  return new PraxisDBStore({ db, registry, initialContext, onRuleError });
1007
929
  }
1008
930
 
1009
- // src/core/pluresdb/adapter.ts
1010
- var InMemoryPraxisDB = class {
1011
- store = /* @__PURE__ */ new Map();
1012
- watchers = /* @__PURE__ */ new Map();
1013
- async get(key) {
1014
- return this.store.get(key);
1015
- }
1016
- async set(key, value) {
1017
- this.store.set(key, value);
1018
- const keyWatchers = this.watchers.get(key);
1019
- if (keyWatchers) {
1020
- for (const callback of keyWatchers) {
1021
- callback(value);
1022
- }
1023
- }
1024
- }
1025
- watch(key, callback) {
1026
- if (!this.watchers.has(key)) {
1027
- this.watchers.set(key, /* @__PURE__ */ new Set());
1028
- }
1029
- const watchers = this.watchers.get(key);
1030
- const wrappedCallback = (val) => callback(val);
1031
- watchers.add(wrappedCallback);
1032
- return () => {
1033
- watchers.delete(wrappedCallback);
1034
- if (watchers.size === 0) {
1035
- this.watchers.delete(key);
1036
- }
1037
- };
1038
- }
1039
- /**
1040
- * Get all keys (for testing/debugging)
1041
- */
1042
- keys() {
1043
- return Array.from(this.store.keys());
1044
- }
1045
- /**
1046
- * Clear all data (for testing)
1047
- */
1048
- clear() {
1049
- this.store.clear();
1050
- this.watchers.clear();
1051
- }
1052
- };
1053
- function createInMemoryDB() {
1054
- return new InMemoryPraxisDB();
1055
- }
1056
-
1057
931
  // src/core/pluresdb/schema-registry.ts
1058
932
  function getSchemaPath(schemaName) {
1059
933
  return `${PRAXIS_PATHS.SCHEMAS}/${schemaName}`;
@@ -1374,447 +1248,6 @@ function attachUnumToEngine(_engine, _adapter, _channelId) {
1374
1248
  };
1375
1249
  }
1376
1250
 
1377
- // src/integrations/state-docs.ts
1378
- var StateDocsGenerator = class {
1379
- config;
1380
- constructor(config) {
1381
- this.config = {
1382
- target: "./docs",
1383
- globs: ["**/*.ts", "**/*.js"],
1384
- visualization: {
1385
- format: "mermaid",
1386
- exportPng: false,
1387
- theme: "default"
1388
- },
1389
- template: {
1390
- toc: true,
1391
- timestamp: true
1392
- },
1393
- ...config
1394
- };
1395
- }
1396
- /**
1397
- * Generate documentation from a Praxis schema
1398
- */
1399
- generateFromSchema(schema) {
1400
- const docs = [];
1401
- docs.push(this.generateSchemaReadme(schema));
1402
- if (schema.models && schema.models.length > 0) {
1403
- docs.push(this.generateModelsDoc(schema));
1404
- }
1405
- if (schema.components && schema.components.length > 0) {
1406
- docs.push(this.generateComponentsDoc(schema));
1407
- }
1408
- if (schema.logic && schema.logic.length > 0) {
1409
- for (const logic of schema.logic) {
1410
- docs.push(this.generateLogicDoc(logic));
1411
- docs.push(this.generateLogicDiagram(logic));
1412
- }
1413
- }
1414
- return docs;
1415
- }
1416
- /**
1417
- * Generate documentation from a Praxis registry
1418
- */
1419
- generateFromModule(module) {
1420
- const docs = [];
1421
- const rules = module.rules;
1422
- const constraints = module.constraints;
1423
- docs.push(this.generateRulesDoc(rules));
1424
- docs.push(this.generateConstraintsDoc(constraints));
1425
- docs.push(this.generateRegistryDiagram(rules, constraints));
1426
- return docs;
1427
- }
1428
- /**
1429
- * Generate the main schema README
1430
- */
1431
- generateSchemaReadme(schema) {
1432
- const lines = [];
1433
- if (this.config.template?.header) {
1434
- lines.push(this.config.template.header);
1435
- lines.push("");
1436
- }
1437
- lines.push(`# ${schema.name || this.config.projectTitle}`);
1438
- lines.push("");
1439
- if (schema.description) {
1440
- lines.push(schema.description);
1441
- lines.push("");
1442
- }
1443
- if (this.config.template?.toc) {
1444
- lines.push("## Table of Contents");
1445
- lines.push("");
1446
- lines.push("- [Overview](#overview)");
1447
- if (schema.models && schema.models.length > 0) {
1448
- lines.push("- [Models](#models)");
1449
- }
1450
- if (schema.components && schema.components.length > 0) {
1451
- lines.push("- [Components](#components)");
1452
- }
1453
- if (schema.logic && schema.logic.length > 0) {
1454
- lines.push("- [Logic](#logic)");
1455
- }
1456
- lines.push("");
1457
- }
1458
- lines.push("## Overview");
1459
- lines.push("");
1460
- lines.push(`**Version:** ${schema.version}`);
1461
- lines.push("");
1462
- lines.push("### Statistics");
1463
- lines.push("");
1464
- lines.push("| Category | Count |");
1465
- lines.push("|----------|-------|");
1466
- lines.push(`| Models | ${schema.models?.length || 0} |`);
1467
- lines.push(`| Components | ${schema.components?.length || 0} |`);
1468
- lines.push(`| Logic Modules | ${schema.logic?.length || 0} |`);
1469
- lines.push("");
1470
- if (schema.models && schema.models.length > 0) {
1471
- lines.push("## Models");
1472
- lines.push("");
1473
- for (const model of schema.models) {
1474
- lines.push(`### ${model.name}`);
1475
- lines.push("");
1476
- if (model.description) {
1477
- lines.push(model.description);
1478
- lines.push("");
1479
- }
1480
- lines.push("**Fields:**");
1481
- lines.push("");
1482
- lines.push("| Name | Type | Required |");
1483
- lines.push("|------|------|----------|");
1484
- for (const field of model.fields) {
1485
- const required = field.optional ? "No" : "Yes";
1486
- lines.push(`| ${field.name} | ${field.type} | ${required} |`);
1487
- }
1488
- lines.push("");
1489
- }
1490
- }
1491
- if (schema.components && schema.components.length > 0) {
1492
- lines.push("## Components");
1493
- lines.push("");
1494
- for (const component of schema.components) {
1495
- lines.push(`### ${component.name}`);
1496
- lines.push("");
1497
- lines.push(`**Type:** ${component.type}`);
1498
- lines.push("");
1499
- if (component.description) {
1500
- lines.push(component.description);
1501
- lines.push("");
1502
- }
1503
- if (component.model) {
1504
- lines.push(`**Model:** ${component.model}`);
1505
- lines.push("");
1506
- }
1507
- }
1508
- }
1509
- if (schema.logic && schema.logic.length > 0) {
1510
- lines.push("## Logic");
1511
- lines.push("");
1512
- for (const logic of schema.logic) {
1513
- lines.push(`### ${logic.id}`);
1514
- lines.push("");
1515
- if (logic.description) {
1516
- lines.push(logic.description);
1517
- lines.push("");
1518
- }
1519
- if (logic.events && logic.events.length > 0) {
1520
- lines.push("**Events:**");
1521
- lines.push("");
1522
- for (const event of logic.events) {
1523
- lines.push(`- \`${event.tag}\`: ${event.description || ""}`);
1524
- }
1525
- lines.push("");
1526
- }
1527
- if (logic.facts && logic.facts.length > 0) {
1528
- lines.push("**Facts:**");
1529
- lines.push("");
1530
- for (const fact of logic.facts) {
1531
- lines.push(`- \`${fact.tag}\`: ${fact.description || ""}`);
1532
- }
1533
- lines.push("");
1534
- }
1535
- if (logic.rules && logic.rules.length > 0) {
1536
- lines.push("**Rules:**");
1537
- lines.push("");
1538
- for (const rule of logic.rules) {
1539
- lines.push(`- \`${rule.id}\`: ${rule.description || ""}`);
1540
- }
1541
- lines.push("");
1542
- }
1543
- }
1544
- }
1545
- if (this.config.template?.timestamp) {
1546
- lines.push("---");
1547
- lines.push("");
1548
- lines.push(`*Generated on ${(/* @__PURE__ */ new Date()).toISOString()} by State-Docs*`);
1549
- }
1550
- if (this.config.template?.footer) {
1551
- lines.push("");
1552
- lines.push(this.config.template.footer);
1553
- }
1554
- return {
1555
- path: `${this.config.target}/README.md`,
1556
- content: lines.join("\n"),
1557
- type: "markdown"
1558
- };
1559
- }
1560
- /**
1561
- * Generate models documentation
1562
- */
1563
- generateModelsDoc(schema) {
1564
- const lines = [
1565
- "# Models",
1566
- "",
1567
- "This document describes all data models defined in the schema.",
1568
- ""
1569
- ];
1570
- if (schema.models) {
1571
- for (const model of schema.models) {
1572
- lines.push(`## ${model.name}`);
1573
- lines.push("");
1574
- if (model.description) {
1575
- lines.push(model.description);
1576
- lines.push("");
1577
- }
1578
- lines.push("### Fields");
1579
- lines.push("");
1580
- lines.push("| Name | Type | Required | Description |");
1581
- lines.push("|------|------|----------|-------------|");
1582
- for (const field of model.fields) {
1583
- const required = field.optional ? "No" : "Yes";
1584
- const description = field.description || "-";
1585
- lines.push(`| ${field.name} | \`${field.type}\` | ${required} | ${description} |`);
1586
- }
1587
- lines.push("");
1588
- if (model.indexes && model.indexes.length > 0) {
1589
- lines.push("### Indexes");
1590
- lines.push("");
1591
- for (const index of model.indexes) {
1592
- lines.push(`- **${index.name}**: \`${index.fields.join(", ")}\``);
1593
- }
1594
- lines.push("");
1595
- }
1596
- }
1597
- }
1598
- return {
1599
- path: `${this.config.target}/models.md`,
1600
- content: lines.join("\n"),
1601
- type: "markdown"
1602
- };
1603
- }
1604
- /**
1605
- * Generate components documentation
1606
- */
1607
- generateComponentsDoc(schema) {
1608
- const lines = [
1609
- "# Components",
1610
- "",
1611
- "This document describes all UI components defined in the schema.",
1612
- ""
1613
- ];
1614
- if (schema.components) {
1615
- for (const component of schema.components) {
1616
- lines.push(`## ${component.name}`);
1617
- lines.push("");
1618
- lines.push(`**Type:** ${component.type}`);
1619
- lines.push("");
1620
- if (component.description) {
1621
- lines.push(component.description);
1622
- lines.push("");
1623
- }
1624
- if (component.model) {
1625
- lines.push(
1626
- `**Associated Model:** [${component.model}](./models.md#${component.model.toLowerCase()})`
1627
- );
1628
- lines.push("");
1629
- }
1630
- }
1631
- }
1632
- return {
1633
- path: `${this.config.target}/components.md`,
1634
- content: lines.join("\n"),
1635
- type: "markdown"
1636
- };
1637
- }
1638
- /**
1639
- * Generate logic documentation
1640
- */
1641
- generateLogicDoc(logic) {
1642
- const lines = [`# ${logic.id}`, ""];
1643
- if (logic.description) {
1644
- lines.push(logic.description);
1645
- lines.push("");
1646
- }
1647
- if (logic.events && logic.events.length > 0) {
1648
- lines.push("## Events");
1649
- lines.push("");
1650
- lines.push("| Event | Description | Payload |");
1651
- lines.push("|-------|-------------|---------|");
1652
- for (const event of logic.events) {
1653
- const payload = event.payload ? Object.entries(event.payload).map(([k, v]) => `${k}: ${v}`).join(", ") : "-";
1654
- lines.push(`| \`${event.tag}\` | ${event.description || "-"} | ${payload} |`);
1655
- }
1656
- lines.push("");
1657
- }
1658
- if (logic.facts && logic.facts.length > 0) {
1659
- lines.push("## Facts");
1660
- lines.push("");
1661
- lines.push("| Fact | Description | Payload |");
1662
- lines.push("|------|-------------|---------|");
1663
- for (const fact of logic.facts) {
1664
- const payload = fact.payload ? Object.entries(fact.payload).map(([k, v]) => `${k}: ${v}`).join(", ") : "-";
1665
- lines.push(`| \`${fact.tag}\` | ${fact.description || "-"} | ${payload} |`);
1666
- }
1667
- lines.push("");
1668
- }
1669
- if (logic.rules && logic.rules.length > 0) {
1670
- lines.push("## Rules");
1671
- lines.push("");
1672
- for (const rule of logic.rules) {
1673
- lines.push(`### ${rule.id}`);
1674
- lines.push("");
1675
- if (rule.description) {
1676
- lines.push(rule.description);
1677
- lines.push("");
1678
- }
1679
- if (rule.priority !== void 0) {
1680
- lines.push(`**Priority:** ${rule.priority}`);
1681
- lines.push("");
1682
- }
1683
- }
1684
- }
1685
- if (logic.constraints && logic.constraints.length > 0) {
1686
- lines.push("## Constraints");
1687
- lines.push("");
1688
- for (const constraint of logic.constraints) {
1689
- lines.push(`### ${constraint.id}`);
1690
- lines.push("");
1691
- if (constraint.description) {
1692
- lines.push(constraint.description);
1693
- lines.push("");
1694
- }
1695
- if (constraint.message) {
1696
- lines.push(`**Error Message:** ${constraint.message}`);
1697
- lines.push("");
1698
- }
1699
- }
1700
- }
1701
- return {
1702
- path: `${this.config.target}/logic/${logic.id}.md`,
1703
- content: lines.join("\n"),
1704
- type: "markdown"
1705
- };
1706
- }
1707
- /**
1708
- * Generate Mermaid diagram for logic
1709
- */
1710
- generateLogicDiagram(logic) {
1711
- const lines = ["stateDiagram-v2"];
1712
- if (logic.events && logic.facts) {
1713
- lines.push(" [*] --> Processing");
1714
- for (const event of logic.events) {
1715
- lines.push(` Processing --> ${event.tag.replace(/[^a-zA-Z0-9]/g, "")}: ${event.tag}`);
1716
- }
1717
- for (const fact of logic.facts) {
1718
- lines.push(` ${fact.tag.replace(/[^a-zA-Z0-9]/g, "")} --> [*]`);
1719
- }
1720
- }
1721
- return {
1722
- path: `${this.config.target}/logic/${logic.id}.mmd`,
1723
- content: lines.join("\n"),
1724
- type: "mermaid"
1725
- };
1726
- }
1727
- /**
1728
- * Generate rules documentation
1729
- */
1730
- generateRulesDoc(rules) {
1731
- const lines = [
1732
- "# Rules",
1733
- "",
1734
- "This document describes all rules registered in the Praxis engine.",
1735
- ""
1736
- ];
1737
- for (const rule of rules) {
1738
- lines.push(`## ${rule.id}`);
1739
- lines.push("");
1740
- if (rule.description) {
1741
- lines.push(rule.description);
1742
- lines.push("");
1743
- }
1744
- if (rule.meta?.eventType) {
1745
- lines.push(`**Triggers on:** \`${rule.meta.eventType}\``);
1746
- lines.push("");
1747
- }
1748
- if (rule.meta?.priority !== void 0) {
1749
- lines.push(`**Priority:** ${rule.meta.priority}`);
1750
- lines.push("");
1751
- }
1752
- }
1753
- return {
1754
- path: `${this.config.target}/rules.md`,
1755
- content: lines.join("\n"),
1756
- type: "markdown"
1757
- };
1758
- }
1759
- /**
1760
- * Generate constraints documentation
1761
- */
1762
- generateConstraintsDoc(constraints) {
1763
- const lines = [
1764
- "# Constraints",
1765
- "",
1766
- "This document describes all constraints (invariants) registered in the Praxis engine.",
1767
- ""
1768
- ];
1769
- for (const constraint of constraints) {
1770
- lines.push(`## ${constraint.id}`);
1771
- lines.push("");
1772
- if (constraint.description) {
1773
- lines.push(constraint.description);
1774
- lines.push("");
1775
- }
1776
- if (constraint.meta?.errorMessage) {
1777
- lines.push(`**Error Message:** ${constraint.meta.errorMessage}`);
1778
- lines.push("");
1779
- }
1780
- }
1781
- return {
1782
- path: `${this.config.target}/constraints.md`,
1783
- content: lines.join("\n"),
1784
- type: "markdown"
1785
- };
1786
- }
1787
- /**
1788
- * Generate state diagram from registry
1789
- */
1790
- generateRegistryDiagram(rules, constraints) {
1791
- const lines = ["graph TD", " subgraph Rules"];
1792
- for (const rule of rules) {
1793
- const id = rule.id.replace(/[^a-zA-Z0-9]/g, "_");
1794
- lines.push(` ${id}["${rule.id}"]`);
1795
- }
1796
- lines.push(" end");
1797
- lines.push(" subgraph Constraints");
1798
- for (const constraint of constraints) {
1799
- const id = constraint.id.replace(/[^a-zA-Z0-9]/g, "_");
1800
- lines.push(` ${id}["${constraint.id}"]`);
1801
- }
1802
- lines.push(" end");
1803
- return {
1804
- path: `${this.config.target}/state-diagram.mmd`,
1805
- content: lines.join("\n"),
1806
- type: "mermaid"
1807
- };
1808
- }
1809
- };
1810
- function createStateDocsGenerator(config) {
1811
- return new StateDocsGenerator(config);
1812
- }
1813
- function generateDocs(schema, config) {
1814
- const generator = createStateDocsGenerator(config);
1815
- return generator.generateFromSchema(schema);
1816
- }
1817
-
1818
1251
  // src/integrations/tauri.ts
1819
1252
  function createMockTauriBridge() {
1820
1253
  const eventHandlers = /* @__PURE__ */ new Map();
@@ -1934,8 +1367,8 @@ function createMockTauriBridge() {
1934
1367
  function createTauriPraxisAdapter(options) {
1935
1368
  const { bridge, statePath = "praxis-state.json", eventsPath = "praxis-events.json" } = options;
1936
1369
  return {
1937
- async saveState(state2) {
1938
- const json = JSON.stringify(state2, null, 2);
1370
+ async saveState(state) {
1371
+ const json = JSON.stringify(state, null, 2);
1939
1372
  await bridge.fs.writeTextFile(statePath, json);
1940
1373
  },
1941
1374
  async loadState() {
@@ -2034,13 +1467,147 @@ function generateTauriConfig(config) {
2034
1467
  plugins: Object.fromEntries((config.plugins || []).map((p) => [p.name, p.config || {}]))
2035
1468
  };
2036
1469
  }
1470
+
1471
+ // src/integrations/unified.ts
1472
+ async function createUnifiedApp(config) {
1473
+ const { createPraxisEngine: createPraxisEngine2 } = await import("./engine-2DQBKBJC.js");
1474
+ const { createInMemoryDB: createInMemoryDB2 } = await import("./adapter-K6DOX6XS.js");
1475
+ const db = config.db || createInMemoryDB2();
1476
+ const pluresdb = createPluresDBAdapter({
1477
+ db,
1478
+ registry: config.registry,
1479
+ initialContext: config.initialContext
1480
+ });
1481
+ const engine = createPraxisEngine2({
1482
+ initialContext: config.initialContext,
1483
+ registry: config.registry
1484
+ });
1485
+ pluresdb.attachEngine(engine);
1486
+ const disposers = [];
1487
+ let unum;
1488
+ let channel;
1489
+ if (config.enableUnum) {
1490
+ const fullIdentity = config.unumIdentity ? {
1491
+ ...config.unumIdentity,
1492
+ id: generateId(),
1493
+ createdAt: Date.now()
1494
+ } : void 0;
1495
+ unum = await createUnumAdapter({
1496
+ db,
1497
+ identity: fullIdentity,
1498
+ realtime: true
1499
+ });
1500
+ channel = await unum.createChannel(
1501
+ config.unumIdentity?.name || "praxis-app",
1502
+ []
1503
+ );
1504
+ const unumDisposer = attachUnumToEngine(engine, unum, channel.id);
1505
+ disposers.push(unumDisposer);
1506
+ }
1507
+ let docs;
1508
+ let generateDocs2;
1509
+ if (config.enableDocs && config.docsConfig) {
1510
+ docs = createStateDocsGenerator({
1511
+ projectTitle: config.docsConfig.projectTitle,
1512
+ target: config.docsConfig.target || "./docs"
1513
+ });
1514
+ generateDocs2 = () => {
1515
+ const module = {
1516
+ rules: config.registry.getAllRules(),
1517
+ constraints: config.registry.getAllConstraints()
1518
+ };
1519
+ return docs.generateFromModule(module);
1520
+ };
1521
+ }
1522
+ let canvas;
1523
+ if (config.schema) {
1524
+ canvas = schemaToCanvas(config.schema, { layout: "hierarchical" });
1525
+ }
1526
+ return {
1527
+ engine,
1528
+ pluresdb,
1529
+ unum,
1530
+ channel,
1531
+ docs,
1532
+ canvas,
1533
+ generateDocs: generateDocs2,
1534
+ dispose: () => {
1535
+ pluresdb.dispose();
1536
+ if (unum) {
1537
+ unum.disconnect().catch((err) => {
1538
+ console.warn("Warning: Error during Unum disconnect:", err);
1539
+ });
1540
+ }
1541
+ for (const disposer of disposers) {
1542
+ disposer();
1543
+ }
1544
+ }
1545
+ };
1546
+ }
1547
+ async function attachAllIntegrations(engine, registry, options = {}) {
1548
+ const { createInMemoryDB: createInMemoryDB2 } = await import("./adapter-K6DOX6XS.js");
1549
+ const db = options.db || createInMemoryDB2();
1550
+ const pluresdb = createPluresDBAdapter({
1551
+ db,
1552
+ registry,
1553
+ initialContext: engine.getContext()
1554
+ });
1555
+ pluresdb.attachEngine(engine);
1556
+ const disposers = [];
1557
+ let unum;
1558
+ let channel;
1559
+ if (options.enableUnum) {
1560
+ const fullIdentity = options.unumIdentity ? {
1561
+ ...options.unumIdentity,
1562
+ id: generateId(),
1563
+ createdAt: Date.now()
1564
+ } : void 0;
1565
+ unum = await createUnumAdapter({
1566
+ db,
1567
+ identity: fullIdentity,
1568
+ realtime: true
1569
+ });
1570
+ channel = await unum.createChannel(
1571
+ options.unumIdentity?.name || "praxis-app",
1572
+ []
1573
+ );
1574
+ const unumDisposer = attachUnumToEngine(engine, unum, channel.id);
1575
+ disposers.push(unumDisposer);
1576
+ }
1577
+ let docs;
1578
+ if (options.enableDocs && options.docsConfig) {
1579
+ docs = createStateDocsGenerator({
1580
+ projectTitle: options.docsConfig.projectTitle,
1581
+ target: options.docsConfig.target || "./docs"
1582
+ });
1583
+ }
1584
+ return {
1585
+ pluresdb,
1586
+ unum,
1587
+ channel,
1588
+ docs,
1589
+ dispose: () => {
1590
+ pluresdb.dispose();
1591
+ if (unum) {
1592
+ unum.disconnect().catch((err) => {
1593
+ console.warn("Warning: Error during Unum disconnect:", err);
1594
+ });
1595
+ }
1596
+ for (const disposer of disposers) {
1597
+ disposer();
1598
+ }
1599
+ }
1600
+ };
1601
+ }
2037
1602
  export {
2038
1603
  ActorManager,
1604
+ ReactiveLogicEngine2 as FrameworkAgnosticReactiveEngine,
2039
1605
  InMemoryPraxisDB,
2040
1606
  LogicEngine,
2041
1607
  PRAXIS_PATHS,
2042
1608
  PRAXIS_PROTOCOL_VERSION,
2043
1609
  PluresDBGenerator,
1610
+ PluresDBPraxisAdapter,
2044
1611
  PraxisDBStore,
2045
1612
  PraxisRegistry,
2046
1613
  PraxisSchemaRegistry,
@@ -2048,6 +1615,7 @@ export {
2048
1615
  RegistryIntrospector,
2049
1616
  StateDocsGenerator,
2050
1617
  TerminalAdapter,
1618
+ attachAllIntegrations,
2051
1619
  attachTauriToEngine,
2052
1620
  attachToEngine,
2053
1621
  attachUnumToEngine,
@@ -2055,20 +1623,24 @@ export {
2055
1623
  canvasToSchema,
2056
1624
  canvasToYaml,
2057
1625
  createCanvasEditor,
1626
+ createReactiveEngine2 as createFrameworkAgnosticReactiveEngine,
2058
1627
  createInMemoryDB,
2059
1628
  createIntrospector,
2060
1629
  createMockExecutor,
2061
1630
  createMockTauriBridge,
1631
+ createPluresDB,
2062
1632
  createPluresDBAdapter,
2063
1633
  createPluresDBGenerator,
2064
1634
  createPraxisDBStore,
2065
1635
  createPraxisEngine,
1636
+ createReactiveEngine,
2066
1637
  createSchemaRegistry,
2067
1638
  createSchemaTemplate,
2068
1639
  createStateDocsGenerator,
2069
1640
  createTauriPraxisAdapter,
2070
1641
  createTerminalAdapter,
2071
1642
  createTimerActor,
1643
+ createUnifiedApp,
2072
1644
  createUnumAdapter,
2073
1645
  defineConstraint,
2074
1646
  defineEvent,