@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/browser/index.js
CHANGED
|
@@ -1,315 +1,225 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* Register a rule
|
|
10
|
-
*/
|
|
11
|
-
registerRule(descriptor) {
|
|
12
|
-
if (this.rules.has(descriptor.id)) {
|
|
13
|
-
throw new Error(`Rule with id "${descriptor.id}" already registered`);
|
|
14
|
-
}
|
|
15
|
-
this.rules.set(descriptor.id, descriptor);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Register a constraint
|
|
19
|
-
*/
|
|
20
|
-
registerConstraint(descriptor) {
|
|
21
|
-
if (this.constraints.has(descriptor.id)) {
|
|
22
|
-
throw new Error(`Constraint with id "${descriptor.id}" already registered`);
|
|
23
|
-
}
|
|
24
|
-
this.constraints.set(descriptor.id, descriptor);
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Register a module (all its rules and constraints)
|
|
28
|
-
*/
|
|
29
|
-
registerModule(module) {
|
|
30
|
-
for (const rule of module.rules) {
|
|
31
|
-
this.registerRule(rule);
|
|
32
|
-
}
|
|
33
|
-
for (const constraint of module.constraints) {
|
|
34
|
-
this.registerConstraint(constraint);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Get a rule by ID
|
|
39
|
-
*/
|
|
40
|
-
getRule(id) {
|
|
41
|
-
return this.rules.get(id);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Get a constraint by ID
|
|
45
|
-
*/
|
|
46
|
-
getConstraint(id) {
|
|
47
|
-
return this.constraints.get(id);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Get all registered rule IDs
|
|
51
|
-
*/
|
|
52
|
-
getRuleIds() {
|
|
53
|
-
return Array.from(this.rules.keys());
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Get all registered constraint IDs
|
|
57
|
-
*/
|
|
58
|
-
getConstraintIds() {
|
|
59
|
-
return Array.from(this.constraints.keys());
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Get all rules
|
|
63
|
-
*/
|
|
64
|
-
getAllRules() {
|
|
65
|
-
return Array.from(this.rules.values());
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Get all constraints
|
|
69
|
-
*/
|
|
70
|
-
getAllConstraints() {
|
|
71
|
-
return Array.from(this.constraints.values());
|
|
72
|
-
}
|
|
73
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
LogicEngine,
|
|
3
|
+
PRAXIS_PROTOCOL_VERSION,
|
|
4
|
+
PraxisRegistry,
|
|
5
|
+
ReactiveLogicEngine,
|
|
6
|
+
createPraxisEngine,
|
|
7
|
+
createReactiveEngine
|
|
8
|
+
} from "./chunk-R45WXWKH.js";
|
|
74
9
|
|
|
75
|
-
// src/core/engine.ts
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return [...value];
|
|
88
|
-
}
|
|
89
|
-
return { ...value };
|
|
90
|
-
}
|
|
91
|
-
var LogicEngine = class {
|
|
92
|
-
state;
|
|
93
|
-
registry;
|
|
10
|
+
// src/core/reactive-engine.ts
|
|
11
|
+
var ReactiveLogicEngine2 = class _ReactiveLogicEngine {
|
|
12
|
+
_state;
|
|
13
|
+
_subscribers = /* @__PURE__ */ new Set();
|
|
14
|
+
_contextProxy;
|
|
15
|
+
_factsProxy;
|
|
16
|
+
_metaProxy;
|
|
17
|
+
_batchDepth = 0;
|
|
18
|
+
_pendingNotification = false;
|
|
19
|
+
_proxyCache = /* @__PURE__ */ new WeakMap();
|
|
20
|
+
// Array methods that mutate the array
|
|
21
|
+
static ARRAY_MUTATORS = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"];
|
|
94
22
|
constructor(options) {
|
|
95
|
-
this.
|
|
96
|
-
this.state = {
|
|
23
|
+
this._state = {
|
|
97
24
|
context: options.initialContext,
|
|
98
25
|
facts: options.initialFacts ?? [],
|
|
99
|
-
meta: options.initialMeta ?? {}
|
|
100
|
-
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
26
|
+
meta: options.initialMeta ?? {}
|
|
101
27
|
};
|
|
28
|
+
this._contextProxy = this._createReactiveProxy(this._state.context);
|
|
29
|
+
this._factsProxy = this._createReactiveProxy(this._state.facts);
|
|
30
|
+
this._metaProxy = this._createReactiveProxy(this._state.meta);
|
|
102
31
|
}
|
|
103
32
|
/**
|
|
104
|
-
*
|
|
33
|
+
* Create a reactive proxy that notifies subscribers on changes.
|
|
34
|
+
* Uses a WeakMap cache to avoid creating multiple proxies for the same object.
|
|
105
35
|
*/
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
36
|
+
_createReactiveProxy(target) {
|
|
37
|
+
const cached = this._proxyCache.get(target);
|
|
38
|
+
if (cached) {
|
|
39
|
+
return cached;
|
|
40
|
+
}
|
|
41
|
+
const self = this;
|
|
42
|
+
const handler = {
|
|
43
|
+
get(obj, prop) {
|
|
44
|
+
const value = Reflect.get(obj, prop);
|
|
45
|
+
if (value && typeof value === "object") {
|
|
46
|
+
return self._createReactiveProxy(value);
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(obj) && typeof value === "function") {
|
|
49
|
+
if (_ReactiveLogicEngine.ARRAY_MUTATORS.includes(prop)) {
|
|
50
|
+
return function(...args) {
|
|
51
|
+
const result = value.apply(obj, args);
|
|
52
|
+
self._notify();
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
},
|
|
59
|
+
set(obj, prop, value) {
|
|
60
|
+
const oldValue = obj[prop];
|
|
61
|
+
const result = Reflect.set(obj, prop, value);
|
|
62
|
+
if (oldValue !== value) {
|
|
63
|
+
self._notify();
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
},
|
|
67
|
+
deleteProperty(obj, prop) {
|
|
68
|
+
const result = Reflect.deleteProperty(obj, prop);
|
|
69
|
+
self._notify();
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
112
72
|
};
|
|
73
|
+
const proxy = new Proxy(target, handler);
|
|
74
|
+
this._proxyCache.set(target, proxy);
|
|
75
|
+
return proxy;
|
|
113
76
|
}
|
|
114
77
|
/**
|
|
115
|
-
*
|
|
116
|
-
*/
|
|
117
|
-
getContext() {
|
|
118
|
-
return safeClone(this.state.context);
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Get current facts
|
|
78
|
+
* Notify all subscribers of state changes
|
|
122
79
|
*/
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
* Process events through the engine.
|
|
128
|
-
* Applies all registered rules and checks all registered constraints.
|
|
129
|
-
*
|
|
130
|
-
* @param events Events to process
|
|
131
|
-
* @returns Result with new state and diagnostics
|
|
132
|
-
*/
|
|
133
|
-
step(events) {
|
|
134
|
-
const config = {
|
|
135
|
-
ruleIds: this.registry.getRuleIds(),
|
|
136
|
-
constraintIds: this.registry.getConstraintIds()
|
|
137
|
-
};
|
|
138
|
-
return this.stepWithConfig(events, config);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Process events with specific rule and constraint configuration.
|
|
142
|
-
*
|
|
143
|
-
* @param events Events to process
|
|
144
|
-
* @param config Step configuration
|
|
145
|
-
* @returns Result with new state and diagnostics
|
|
146
|
-
*/
|
|
147
|
-
stepWithConfig(events, config) {
|
|
148
|
-
const diagnostics = [];
|
|
149
|
-
let newState = { ...this.state };
|
|
150
|
-
const newFacts = [];
|
|
151
|
-
for (const ruleId of config.ruleIds) {
|
|
152
|
-
const rule = this.registry.getRule(ruleId);
|
|
153
|
-
if (!rule) {
|
|
154
|
-
diagnostics.push({
|
|
155
|
-
kind: "rule-error",
|
|
156
|
-
message: `Rule "${ruleId}" not found in registry`,
|
|
157
|
-
data: { ruleId }
|
|
158
|
-
});
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
try {
|
|
162
|
-
const ruleFacts = rule.impl(newState, events);
|
|
163
|
-
newFacts.push(...ruleFacts);
|
|
164
|
-
} catch (error) {
|
|
165
|
-
diagnostics.push({
|
|
166
|
-
kind: "rule-error",
|
|
167
|
-
message: `Error executing rule "${ruleId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
168
|
-
data: { ruleId, error }
|
|
169
|
-
});
|
|
170
|
-
}
|
|
80
|
+
_notify() {
|
|
81
|
+
if (this._batchDepth > 0) {
|
|
82
|
+
this._pendingNotification = true;
|
|
83
|
+
return;
|
|
171
84
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
facts:
|
|
85
|
+
const currentState = {
|
|
86
|
+
context: this._contextProxy,
|
|
87
|
+
facts: this._factsProxy,
|
|
88
|
+
meta: this._metaProxy
|
|
175
89
|
};
|
|
176
|
-
|
|
177
|
-
const constraint = this.registry.getConstraint(constraintId);
|
|
178
|
-
if (!constraint) {
|
|
179
|
-
diagnostics.push({
|
|
180
|
-
kind: "constraint-violation",
|
|
181
|
-
message: `Constraint "${constraintId}" not found in registry`,
|
|
182
|
-
data: { constraintId }
|
|
183
|
-
});
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
90
|
+
this._subscribers.forEach((callback) => {
|
|
186
91
|
try {
|
|
187
|
-
|
|
188
|
-
if (result === false) {
|
|
189
|
-
diagnostics.push({
|
|
190
|
-
kind: "constraint-violation",
|
|
191
|
-
message: `Constraint "${constraintId}" violated`,
|
|
192
|
-
data: { constraintId, description: constraint.description }
|
|
193
|
-
});
|
|
194
|
-
} else if (typeof result === "string") {
|
|
195
|
-
diagnostics.push({
|
|
196
|
-
kind: "constraint-violation",
|
|
197
|
-
message: result,
|
|
198
|
-
data: { constraintId, description: constraint.description }
|
|
199
|
-
});
|
|
200
|
-
}
|
|
92
|
+
callback(currentState);
|
|
201
93
|
} catch (error) {
|
|
202
|
-
|
|
203
|
-
kind: "constraint-violation",
|
|
204
|
-
message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
205
|
-
data: { constraintId, error }
|
|
206
|
-
});
|
|
94
|
+
console.error("Error in reactive engine subscriber:", error);
|
|
207
95
|
}
|
|
208
|
-
}
|
|
209
|
-
this.state = newState;
|
|
210
|
-
return {
|
|
211
|
-
state: newState,
|
|
212
|
-
diagnostics
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Update the context directly (for exceptional cases).
|
|
217
|
-
* Generally, context should be updated through rules.
|
|
218
|
-
*
|
|
219
|
-
* @param updater Function that produces new context from old context
|
|
220
|
-
*/
|
|
221
|
-
updateContext(updater) {
|
|
222
|
-
this.state = {
|
|
223
|
-
...this.state,
|
|
224
|
-
context: updater(this.state.context)
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Add facts directly (for exceptional cases).
|
|
229
|
-
* Generally, facts should be added through rules.
|
|
230
|
-
*
|
|
231
|
-
* @param facts Facts to add
|
|
232
|
-
*/
|
|
233
|
-
addFacts(facts) {
|
|
234
|
-
this.state = {
|
|
235
|
-
...this.state,
|
|
236
|
-
facts: [...this.state.facts, ...facts]
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Clear all facts
|
|
241
|
-
*/
|
|
242
|
-
clearFacts() {
|
|
243
|
-
this.state = {
|
|
244
|
-
...this.state,
|
|
245
|
-
facts: []
|
|
246
|
-
};
|
|
96
|
+
});
|
|
247
97
|
}
|
|
248
98
|
/**
|
|
249
|
-
*
|
|
99
|
+
* Get the full state object
|
|
250
100
|
*/
|
|
251
|
-
reset(options) {
|
|
252
|
-
this.state = {
|
|
253
|
-
context: options.initialContext,
|
|
254
|
-
facts: options.initialFacts ?? [],
|
|
255
|
-
meta: options.initialMeta ?? {},
|
|
256
|
-
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
function createPraxisEngine(options) {
|
|
261
|
-
return new LogicEngine(options);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// src/core/reactive-engine.svelte.ts
|
|
265
|
-
import * as $ from "svelte/internal/client";
|
|
266
|
-
var ReactiveLogicEngine = class {
|
|
267
|
-
#state = (
|
|
268
|
-
// The single source of truth, reactive by default
|
|
269
|
-
// We use $state.raw for things that shouldn't be deeply reactive if needed,
|
|
270
|
-
// but for context we usually want deep reactivity.
|
|
271
|
-
$.state($.proxy({ context: {}, facts: [], meta: {} }))
|
|
272
|
-
);
|
|
273
101
|
get state() {
|
|
274
|
-
return
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
constructor(options) {
|
|
280
|
-
this.state.context = options.initialContext;
|
|
281
|
-
this.state.facts = options.initialFacts ?? [];
|
|
282
|
-
this.state.meta = options.initialMeta ?? {};
|
|
102
|
+
return {
|
|
103
|
+
context: this._contextProxy,
|
|
104
|
+
facts: this._factsProxy,
|
|
105
|
+
meta: this._metaProxy
|
|
106
|
+
};
|
|
283
107
|
}
|
|
284
108
|
/**
|
|
285
|
-
* Access the reactive context
|
|
286
|
-
*
|
|
109
|
+
* Access the reactive context.
|
|
110
|
+
* Changes to this object will trigger subscriber notifications.
|
|
287
111
|
*/
|
|
288
112
|
get context() {
|
|
289
|
-
return this.
|
|
113
|
+
return this._contextProxy;
|
|
290
114
|
}
|
|
291
115
|
/**
|
|
292
116
|
* Access the reactive facts list.
|
|
117
|
+
* Changes to this array will trigger subscriber notifications.
|
|
293
118
|
*/
|
|
294
119
|
get facts() {
|
|
295
|
-
return this.
|
|
120
|
+
return this._factsProxy;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Access the reactive metadata.
|
|
124
|
+
* Changes to this object will trigger subscriber notifications.
|
|
125
|
+
*/
|
|
126
|
+
get meta() {
|
|
127
|
+
return this._metaProxy;
|
|
296
128
|
}
|
|
297
129
|
/**
|
|
298
130
|
* Apply a mutation to the state.
|
|
299
131
|
* This is the "Action" or "Rule" equivalent.
|
|
132
|
+
* Mutations are batched - notifications only happen once per apply call.
|
|
300
133
|
*
|
|
301
134
|
* @param mutator A function that receives the state and modifies it.
|
|
302
135
|
*/
|
|
303
136
|
apply(mutator) {
|
|
304
|
-
|
|
137
|
+
this._batchDepth++;
|
|
138
|
+
try {
|
|
139
|
+
mutator({
|
|
140
|
+
context: this._contextProxy,
|
|
141
|
+
facts: this._factsProxy,
|
|
142
|
+
meta: this._metaProxy
|
|
143
|
+
});
|
|
144
|
+
} finally {
|
|
145
|
+
this._batchDepth--;
|
|
146
|
+
if (this._batchDepth === 0 && this._pendingNotification) {
|
|
147
|
+
this._pendingNotification = false;
|
|
148
|
+
this._notify();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
305
151
|
}
|
|
306
152
|
/**
|
|
307
|
-
*
|
|
153
|
+
* Subscribe to state changes.
|
|
154
|
+
* Returns an unsubscribe function.
|
|
155
|
+
*
|
|
156
|
+
* @param callback Function to call when state changes
|
|
157
|
+
* @returns Unsubscribe function
|
|
308
158
|
*/
|
|
309
|
-
|
|
310
|
-
|
|
159
|
+
subscribe(callback) {
|
|
160
|
+
this._subscribers.add(callback);
|
|
161
|
+
try {
|
|
162
|
+
callback({
|
|
163
|
+
context: this._contextProxy,
|
|
164
|
+
facts: this._factsProxy,
|
|
165
|
+
meta: this._metaProxy
|
|
166
|
+
});
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error("Error in reactive engine subscriber:", error);
|
|
169
|
+
}
|
|
170
|
+
return () => {
|
|
171
|
+
this._subscribers.delete(callback);
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Create a derived/computed value from the state.
|
|
176
|
+
* The selector function will be called whenever the state changes.
|
|
177
|
+
*
|
|
178
|
+
* @param selector Function to extract derived value from state
|
|
179
|
+
* @returns Object with subscribe method for reactive updates
|
|
180
|
+
*/
|
|
181
|
+
$derived(selector) {
|
|
182
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
183
|
+
let currentValue = selector({
|
|
184
|
+
context: this._contextProxy,
|
|
185
|
+
facts: this._factsProxy,
|
|
186
|
+
meta: this._metaProxy
|
|
187
|
+
});
|
|
188
|
+
this.subscribe(() => {
|
|
189
|
+
const newValue = selector({
|
|
190
|
+
context: this._contextProxy,
|
|
191
|
+
facts: this._factsProxy,
|
|
192
|
+
meta: this._metaProxy
|
|
193
|
+
});
|
|
194
|
+
if (newValue !== currentValue) {
|
|
195
|
+
currentValue = newValue;
|
|
196
|
+
subscribers.forEach((callback) => {
|
|
197
|
+
try {
|
|
198
|
+
callback(currentValue);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.error("Error in derived value subscriber:", error);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
return {
|
|
206
|
+
subscribe: (callback) => {
|
|
207
|
+
subscribers.add(callback);
|
|
208
|
+
try {
|
|
209
|
+
callback(currentValue);
|
|
210
|
+
} catch (error) {
|
|
211
|
+
console.error("Error in derived value subscriber:", error);
|
|
212
|
+
}
|
|
213
|
+
return () => {
|
|
214
|
+
subscribers.delete(callback);
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
};
|
|
311
218
|
}
|
|
312
219
|
};
|
|
220
|
+
function createReactiveEngine2(options) {
|
|
221
|
+
return new ReactiveLogicEngine2(options);
|
|
222
|
+
}
|
|
313
223
|
|
|
314
224
|
// src/core/actors.ts
|
|
315
225
|
var ActorManager = class {
|
|
@@ -398,7 +308,7 @@ var ActorManager = class {
|
|
|
398
308
|
/**
|
|
399
309
|
* Notify active actors of a state change
|
|
400
310
|
*/
|
|
401
|
-
async notifyStateChange(
|
|
311
|
+
async notifyStateChange(state) {
|
|
402
312
|
if (!this.engine) {
|
|
403
313
|
return;
|
|
404
314
|
}
|
|
@@ -406,7 +316,7 @@ var ActorManager = class {
|
|
|
406
316
|
for (const actorId of this.activeActors) {
|
|
407
317
|
const actor = this.actors.get(actorId);
|
|
408
318
|
if (actor?.onStateChange) {
|
|
409
|
-
const result = actor.onStateChange(
|
|
319
|
+
const result = actor.onStateChange(state, this.engine);
|
|
410
320
|
if (result instanceof Promise) {
|
|
411
321
|
promises.push(result);
|
|
412
322
|
}
|
|
@@ -1147,14 +1057,14 @@ var PraxisDBStore = class {
|
|
|
1147
1057
|
async checkConstraints(newFacts) {
|
|
1148
1058
|
const constraints = this.registry.getAllConstraints();
|
|
1149
1059
|
const errors = [];
|
|
1150
|
-
const
|
|
1060
|
+
const state = {
|
|
1151
1061
|
context: this.context,
|
|
1152
1062
|
facts: newFacts,
|
|
1153
1063
|
meta: {}
|
|
1154
1064
|
};
|
|
1155
1065
|
for (const constraint of constraints) {
|
|
1156
1066
|
try {
|
|
1157
|
-
const result = constraint.impl(
|
|
1067
|
+
const result = constraint.impl(state);
|
|
1158
1068
|
if (result === false) {
|
|
1159
1069
|
errors.push(`Constraint "${constraint.id}" violated`);
|
|
1160
1070
|
} else if (typeof result === "string") {
|
|
@@ -1188,7 +1098,7 @@ var PraxisDBStore = class {
|
|
|
1188
1098
|
*/
|
|
1189
1099
|
async triggerRulesForEvents(events) {
|
|
1190
1100
|
const rules = this.registry.getAllRules();
|
|
1191
|
-
const
|
|
1101
|
+
const state = {
|
|
1192
1102
|
context: this.context,
|
|
1193
1103
|
facts: [],
|
|
1194
1104
|
meta: {}
|
|
@@ -1196,7 +1106,7 @@ var PraxisDBStore = class {
|
|
|
1196
1106
|
const derivedFacts = [];
|
|
1197
1107
|
for (const rule of rules) {
|
|
1198
1108
|
try {
|
|
1199
|
-
const facts = rule.impl(
|
|
1109
|
+
const facts = rule.impl(state, events);
|
|
1200
1110
|
derivedFacts.push(...facts);
|
|
1201
1111
|
} catch (error) {
|
|
1202
1112
|
this.onRuleError(rule.id, error);
|
|
@@ -1285,6 +1195,93 @@ var InMemoryPraxisDB = class {
|
|
|
1285
1195
|
function createInMemoryDB() {
|
|
1286
1196
|
return new InMemoryPraxisDB();
|
|
1287
1197
|
}
|
|
1198
|
+
var PluresDBPraxisAdapter = class {
|
|
1199
|
+
db;
|
|
1200
|
+
watchers = /* @__PURE__ */ new Map();
|
|
1201
|
+
pollIntervals = /* @__PURE__ */ new Map();
|
|
1202
|
+
lastValues = /* @__PURE__ */ new Map();
|
|
1203
|
+
pollInterval;
|
|
1204
|
+
constructor(config) {
|
|
1205
|
+
if ("get" in config && "put" in config) {
|
|
1206
|
+
this.db = config;
|
|
1207
|
+
this.pollInterval = 1e3;
|
|
1208
|
+
} else {
|
|
1209
|
+
this.db = config.db;
|
|
1210
|
+
this.pollInterval = config.pollInterval ?? 1e3;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
async get(key) {
|
|
1214
|
+
try {
|
|
1215
|
+
const value = await this.db.get(key);
|
|
1216
|
+
return value;
|
|
1217
|
+
} catch (error) {
|
|
1218
|
+
return void 0;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
async set(key, value) {
|
|
1222
|
+
await this.db.put(key, value);
|
|
1223
|
+
this.lastValues.set(key, value);
|
|
1224
|
+
const keyWatchers = this.watchers.get(key);
|
|
1225
|
+
if (keyWatchers) {
|
|
1226
|
+
for (const callback of keyWatchers) {
|
|
1227
|
+
callback(value);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
watch(key, callback) {
|
|
1232
|
+
if (!this.watchers.has(key)) {
|
|
1233
|
+
this.watchers.set(key, /* @__PURE__ */ new Set());
|
|
1234
|
+
}
|
|
1235
|
+
const watchers = this.watchers.get(key);
|
|
1236
|
+
const wrappedCallback = (val) => callback(val);
|
|
1237
|
+
watchers.add(wrappedCallback);
|
|
1238
|
+
if (!this.pollIntervals.has(key)) {
|
|
1239
|
+
const interval = setInterval(async () => {
|
|
1240
|
+
try {
|
|
1241
|
+
const value = await this.db.get(key);
|
|
1242
|
+
const lastValue = this.lastValues.get(key);
|
|
1243
|
+
if (JSON.stringify(value) !== JSON.stringify(lastValue)) {
|
|
1244
|
+
this.lastValues.set(key, value);
|
|
1245
|
+
const currentWatchers = this.watchers.get(key);
|
|
1246
|
+
if (currentWatchers) {
|
|
1247
|
+
for (const cb of currentWatchers) {
|
|
1248
|
+
cb(value);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
} catch (error) {
|
|
1253
|
+
}
|
|
1254
|
+
}, this.pollInterval);
|
|
1255
|
+
this.pollIntervals.set(key, interval);
|
|
1256
|
+
}
|
|
1257
|
+
return () => {
|
|
1258
|
+
watchers.delete(wrappedCallback);
|
|
1259
|
+
if (watchers.size === 0) {
|
|
1260
|
+
this.watchers.delete(key);
|
|
1261
|
+
const interval = this.pollIntervals.get(key);
|
|
1262
|
+
if (interval) {
|
|
1263
|
+
clearInterval(interval);
|
|
1264
|
+
this.pollIntervals.delete(key);
|
|
1265
|
+
}
|
|
1266
|
+
this.lastValues.delete(key);
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Clean up all resources
|
|
1272
|
+
*/
|
|
1273
|
+
dispose() {
|
|
1274
|
+
for (const interval of this.pollIntervals.values()) {
|
|
1275
|
+
clearInterval(interval);
|
|
1276
|
+
}
|
|
1277
|
+
this.pollIntervals.clear();
|
|
1278
|
+
this.watchers.clear();
|
|
1279
|
+
this.lastValues.clear();
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
function createPluresDB(config) {
|
|
1283
|
+
return new PluresDBPraxisAdapter(config);
|
|
1284
|
+
}
|
|
1288
1285
|
|
|
1289
1286
|
// src/core/pluresdb/schema-registry.ts
|
|
1290
1287
|
function getSchemaPath(schemaName) {
|
|
@@ -2733,8 +2730,8 @@ function createMockTauriBridge() {
|
|
|
2733
2730
|
function createTauriPraxisAdapter(options) {
|
|
2734
2731
|
const { bridge, statePath = "praxis-state.json", eventsPath = "praxis-events.json" } = options;
|
|
2735
2732
|
return {
|
|
2736
|
-
async saveState(
|
|
2737
|
-
const json = JSON.stringify(
|
|
2733
|
+
async saveState(state) {
|
|
2734
|
+
const json = JSON.stringify(state, null, 2);
|
|
2738
2735
|
await bridge.fs.writeTextFile(statePath, json);
|
|
2739
2736
|
},
|
|
2740
2737
|
async loadState() {
|
|
@@ -2835,11 +2832,13 @@ function generateTauriConfig(config) {
|
|
|
2835
2832
|
}
|
|
2836
2833
|
export {
|
|
2837
2834
|
ActorManager,
|
|
2835
|
+
ReactiveLogicEngine2 as FrameworkAgnosticReactiveEngine,
|
|
2838
2836
|
InMemoryPraxisDB,
|
|
2839
2837
|
LogicEngine,
|
|
2840
2838
|
PRAXIS_PATHS,
|
|
2841
2839
|
PRAXIS_PROTOCOL_VERSION,
|
|
2842
2840
|
PluresDBGenerator,
|
|
2841
|
+
PluresDBPraxisAdapter,
|
|
2843
2842
|
PraxisDBStore,
|
|
2844
2843
|
PraxisRegistry,
|
|
2845
2844
|
PraxisSchemaRegistry,
|
|
@@ -2853,13 +2852,16 @@ export {
|
|
|
2853
2852
|
canvasToSchema,
|
|
2854
2853
|
canvasToYaml,
|
|
2855
2854
|
createCanvasEditor,
|
|
2855
|
+
createReactiveEngine2 as createFrameworkAgnosticReactiveEngine,
|
|
2856
2856
|
createInMemoryDB,
|
|
2857
2857
|
createIntrospector,
|
|
2858
2858
|
createMockTauriBridge,
|
|
2859
|
+
createPluresDB,
|
|
2859
2860
|
createPluresDBAdapter,
|
|
2860
2861
|
createPluresDBGenerator,
|
|
2861
2862
|
createPraxisDBStore,
|
|
2862
2863
|
createPraxisEngine,
|
|
2864
|
+
createReactiveEngine,
|
|
2863
2865
|
createSchema,
|
|
2864
2866
|
createSchemaRegistry,
|
|
2865
2867
|
createSchemaTemplate,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { L as LogicEngine, P as PraxisState, a as PraxisEvent } from '../engine-
|
|
1
|
+
import { L as LogicEngine, P as PraxisState, a as PraxisEvent } from '../reactive-engine.svelte-C9OpcTHf.js';
|
|
2
|
+
export { p as ReactiveEngineOptions, q as ReactiveLogicEngine, r as createReactiveEngine } from '../reactive-engine.svelte-C9OpcTHf.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Svelte v5 Integration
|
|
@@ -9,6 +10,7 @@ import { L as LogicEngine, P as PraxisState, a as PraxisEvent } from '../engine-
|
|
|
9
10
|
* Features:
|
|
10
11
|
* - Store-based API for backward compatibility
|
|
11
12
|
* - Runes-based composables for Svelte 5
|
|
13
|
+
* - createReactiveEngine for easy reactive engine setup
|
|
12
14
|
* - Snapshot support for time-travel debugging
|
|
13
15
|
* - History state pattern implementation
|
|
14
16
|
* - Automatic cleanup and subscription management
|