@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.
- package/README.md +68 -7
- package/dist/browser/chunk-R45WXWKH.js +345 -0
- package/dist/browser/index.d.ts +171 -11
- package/dist/browser/index.js +279 -277
- package/dist/browser/integrations/svelte.d.ts +3 -1
- package/dist/browser/integrations/svelte.js +7 -0
- package/dist/browser/{engine-BjdqxeXG.d.ts → reactive-engine.svelte-C9OpcTHf.d.ts} +87 -1
- package/dist/node/chunk-R45WXWKH.js +345 -0
- package/dist/node/components/index.d.cts +2 -2
- package/dist/node/components/index.d.ts +2 -2
- package/dist/node/index.cjs +343 -8
- package/dist/node/index.d.cts +108 -15
- package/dist/node/index.d.ts +108 -15
- package/dist/node/index.js +279 -278
- package/dist/node/integrations/svelte.cjs +357 -2
- package/dist/node/integrations/svelte.d.cts +3 -1
- package/dist/node/integrations/svelte.d.ts +3 -1
- package/dist/node/integrations/svelte.js +6 -0
- package/dist/node/{engine-CVJobhHm.d.cts → reactive-engine.svelte-1M4m_C_v.d.cts} +87 -1
- package/dist/node/{engine-1iqLe6_P.d.ts → reactive-engine.svelte-ChNFn4Hj.d.ts} +87 -1
- package/dist/node/{terminal-adapter-XLtCjjb_.d.cts → terminal-adapter-CDzxoLKR.d.cts} +68 -1
- package/dist/node/{terminal-adapter-07HGftGQ.d.ts → terminal-adapter-CWka-yL8.d.ts} +68 -1
- package/package.json +3 -2
- package/src/__tests__/reactive-engine.test.ts +516 -0
- package/src/core/pluresdb/README.md +156 -0
- package/src/core/pluresdb/adapter.ts +165 -0
- package/src/core/pluresdb/index.ts +3 -3
- package/src/core/reactive-engine.svelte.ts +88 -19
- package/src/core/reactive-engine.ts +283 -30
- package/src/index.browser.ts +12 -0
- package/src/index.ts +12 -0
- package/src/integrations/pluresdb.ts +2 -2
- package/src/integrations/svelte.ts +8 -0
package/dist/node/index.js
CHANGED
|
@@ -6,6 +6,14 @@ import {
|
|
|
6
6
|
schemaToCanvas,
|
|
7
7
|
validateWithGuardian
|
|
8
8
|
} from "./chunk-SRM3OPPM.js";
|
|
9
|
+
import {
|
|
10
|
+
LogicEngine,
|
|
11
|
+
PRAXIS_PROTOCOL_VERSION,
|
|
12
|
+
PraxisRegistry,
|
|
13
|
+
ReactiveLogicEngine,
|
|
14
|
+
createPraxisEngine,
|
|
15
|
+
createReactiveEngine
|
|
16
|
+
} from "./chunk-R45WXWKH.js";
|
|
9
17
|
import {
|
|
10
18
|
TerminalAdapter,
|
|
11
19
|
createMockExecutor,
|
|
@@ -29,318 +37,219 @@ import {
|
|
|
29
37
|
} from "./chunk-UATVJBNV.js";
|
|
30
38
|
import "./chunk-QGM4M3NI.js";
|
|
31
39
|
|
|
32
|
-
// src/core/
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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;
|
|
40
|
+
// src/core/reactive-engine.ts
|
|
41
|
+
var ReactiveLogicEngine2 = class _ReactiveLogicEngine {
|
|
42
|
+
_state;
|
|
43
|
+
_subscribers = /* @__PURE__ */ new Set();
|
|
44
|
+
_contextProxy;
|
|
45
|
+
_factsProxy;
|
|
46
|
+
_metaProxy;
|
|
47
|
+
_batchDepth = 0;
|
|
48
|
+
_pendingNotification = false;
|
|
49
|
+
_proxyCache = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
// Array methods that mutate the array
|
|
51
|
+
static ARRAY_MUTATORS = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"];
|
|
125
52
|
constructor(options) {
|
|
126
|
-
this.
|
|
127
|
-
this.state = {
|
|
53
|
+
this._state = {
|
|
128
54
|
context: options.initialContext,
|
|
129
55
|
facts: options.initialFacts ?? [],
|
|
130
|
-
meta: options.initialMeta ?? {}
|
|
131
|
-
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
56
|
+
meta: options.initialMeta ?? {}
|
|
132
57
|
};
|
|
58
|
+
this._contextProxy = this._createReactiveProxy(this._state.context);
|
|
59
|
+
this._factsProxy = this._createReactiveProxy(this._state.facts);
|
|
60
|
+
this._metaProxy = this._createReactiveProxy(this._state.meta);
|
|
133
61
|
}
|
|
134
62
|
/**
|
|
135
|
-
*
|
|
63
|
+
* Create a reactive proxy that notifies subscribers on changes.
|
|
64
|
+
* Uses a WeakMap cache to avoid creating multiple proxies for the same object.
|
|
136
65
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
66
|
+
_createReactiveProxy(target) {
|
|
67
|
+
const cached = this._proxyCache.get(target);
|
|
68
|
+
if (cached) {
|
|
69
|
+
return cached;
|
|
70
|
+
}
|
|
71
|
+
const self = this;
|
|
72
|
+
const handler = {
|
|
73
|
+
get(obj, prop) {
|
|
74
|
+
const value = Reflect.get(obj, prop);
|
|
75
|
+
if (value && typeof value === "object") {
|
|
76
|
+
return self._createReactiveProxy(value);
|
|
77
|
+
}
|
|
78
|
+
if (Array.isArray(obj) && typeof value === "function") {
|
|
79
|
+
if (_ReactiveLogicEngine.ARRAY_MUTATORS.includes(prop)) {
|
|
80
|
+
return function(...args) {
|
|
81
|
+
const result = value.apply(obj, args);
|
|
82
|
+
self._notify();
|
|
83
|
+
return result;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return value;
|
|
88
|
+
},
|
|
89
|
+
set(obj, prop, value) {
|
|
90
|
+
const oldValue = obj[prop];
|
|
91
|
+
const result = Reflect.set(obj, prop, value);
|
|
92
|
+
if (oldValue !== value) {
|
|
93
|
+
self._notify();
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
},
|
|
97
|
+
deleteProperty(obj, prop) {
|
|
98
|
+
const result = Reflect.deleteProperty(obj, prop);
|
|
99
|
+
self._notify();
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
168
102
|
};
|
|
169
|
-
|
|
103
|
+
const proxy = new Proxy(target, handler);
|
|
104
|
+
this._proxyCache.set(target, proxy);
|
|
105
|
+
return proxy;
|
|
170
106
|
}
|
|
171
107
|
/**
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* @param events Events to process
|
|
175
|
-
* @param config Step configuration
|
|
176
|
-
* @returns Result with new state and diagnostics
|
|
108
|
+
* Notify all subscribers of state changes
|
|
177
109
|
*/
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
}
|
|
110
|
+
_notify() {
|
|
111
|
+
if (this._batchDepth > 0) {
|
|
112
|
+
this._pendingNotification = true;
|
|
113
|
+
return;
|
|
202
114
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
facts:
|
|
115
|
+
const currentState = {
|
|
116
|
+
context: this._contextProxy,
|
|
117
|
+
facts: this._factsProxy,
|
|
118
|
+
meta: this._metaProxy
|
|
206
119
|
};
|
|
207
|
-
|
|
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
|
-
}
|
|
120
|
+
this._subscribers.forEach((callback) => {
|
|
217
121
|
try {
|
|
218
|
-
|
|
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
|
-
}
|
|
122
|
+
callback(currentState);
|
|
232
123
|
} catch (error) {
|
|
233
|
-
|
|
234
|
-
kind: "constraint-violation",
|
|
235
|
-
message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
236
|
-
data: { constraintId, error }
|
|
237
|
-
});
|
|
124
|
+
console.error("Error in reactive engine subscriber:", error);
|
|
238
125
|
}
|
|
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
|
-
};
|
|
126
|
+
});
|
|
278
127
|
}
|
|
279
128
|
/**
|
|
280
|
-
*
|
|
129
|
+
* Get the full state object
|
|
281
130
|
*/
|
|
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
131
|
get state() {
|
|
305
|
-
return
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
constructor(options) {
|
|
311
|
-
this.state.context = options.initialContext;
|
|
312
|
-
this.state.facts = options.initialFacts ?? [];
|
|
313
|
-
this.state.meta = options.initialMeta ?? {};
|
|
132
|
+
return {
|
|
133
|
+
context: this._contextProxy,
|
|
134
|
+
facts: this._factsProxy,
|
|
135
|
+
meta: this._metaProxy
|
|
136
|
+
};
|
|
314
137
|
}
|
|
315
138
|
/**
|
|
316
|
-
* Access the reactive context
|
|
317
|
-
*
|
|
139
|
+
* Access the reactive context.
|
|
140
|
+
* Changes to this object will trigger subscriber notifications.
|
|
318
141
|
*/
|
|
319
142
|
get context() {
|
|
320
|
-
return this.
|
|
143
|
+
return this._contextProxy;
|
|
321
144
|
}
|
|
322
145
|
/**
|
|
323
146
|
* Access the reactive facts list.
|
|
147
|
+
* Changes to this array will trigger subscriber notifications.
|
|
324
148
|
*/
|
|
325
149
|
get facts() {
|
|
326
|
-
return this.
|
|
150
|
+
return this._factsProxy;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Access the reactive metadata.
|
|
154
|
+
* Changes to this object will trigger subscriber notifications.
|
|
155
|
+
*/
|
|
156
|
+
get meta() {
|
|
157
|
+
return this._metaProxy;
|
|
327
158
|
}
|
|
328
159
|
/**
|
|
329
160
|
* Apply a mutation to the state.
|
|
330
161
|
* This is the "Action" or "Rule" equivalent.
|
|
162
|
+
* Mutations are batched - notifications only happen once per apply call.
|
|
331
163
|
*
|
|
332
164
|
* @param mutator A function that receives the state and modifies it.
|
|
333
165
|
*/
|
|
334
166
|
apply(mutator) {
|
|
335
|
-
|
|
167
|
+
this._batchDepth++;
|
|
168
|
+
try {
|
|
169
|
+
mutator({
|
|
170
|
+
context: this._contextProxy,
|
|
171
|
+
facts: this._factsProxy,
|
|
172
|
+
meta: this._metaProxy
|
|
173
|
+
});
|
|
174
|
+
} finally {
|
|
175
|
+
this._batchDepth--;
|
|
176
|
+
if (this._batchDepth === 0 && this._pendingNotification) {
|
|
177
|
+
this._pendingNotification = false;
|
|
178
|
+
this._notify();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
336
181
|
}
|
|
337
182
|
/**
|
|
338
|
-
*
|
|
183
|
+
* Subscribe to state changes.
|
|
184
|
+
* Returns an unsubscribe function.
|
|
185
|
+
*
|
|
186
|
+
* @param callback Function to call when state changes
|
|
187
|
+
* @returns Unsubscribe function
|
|
339
188
|
*/
|
|
340
|
-
|
|
341
|
-
|
|
189
|
+
subscribe(callback) {
|
|
190
|
+
this._subscribers.add(callback);
|
|
191
|
+
try {
|
|
192
|
+
callback({
|
|
193
|
+
context: this._contextProxy,
|
|
194
|
+
facts: this._factsProxy,
|
|
195
|
+
meta: this._metaProxy
|
|
196
|
+
});
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error("Error in reactive engine subscriber:", error);
|
|
199
|
+
}
|
|
200
|
+
return () => {
|
|
201
|
+
this._subscribers.delete(callback);
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Create a derived/computed value from the state.
|
|
206
|
+
* The selector function will be called whenever the state changes.
|
|
207
|
+
*
|
|
208
|
+
* @param selector Function to extract derived value from state
|
|
209
|
+
* @returns Object with subscribe method for reactive updates
|
|
210
|
+
*/
|
|
211
|
+
$derived(selector) {
|
|
212
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
213
|
+
let currentValue = selector({
|
|
214
|
+
context: this._contextProxy,
|
|
215
|
+
facts: this._factsProxy,
|
|
216
|
+
meta: this._metaProxy
|
|
217
|
+
});
|
|
218
|
+
this.subscribe(() => {
|
|
219
|
+
const newValue = selector({
|
|
220
|
+
context: this._contextProxy,
|
|
221
|
+
facts: this._factsProxy,
|
|
222
|
+
meta: this._metaProxy
|
|
223
|
+
});
|
|
224
|
+
if (newValue !== currentValue) {
|
|
225
|
+
currentValue = newValue;
|
|
226
|
+
subscribers.forEach((callback) => {
|
|
227
|
+
try {
|
|
228
|
+
callback(currentValue);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error("Error in derived value subscriber:", error);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return {
|
|
236
|
+
subscribe: (callback) => {
|
|
237
|
+
subscribers.add(callback);
|
|
238
|
+
try {
|
|
239
|
+
callback(currentValue);
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.error("Error in derived value subscriber:", error);
|
|
242
|
+
}
|
|
243
|
+
return () => {
|
|
244
|
+
subscribers.delete(callback);
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
};
|
|
342
248
|
}
|
|
343
249
|
};
|
|
250
|
+
function createReactiveEngine2(options) {
|
|
251
|
+
return new ReactiveLogicEngine2(options);
|
|
252
|
+
}
|
|
344
253
|
|
|
345
254
|
// src/core/actors.ts
|
|
346
255
|
var ActorManager = class {
|
|
@@ -429,7 +338,7 @@ var ActorManager = class {
|
|
|
429
338
|
/**
|
|
430
339
|
* Notify active actors of a state change
|
|
431
340
|
*/
|
|
432
|
-
async notifyStateChange(
|
|
341
|
+
async notifyStateChange(state) {
|
|
433
342
|
if (!this.engine) {
|
|
434
343
|
return;
|
|
435
344
|
}
|
|
@@ -437,7 +346,7 @@ var ActorManager = class {
|
|
|
437
346
|
for (const actorId of this.activeActors) {
|
|
438
347
|
const actor = this.actors.get(actorId);
|
|
439
348
|
if (actor?.onStateChange) {
|
|
440
|
-
const result = actor.onStateChange(
|
|
349
|
+
const result = actor.onStateChange(state, this.engine);
|
|
441
350
|
if (result instanceof Promise) {
|
|
442
351
|
promises.push(result);
|
|
443
352
|
}
|
|
@@ -915,14 +824,14 @@ var PraxisDBStore = class {
|
|
|
915
824
|
async checkConstraints(newFacts) {
|
|
916
825
|
const constraints = this.registry.getAllConstraints();
|
|
917
826
|
const errors = [];
|
|
918
|
-
const
|
|
827
|
+
const state = {
|
|
919
828
|
context: this.context,
|
|
920
829
|
facts: newFacts,
|
|
921
830
|
meta: {}
|
|
922
831
|
};
|
|
923
832
|
for (const constraint of constraints) {
|
|
924
833
|
try {
|
|
925
|
-
const result = constraint.impl(
|
|
834
|
+
const result = constraint.impl(state);
|
|
926
835
|
if (result === false) {
|
|
927
836
|
errors.push(`Constraint "${constraint.id}" violated`);
|
|
928
837
|
} else if (typeof result === "string") {
|
|
@@ -956,7 +865,7 @@ var PraxisDBStore = class {
|
|
|
956
865
|
*/
|
|
957
866
|
async triggerRulesForEvents(events) {
|
|
958
867
|
const rules = this.registry.getAllRules();
|
|
959
|
-
const
|
|
868
|
+
const state = {
|
|
960
869
|
context: this.context,
|
|
961
870
|
facts: [],
|
|
962
871
|
meta: {}
|
|
@@ -964,7 +873,7 @@ var PraxisDBStore = class {
|
|
|
964
873
|
const derivedFacts = [];
|
|
965
874
|
for (const rule of rules) {
|
|
966
875
|
try {
|
|
967
|
-
const facts = rule.impl(
|
|
876
|
+
const facts = rule.impl(state, events);
|
|
968
877
|
derivedFacts.push(...facts);
|
|
969
878
|
} catch (error) {
|
|
970
879
|
this.onRuleError(rule.id, error);
|
|
@@ -1053,6 +962,93 @@ var InMemoryPraxisDB = class {
|
|
|
1053
962
|
function createInMemoryDB() {
|
|
1054
963
|
return new InMemoryPraxisDB();
|
|
1055
964
|
}
|
|
965
|
+
var PluresDBPraxisAdapter = class {
|
|
966
|
+
db;
|
|
967
|
+
watchers = /* @__PURE__ */ new Map();
|
|
968
|
+
pollIntervals = /* @__PURE__ */ new Map();
|
|
969
|
+
lastValues = /* @__PURE__ */ new Map();
|
|
970
|
+
pollInterval;
|
|
971
|
+
constructor(config) {
|
|
972
|
+
if ("get" in config && "put" in config) {
|
|
973
|
+
this.db = config;
|
|
974
|
+
this.pollInterval = 1e3;
|
|
975
|
+
} else {
|
|
976
|
+
this.db = config.db;
|
|
977
|
+
this.pollInterval = config.pollInterval ?? 1e3;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
async get(key) {
|
|
981
|
+
try {
|
|
982
|
+
const value = await this.db.get(key);
|
|
983
|
+
return value;
|
|
984
|
+
} catch (error) {
|
|
985
|
+
return void 0;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
async set(key, value) {
|
|
989
|
+
await this.db.put(key, value);
|
|
990
|
+
this.lastValues.set(key, value);
|
|
991
|
+
const keyWatchers = this.watchers.get(key);
|
|
992
|
+
if (keyWatchers) {
|
|
993
|
+
for (const callback of keyWatchers) {
|
|
994
|
+
callback(value);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
watch(key, callback) {
|
|
999
|
+
if (!this.watchers.has(key)) {
|
|
1000
|
+
this.watchers.set(key, /* @__PURE__ */ new Set());
|
|
1001
|
+
}
|
|
1002
|
+
const watchers = this.watchers.get(key);
|
|
1003
|
+
const wrappedCallback = (val) => callback(val);
|
|
1004
|
+
watchers.add(wrappedCallback);
|
|
1005
|
+
if (!this.pollIntervals.has(key)) {
|
|
1006
|
+
const interval = setInterval(async () => {
|
|
1007
|
+
try {
|
|
1008
|
+
const value = await this.db.get(key);
|
|
1009
|
+
const lastValue = this.lastValues.get(key);
|
|
1010
|
+
if (JSON.stringify(value) !== JSON.stringify(lastValue)) {
|
|
1011
|
+
this.lastValues.set(key, value);
|
|
1012
|
+
const currentWatchers = this.watchers.get(key);
|
|
1013
|
+
if (currentWatchers) {
|
|
1014
|
+
for (const cb of currentWatchers) {
|
|
1015
|
+
cb(value);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
} catch (error) {
|
|
1020
|
+
}
|
|
1021
|
+
}, this.pollInterval);
|
|
1022
|
+
this.pollIntervals.set(key, interval);
|
|
1023
|
+
}
|
|
1024
|
+
return () => {
|
|
1025
|
+
watchers.delete(wrappedCallback);
|
|
1026
|
+
if (watchers.size === 0) {
|
|
1027
|
+
this.watchers.delete(key);
|
|
1028
|
+
const interval = this.pollIntervals.get(key);
|
|
1029
|
+
if (interval) {
|
|
1030
|
+
clearInterval(interval);
|
|
1031
|
+
this.pollIntervals.delete(key);
|
|
1032
|
+
}
|
|
1033
|
+
this.lastValues.delete(key);
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Clean up all resources
|
|
1039
|
+
*/
|
|
1040
|
+
dispose() {
|
|
1041
|
+
for (const interval of this.pollIntervals.values()) {
|
|
1042
|
+
clearInterval(interval);
|
|
1043
|
+
}
|
|
1044
|
+
this.pollIntervals.clear();
|
|
1045
|
+
this.watchers.clear();
|
|
1046
|
+
this.lastValues.clear();
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
function createPluresDB(config) {
|
|
1050
|
+
return new PluresDBPraxisAdapter(config);
|
|
1051
|
+
}
|
|
1056
1052
|
|
|
1057
1053
|
// src/core/pluresdb/schema-registry.ts
|
|
1058
1054
|
function getSchemaPath(schemaName) {
|
|
@@ -1934,8 +1930,8 @@ function createMockTauriBridge() {
|
|
|
1934
1930
|
function createTauriPraxisAdapter(options) {
|
|
1935
1931
|
const { bridge, statePath = "praxis-state.json", eventsPath = "praxis-events.json" } = options;
|
|
1936
1932
|
return {
|
|
1937
|
-
async saveState(
|
|
1938
|
-
const json = JSON.stringify(
|
|
1933
|
+
async saveState(state) {
|
|
1934
|
+
const json = JSON.stringify(state, null, 2);
|
|
1939
1935
|
await bridge.fs.writeTextFile(statePath, json);
|
|
1940
1936
|
},
|
|
1941
1937
|
async loadState() {
|
|
@@ -2036,11 +2032,13 @@ function generateTauriConfig(config) {
|
|
|
2036
2032
|
}
|
|
2037
2033
|
export {
|
|
2038
2034
|
ActorManager,
|
|
2035
|
+
ReactiveLogicEngine2 as FrameworkAgnosticReactiveEngine,
|
|
2039
2036
|
InMemoryPraxisDB,
|
|
2040
2037
|
LogicEngine,
|
|
2041
2038
|
PRAXIS_PATHS,
|
|
2042
2039
|
PRAXIS_PROTOCOL_VERSION,
|
|
2043
2040
|
PluresDBGenerator,
|
|
2041
|
+
PluresDBPraxisAdapter,
|
|
2044
2042
|
PraxisDBStore,
|
|
2045
2043
|
PraxisRegistry,
|
|
2046
2044
|
PraxisSchemaRegistry,
|
|
@@ -2055,14 +2053,17 @@ export {
|
|
|
2055
2053
|
canvasToSchema,
|
|
2056
2054
|
canvasToYaml,
|
|
2057
2055
|
createCanvasEditor,
|
|
2056
|
+
createReactiveEngine2 as createFrameworkAgnosticReactiveEngine,
|
|
2058
2057
|
createInMemoryDB,
|
|
2059
2058
|
createIntrospector,
|
|
2060
2059
|
createMockExecutor,
|
|
2061
2060
|
createMockTauriBridge,
|
|
2061
|
+
createPluresDB,
|
|
2062
2062
|
createPluresDBAdapter,
|
|
2063
2063
|
createPluresDBGenerator,
|
|
2064
2064
|
createPraxisDBStore,
|
|
2065
2065
|
createPraxisEngine,
|
|
2066
|
+
createReactiveEngine,
|
|
2066
2067
|
createSchemaRegistry,
|
|
2067
2068
|
createSchemaTemplate,
|
|
2068
2069
|
createStateDocsGenerator,
|