@plures/praxis 1.1.3 → 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.
- package/FRAMEWORK.md +106 -15
- package/README.md +209 -48
- package/dist/browser/adapter-TM4IS5KT.js +12 -0
- package/dist/browser/chunk-JQ64KMLN.js +141 -0
- package/dist/browser/chunk-LE2ZJYFC.js +154 -0
- package/dist/browser/{chunk-R45WXWKH.js → chunk-VOMLVI6V.js} +1 -149
- package/dist/browser/engine-YJZV4SLD.js +8 -0
- package/dist/browser/index.d.ts +130 -1
- package/dist/browser/index.js +146 -139
- package/dist/browser/integrations/svelte.js +2 -1
- package/dist/node/adapter-K6DOX6XS.js +13 -0
- package/dist/node/chunk-JQ64KMLN.js +141 -0
- package/dist/node/chunk-LE2ZJYFC.js +154 -0
- package/dist/node/chunk-S54337I5.js +446 -0
- package/dist/node/{chunk-R45WXWKH.js → chunk-VOMLVI6V.js} +1 -149
- package/dist/node/cli/index.cjs +1444 -889
- package/dist/node/cli/index.js +9 -0
- package/dist/node/docs-JFNYTOJA.js +102 -0
- package/dist/node/engine-2DQBKBJC.js +9 -0
- package/dist/node/index.cjs +503 -325
- package/dist/node/index.d.cts +130 -1
- package/dist/node/index.d.ts +130 -1
- package/dist/node/index.js +151 -580
- package/dist/node/integrations/svelte.js +2 -1
- package/package.json +1 -1
- package/src/cli/commands/docs.ts +147 -0
- package/src/cli/index.ts +21 -0
- package/src/core/pluresdb/adapter.ts +1 -1
- package/src/core/reactive-engine.svelte.ts +6 -1
- package/src/core/reactive-engine.ts +1 -1
- package/src/index.browser.ts +4 -0
- package/src/index.ts +4 -0
- package/src/integrations/unified.ts +350 -0
package/dist/node/index.cjs
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +30,364 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
33
|
+
// src/core/protocol.ts
|
|
34
|
+
var PRAXIS_PROTOCOL_VERSION;
|
|
35
|
+
var init_protocol = __esm({
|
|
36
|
+
"src/core/protocol.ts"() {
|
|
37
|
+
"use strict";
|
|
38
|
+
PRAXIS_PROTOCOL_VERSION = "1.0.0";
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// src/core/engine.ts
|
|
43
|
+
var engine_exports = {};
|
|
44
|
+
__export(engine_exports, {
|
|
45
|
+
LogicEngine: () => LogicEngine,
|
|
46
|
+
createPraxisEngine: () => createPraxisEngine
|
|
47
|
+
});
|
|
48
|
+
function safeClone(value) {
|
|
49
|
+
if (value === null || typeof value !== "object") {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
if (typeof globalThis.structuredClone === "function") {
|
|
53
|
+
try {
|
|
54
|
+
return globalThis.structuredClone(value);
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
return [...value];
|
|
60
|
+
}
|
|
61
|
+
return { ...value };
|
|
62
|
+
}
|
|
63
|
+
function createPraxisEngine(options) {
|
|
64
|
+
return new LogicEngine(options);
|
|
65
|
+
}
|
|
66
|
+
var LogicEngine;
|
|
67
|
+
var init_engine = __esm({
|
|
68
|
+
"src/core/engine.ts"() {
|
|
69
|
+
"use strict";
|
|
70
|
+
init_protocol();
|
|
71
|
+
LogicEngine = class {
|
|
72
|
+
state;
|
|
73
|
+
registry;
|
|
74
|
+
constructor(options) {
|
|
75
|
+
this.registry = options.registry;
|
|
76
|
+
this.state = {
|
|
77
|
+
context: options.initialContext,
|
|
78
|
+
facts: options.initialFacts ?? [],
|
|
79
|
+
meta: options.initialMeta ?? {},
|
|
80
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get the current state (immutable copy)
|
|
85
|
+
*/
|
|
86
|
+
getState() {
|
|
87
|
+
return {
|
|
88
|
+
context: safeClone(this.state.context),
|
|
89
|
+
facts: [...this.state.facts],
|
|
90
|
+
meta: this.state.meta ? safeClone(this.state.meta) : void 0,
|
|
91
|
+
protocolVersion: this.state.protocolVersion
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get the current context
|
|
96
|
+
*/
|
|
97
|
+
getContext() {
|
|
98
|
+
return safeClone(this.state.context);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get current facts
|
|
102
|
+
*/
|
|
103
|
+
getFacts() {
|
|
104
|
+
return [...this.state.facts];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Process events through the engine.
|
|
108
|
+
* Applies all registered rules and checks all registered constraints.
|
|
109
|
+
*
|
|
110
|
+
* @param events Events to process
|
|
111
|
+
* @returns Result with new state and diagnostics
|
|
112
|
+
*/
|
|
113
|
+
step(events) {
|
|
114
|
+
const config = {
|
|
115
|
+
ruleIds: this.registry.getRuleIds(),
|
|
116
|
+
constraintIds: this.registry.getConstraintIds()
|
|
117
|
+
};
|
|
118
|
+
return this.stepWithConfig(events, config);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Process events with specific rule and constraint configuration.
|
|
122
|
+
*
|
|
123
|
+
* @param events Events to process
|
|
124
|
+
* @param config Step configuration
|
|
125
|
+
* @returns Result with new state and diagnostics
|
|
126
|
+
*/
|
|
127
|
+
stepWithConfig(events, config) {
|
|
128
|
+
const diagnostics = [];
|
|
129
|
+
let newState = { ...this.state };
|
|
130
|
+
const newFacts = [];
|
|
131
|
+
for (const ruleId of config.ruleIds) {
|
|
132
|
+
const rule = this.registry.getRule(ruleId);
|
|
133
|
+
if (!rule) {
|
|
134
|
+
diagnostics.push({
|
|
135
|
+
kind: "rule-error",
|
|
136
|
+
message: `Rule "${ruleId}" not found in registry`,
|
|
137
|
+
data: { ruleId }
|
|
138
|
+
});
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const ruleFacts = rule.impl(newState, events);
|
|
143
|
+
newFacts.push(...ruleFacts);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
diagnostics.push({
|
|
146
|
+
kind: "rule-error",
|
|
147
|
+
message: `Error executing rule "${ruleId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
148
|
+
data: { ruleId, error }
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
newState = {
|
|
153
|
+
...newState,
|
|
154
|
+
facts: [...newState.facts, ...newFacts]
|
|
155
|
+
};
|
|
156
|
+
for (const constraintId of config.constraintIds) {
|
|
157
|
+
const constraint = this.registry.getConstraint(constraintId);
|
|
158
|
+
if (!constraint) {
|
|
159
|
+
diagnostics.push({
|
|
160
|
+
kind: "constraint-violation",
|
|
161
|
+
message: `Constraint "${constraintId}" not found in registry`,
|
|
162
|
+
data: { constraintId }
|
|
163
|
+
});
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const result = constraint.impl(newState);
|
|
168
|
+
if (result === false) {
|
|
169
|
+
diagnostics.push({
|
|
170
|
+
kind: "constraint-violation",
|
|
171
|
+
message: `Constraint "${constraintId}" violated`,
|
|
172
|
+
data: { constraintId, description: constraint.description }
|
|
173
|
+
});
|
|
174
|
+
} else if (typeof result === "string") {
|
|
175
|
+
diagnostics.push({
|
|
176
|
+
kind: "constraint-violation",
|
|
177
|
+
message: result,
|
|
178
|
+
data: { constraintId, description: constraint.description }
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
} catch (error) {
|
|
182
|
+
diagnostics.push({
|
|
183
|
+
kind: "constraint-violation",
|
|
184
|
+
message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
185
|
+
data: { constraintId, error }
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
this.state = newState;
|
|
190
|
+
return {
|
|
191
|
+
state: newState,
|
|
192
|
+
diagnostics
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Update the context directly (for exceptional cases).
|
|
197
|
+
* Generally, context should be updated through rules.
|
|
198
|
+
*
|
|
199
|
+
* @param updater Function that produces new context from old context
|
|
200
|
+
*/
|
|
201
|
+
updateContext(updater) {
|
|
202
|
+
this.state = {
|
|
203
|
+
...this.state,
|
|
204
|
+
context: updater(this.state.context)
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Add facts directly (for exceptional cases).
|
|
209
|
+
* Generally, facts should be added through rules.
|
|
210
|
+
*
|
|
211
|
+
* @param facts Facts to add
|
|
212
|
+
*/
|
|
213
|
+
addFacts(facts) {
|
|
214
|
+
this.state = {
|
|
215
|
+
...this.state,
|
|
216
|
+
facts: [...this.state.facts, ...facts]
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Clear all facts
|
|
221
|
+
*/
|
|
222
|
+
clearFacts() {
|
|
223
|
+
this.state = {
|
|
224
|
+
...this.state,
|
|
225
|
+
facts: []
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Reset the engine to initial state
|
|
230
|
+
*/
|
|
231
|
+
reset(options) {
|
|
232
|
+
this.state = {
|
|
233
|
+
context: options.initialContext,
|
|
234
|
+
facts: options.initialFacts ?? [],
|
|
235
|
+
meta: options.initialMeta ?? {},
|
|
236
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// src/core/pluresdb/adapter.ts
|
|
244
|
+
var adapter_exports = {};
|
|
245
|
+
__export(adapter_exports, {
|
|
246
|
+
InMemoryPraxisDB: () => InMemoryPraxisDB,
|
|
247
|
+
PluresDBPraxisAdapter: () => PluresDBPraxisAdapter,
|
|
248
|
+
createInMemoryDB: () => createInMemoryDB,
|
|
249
|
+
createPluresDB: () => createPluresDB
|
|
250
|
+
});
|
|
251
|
+
function createInMemoryDB() {
|
|
252
|
+
return new InMemoryPraxisDB();
|
|
253
|
+
}
|
|
254
|
+
function createPluresDB(config) {
|
|
255
|
+
return new PluresDBPraxisAdapter(config);
|
|
256
|
+
}
|
|
257
|
+
var InMemoryPraxisDB, PluresDBPraxisAdapter;
|
|
258
|
+
var init_adapter = __esm({
|
|
259
|
+
"src/core/pluresdb/adapter.ts"() {
|
|
260
|
+
"use strict";
|
|
261
|
+
InMemoryPraxisDB = class {
|
|
262
|
+
store = /* @__PURE__ */ new Map();
|
|
263
|
+
watchers = /* @__PURE__ */ new Map();
|
|
264
|
+
async get(key) {
|
|
265
|
+
return this.store.get(key);
|
|
266
|
+
}
|
|
267
|
+
async set(key, value) {
|
|
268
|
+
this.store.set(key, value);
|
|
269
|
+
const keyWatchers = this.watchers.get(key);
|
|
270
|
+
if (keyWatchers) {
|
|
271
|
+
for (const callback of keyWatchers) {
|
|
272
|
+
callback(value);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
watch(key, callback) {
|
|
277
|
+
if (!this.watchers.has(key)) {
|
|
278
|
+
this.watchers.set(key, /* @__PURE__ */ new Set());
|
|
279
|
+
}
|
|
280
|
+
const watchers = this.watchers.get(key);
|
|
281
|
+
const wrappedCallback = (val) => callback(val);
|
|
282
|
+
watchers.add(wrappedCallback);
|
|
283
|
+
return () => {
|
|
284
|
+
watchers.delete(wrappedCallback);
|
|
285
|
+
if (watchers.size === 0) {
|
|
286
|
+
this.watchers.delete(key);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Get all keys (for testing/debugging)
|
|
292
|
+
*/
|
|
293
|
+
keys() {
|
|
294
|
+
return Array.from(this.store.keys());
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Clear all data (for testing)
|
|
298
|
+
*/
|
|
299
|
+
clear() {
|
|
300
|
+
this.store.clear();
|
|
301
|
+
this.watchers.clear();
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
PluresDBPraxisAdapter = class {
|
|
305
|
+
db;
|
|
306
|
+
watchers = /* @__PURE__ */ new Map();
|
|
307
|
+
pollIntervals = /* @__PURE__ */ new Map();
|
|
308
|
+
lastValues = /* @__PURE__ */ new Map();
|
|
309
|
+
pollInterval;
|
|
310
|
+
constructor(config) {
|
|
311
|
+
if ("get" in config && "put" in config) {
|
|
312
|
+
this.db = config;
|
|
313
|
+
this.pollInterval = 1e3;
|
|
314
|
+
} else {
|
|
315
|
+
this.db = config.db;
|
|
316
|
+
this.pollInterval = config.pollInterval ?? 1e3;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async get(key) {
|
|
320
|
+
try {
|
|
321
|
+
const value = await this.db.get(key);
|
|
322
|
+
return value;
|
|
323
|
+
} catch (error) {
|
|
324
|
+
return void 0;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
async set(key, value) {
|
|
328
|
+
await this.db.put(key, value);
|
|
329
|
+
this.lastValues.set(key, value);
|
|
330
|
+
const keyWatchers = this.watchers.get(key);
|
|
331
|
+
if (keyWatchers) {
|
|
332
|
+
for (const callback of keyWatchers) {
|
|
333
|
+
callback(value);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
watch(key, callback) {
|
|
338
|
+
if (!this.watchers.has(key)) {
|
|
339
|
+
this.watchers.set(key, /* @__PURE__ */ new Set());
|
|
340
|
+
}
|
|
341
|
+
const watchers = this.watchers.get(key);
|
|
342
|
+
const wrappedCallback = (val) => callback(val);
|
|
343
|
+
watchers.add(wrappedCallback);
|
|
344
|
+
if (!this.pollIntervals.has(key)) {
|
|
345
|
+
const interval = setInterval(async () => {
|
|
346
|
+
try {
|
|
347
|
+
const value = await this.db.get(key);
|
|
348
|
+
const lastValue = this.lastValues.get(key);
|
|
349
|
+
if (JSON.stringify(value) !== JSON.stringify(lastValue)) {
|
|
350
|
+
this.lastValues.set(key, value);
|
|
351
|
+
const currentWatchers = this.watchers.get(key);
|
|
352
|
+
if (currentWatchers) {
|
|
353
|
+
for (const cb of currentWatchers) {
|
|
354
|
+
cb(value);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
} catch (error) {
|
|
359
|
+
}
|
|
360
|
+
}, this.pollInterval);
|
|
361
|
+
this.pollIntervals.set(key, interval);
|
|
362
|
+
}
|
|
363
|
+
return () => {
|
|
364
|
+
watchers.delete(wrappedCallback);
|
|
365
|
+
if (watchers.size === 0) {
|
|
366
|
+
this.watchers.delete(key);
|
|
367
|
+
const interval = this.pollIntervals.get(key);
|
|
368
|
+
if (interval) {
|
|
369
|
+
clearInterval(interval);
|
|
370
|
+
this.pollIntervals.delete(key);
|
|
371
|
+
}
|
|
372
|
+
this.lastValues.delete(key);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Clean up all resources
|
|
378
|
+
*/
|
|
379
|
+
dispose() {
|
|
380
|
+
for (const interval of this.pollIntervals.values()) {
|
|
381
|
+
clearInterval(interval);
|
|
382
|
+
}
|
|
383
|
+
this.pollIntervals.clear();
|
|
384
|
+
this.watchers.clear();
|
|
385
|
+
this.lastValues.clear();
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
|
|
30
391
|
// src/index.ts
|
|
31
392
|
var src_exports = {};
|
|
32
393
|
__export(src_exports, {
|
|
@@ -45,6 +406,7 @@ __export(src_exports, {
|
|
|
45
406
|
RegistryIntrospector: () => RegistryIntrospector,
|
|
46
407
|
StateDocsGenerator: () => StateDocsGenerator,
|
|
47
408
|
TerminalAdapter: () => TerminalAdapter,
|
|
409
|
+
attachAllIntegrations: () => attachAllIntegrations,
|
|
48
410
|
attachTauriToEngine: () => attachTauriToEngine,
|
|
49
411
|
attachToEngine: () => attachToEngine,
|
|
50
412
|
attachUnumToEngine: () => attachUnumToEngine,
|
|
@@ -69,6 +431,7 @@ __export(src_exports, {
|
|
|
69
431
|
createTauriPraxisAdapter: () => createTauriPraxisAdapter,
|
|
70
432
|
createTerminalAdapter: () => createTerminalAdapter,
|
|
71
433
|
createTimerActor: () => createTimerActor,
|
|
434
|
+
createUnifiedApp: () => createUnifiedApp,
|
|
72
435
|
createUnumAdapter: () => createUnumAdapter,
|
|
73
436
|
defineConstraint: () => defineConstraint,
|
|
74
437
|
defineEvent: () => defineEvent,
|
|
@@ -97,9 +460,7 @@ __export(src_exports, {
|
|
|
97
460
|
validateWithGuardian: () => validateWithGuardian
|
|
98
461
|
});
|
|
99
462
|
module.exports = __toCommonJS(src_exports);
|
|
100
|
-
|
|
101
|
-
// src/core/protocol.ts
|
|
102
|
-
var PRAXIS_PROTOCOL_VERSION = "1.0.0";
|
|
463
|
+
init_protocol();
|
|
103
464
|
|
|
104
465
|
// src/core/rules.ts
|
|
105
466
|
var PraxisRegistry = class {
|
|
@@ -172,197 +533,12 @@ var PraxisRegistry = class {
|
|
|
172
533
|
}
|
|
173
534
|
};
|
|
174
535
|
|
|
175
|
-
// src/
|
|
176
|
-
|
|
177
|
-
if (value === null || typeof value !== "object") {
|
|
178
|
-
return value;
|
|
179
|
-
}
|
|
180
|
-
if (typeof globalThis.structuredClone === "function") {
|
|
181
|
-
try {
|
|
182
|
-
return globalThis.structuredClone(value);
|
|
183
|
-
} catch {
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (Array.isArray(value)) {
|
|
187
|
-
return [...value];
|
|
188
|
-
}
|
|
189
|
-
return { ...value };
|
|
190
|
-
}
|
|
191
|
-
var LogicEngine = class {
|
|
192
|
-
state;
|
|
193
|
-
registry;
|
|
194
|
-
constructor(options) {
|
|
195
|
-
this.registry = options.registry;
|
|
196
|
-
this.state = {
|
|
197
|
-
context: options.initialContext,
|
|
198
|
-
facts: options.initialFacts ?? [],
|
|
199
|
-
meta: options.initialMeta ?? {},
|
|
200
|
-
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Get the current state (immutable copy)
|
|
205
|
-
*/
|
|
206
|
-
getState() {
|
|
207
|
-
return {
|
|
208
|
-
context: safeClone(this.state.context),
|
|
209
|
-
facts: [...this.state.facts],
|
|
210
|
-
meta: this.state.meta ? safeClone(this.state.meta) : void 0,
|
|
211
|
-
protocolVersion: this.state.protocolVersion
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Get the current context
|
|
216
|
-
*/
|
|
217
|
-
getContext() {
|
|
218
|
-
return safeClone(this.state.context);
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Get current facts
|
|
222
|
-
*/
|
|
223
|
-
getFacts() {
|
|
224
|
-
return [...this.state.facts];
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Process events through the engine.
|
|
228
|
-
* Applies all registered rules and checks all registered constraints.
|
|
229
|
-
*
|
|
230
|
-
* @param events Events to process
|
|
231
|
-
* @returns Result with new state and diagnostics
|
|
232
|
-
*/
|
|
233
|
-
step(events) {
|
|
234
|
-
const config = {
|
|
235
|
-
ruleIds: this.registry.getRuleIds(),
|
|
236
|
-
constraintIds: this.registry.getConstraintIds()
|
|
237
|
-
};
|
|
238
|
-
return this.stepWithConfig(events, config);
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Process events with specific rule and constraint configuration.
|
|
242
|
-
*
|
|
243
|
-
* @param events Events to process
|
|
244
|
-
* @param config Step configuration
|
|
245
|
-
* @returns Result with new state and diagnostics
|
|
246
|
-
*/
|
|
247
|
-
stepWithConfig(events, config) {
|
|
248
|
-
const diagnostics = [];
|
|
249
|
-
let newState = { ...this.state };
|
|
250
|
-
const newFacts = [];
|
|
251
|
-
for (const ruleId of config.ruleIds) {
|
|
252
|
-
const rule = this.registry.getRule(ruleId);
|
|
253
|
-
if (!rule) {
|
|
254
|
-
diagnostics.push({
|
|
255
|
-
kind: "rule-error",
|
|
256
|
-
message: `Rule "${ruleId}" not found in registry`,
|
|
257
|
-
data: { ruleId }
|
|
258
|
-
});
|
|
259
|
-
continue;
|
|
260
|
-
}
|
|
261
|
-
try {
|
|
262
|
-
const ruleFacts = rule.impl(newState, events);
|
|
263
|
-
newFacts.push(...ruleFacts);
|
|
264
|
-
} catch (error) {
|
|
265
|
-
diagnostics.push({
|
|
266
|
-
kind: "rule-error",
|
|
267
|
-
message: `Error executing rule "${ruleId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
268
|
-
data: { ruleId, error }
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
newState = {
|
|
273
|
-
...newState,
|
|
274
|
-
facts: [...newState.facts, ...newFacts]
|
|
275
|
-
};
|
|
276
|
-
for (const constraintId of config.constraintIds) {
|
|
277
|
-
const constraint = this.registry.getConstraint(constraintId);
|
|
278
|
-
if (!constraint) {
|
|
279
|
-
diagnostics.push({
|
|
280
|
-
kind: "constraint-violation",
|
|
281
|
-
message: `Constraint "${constraintId}" not found in registry`,
|
|
282
|
-
data: { constraintId }
|
|
283
|
-
});
|
|
284
|
-
continue;
|
|
285
|
-
}
|
|
286
|
-
try {
|
|
287
|
-
const result = constraint.impl(newState);
|
|
288
|
-
if (result === false) {
|
|
289
|
-
diagnostics.push({
|
|
290
|
-
kind: "constraint-violation",
|
|
291
|
-
message: `Constraint "${constraintId}" violated`,
|
|
292
|
-
data: { constraintId, description: constraint.description }
|
|
293
|
-
});
|
|
294
|
-
} else if (typeof result === "string") {
|
|
295
|
-
diagnostics.push({
|
|
296
|
-
kind: "constraint-violation",
|
|
297
|
-
message: result,
|
|
298
|
-
data: { constraintId, description: constraint.description }
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
} catch (error) {
|
|
302
|
-
diagnostics.push({
|
|
303
|
-
kind: "constraint-violation",
|
|
304
|
-
message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
305
|
-
data: { constraintId, error }
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
this.state = newState;
|
|
310
|
-
return {
|
|
311
|
-
state: newState,
|
|
312
|
-
diagnostics
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Update the context directly (for exceptional cases).
|
|
317
|
-
* Generally, context should be updated through rules.
|
|
318
|
-
*
|
|
319
|
-
* @param updater Function that produces new context from old context
|
|
320
|
-
*/
|
|
321
|
-
updateContext(updater) {
|
|
322
|
-
this.state = {
|
|
323
|
-
...this.state,
|
|
324
|
-
context: updater(this.state.context)
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Add facts directly (for exceptional cases).
|
|
329
|
-
* Generally, facts should be added through rules.
|
|
330
|
-
*
|
|
331
|
-
* @param facts Facts to add
|
|
332
|
-
*/
|
|
333
|
-
addFacts(facts) {
|
|
334
|
-
this.state = {
|
|
335
|
-
...this.state,
|
|
336
|
-
facts: [...this.state.facts, ...facts]
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Clear all facts
|
|
341
|
-
*/
|
|
342
|
-
clearFacts() {
|
|
343
|
-
this.state = {
|
|
344
|
-
...this.state,
|
|
345
|
-
facts: []
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* Reset the engine to initial state
|
|
350
|
-
*/
|
|
351
|
-
reset(options) {
|
|
352
|
-
this.state = {
|
|
353
|
-
context: options.initialContext,
|
|
354
|
-
facts: options.initialFacts ?? [],
|
|
355
|
-
meta: options.initialMeta ?? {},
|
|
356
|
-
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
function createPraxisEngine(options) {
|
|
361
|
-
return new LogicEngine(options);
|
|
362
|
-
}
|
|
536
|
+
// src/index.ts
|
|
537
|
+
init_engine();
|
|
363
538
|
|
|
364
539
|
// src/core/reactive-engine.svelte.ts
|
|
365
540
|
var $ = __toESM(require("svelte/internal/client"), 1);
|
|
541
|
+
init_engine();
|
|
366
542
|
var ReactiveLogicEngine = class {
|
|
367
543
|
#state = (
|
|
368
544
|
// Use Svelte's $state rune for automatic reactivity
|
|
@@ -1830,140 +2006,8 @@ function createPraxisDBStore(db, registry, initialContext, onRuleError) {
|
|
|
1830
2006
|
return new PraxisDBStore({ db, registry, initialContext, onRuleError });
|
|
1831
2007
|
}
|
|
1832
2008
|
|
|
1833
|
-
// src/
|
|
1834
|
-
|
|
1835
|
-
store = /* @__PURE__ */ new Map();
|
|
1836
|
-
watchers = /* @__PURE__ */ new Map();
|
|
1837
|
-
async get(key) {
|
|
1838
|
-
return this.store.get(key);
|
|
1839
|
-
}
|
|
1840
|
-
async set(key, value) {
|
|
1841
|
-
this.store.set(key, value);
|
|
1842
|
-
const keyWatchers = this.watchers.get(key);
|
|
1843
|
-
if (keyWatchers) {
|
|
1844
|
-
for (const callback of keyWatchers) {
|
|
1845
|
-
callback(value);
|
|
1846
|
-
}
|
|
1847
|
-
}
|
|
1848
|
-
}
|
|
1849
|
-
watch(key, callback) {
|
|
1850
|
-
if (!this.watchers.has(key)) {
|
|
1851
|
-
this.watchers.set(key, /* @__PURE__ */ new Set());
|
|
1852
|
-
}
|
|
1853
|
-
const watchers = this.watchers.get(key);
|
|
1854
|
-
const wrappedCallback = (val) => callback(val);
|
|
1855
|
-
watchers.add(wrappedCallback);
|
|
1856
|
-
return () => {
|
|
1857
|
-
watchers.delete(wrappedCallback);
|
|
1858
|
-
if (watchers.size === 0) {
|
|
1859
|
-
this.watchers.delete(key);
|
|
1860
|
-
}
|
|
1861
|
-
};
|
|
1862
|
-
}
|
|
1863
|
-
/**
|
|
1864
|
-
* Get all keys (for testing/debugging)
|
|
1865
|
-
*/
|
|
1866
|
-
keys() {
|
|
1867
|
-
return Array.from(this.store.keys());
|
|
1868
|
-
}
|
|
1869
|
-
/**
|
|
1870
|
-
* Clear all data (for testing)
|
|
1871
|
-
*/
|
|
1872
|
-
clear() {
|
|
1873
|
-
this.store.clear();
|
|
1874
|
-
this.watchers.clear();
|
|
1875
|
-
}
|
|
1876
|
-
};
|
|
1877
|
-
function createInMemoryDB() {
|
|
1878
|
-
return new InMemoryPraxisDB();
|
|
1879
|
-
}
|
|
1880
|
-
var PluresDBPraxisAdapter = class {
|
|
1881
|
-
db;
|
|
1882
|
-
watchers = /* @__PURE__ */ new Map();
|
|
1883
|
-
pollIntervals = /* @__PURE__ */ new Map();
|
|
1884
|
-
lastValues = /* @__PURE__ */ new Map();
|
|
1885
|
-
pollInterval;
|
|
1886
|
-
constructor(config) {
|
|
1887
|
-
if ("get" in config && "put" in config) {
|
|
1888
|
-
this.db = config;
|
|
1889
|
-
this.pollInterval = 1e3;
|
|
1890
|
-
} else {
|
|
1891
|
-
this.db = config.db;
|
|
1892
|
-
this.pollInterval = config.pollInterval ?? 1e3;
|
|
1893
|
-
}
|
|
1894
|
-
}
|
|
1895
|
-
async get(key) {
|
|
1896
|
-
try {
|
|
1897
|
-
const value = await this.db.get(key);
|
|
1898
|
-
return value;
|
|
1899
|
-
} catch (error) {
|
|
1900
|
-
return void 0;
|
|
1901
|
-
}
|
|
1902
|
-
}
|
|
1903
|
-
async set(key, value) {
|
|
1904
|
-
await this.db.put(key, value);
|
|
1905
|
-
this.lastValues.set(key, value);
|
|
1906
|
-
const keyWatchers = this.watchers.get(key);
|
|
1907
|
-
if (keyWatchers) {
|
|
1908
|
-
for (const callback of keyWatchers) {
|
|
1909
|
-
callback(value);
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
watch(key, callback) {
|
|
1914
|
-
if (!this.watchers.has(key)) {
|
|
1915
|
-
this.watchers.set(key, /* @__PURE__ */ new Set());
|
|
1916
|
-
}
|
|
1917
|
-
const watchers = this.watchers.get(key);
|
|
1918
|
-
const wrappedCallback = (val) => callback(val);
|
|
1919
|
-
watchers.add(wrappedCallback);
|
|
1920
|
-
if (!this.pollIntervals.has(key)) {
|
|
1921
|
-
const interval = setInterval(async () => {
|
|
1922
|
-
try {
|
|
1923
|
-
const value = await this.db.get(key);
|
|
1924
|
-
const lastValue = this.lastValues.get(key);
|
|
1925
|
-
if (JSON.stringify(value) !== JSON.stringify(lastValue)) {
|
|
1926
|
-
this.lastValues.set(key, value);
|
|
1927
|
-
const currentWatchers = this.watchers.get(key);
|
|
1928
|
-
if (currentWatchers) {
|
|
1929
|
-
for (const cb of currentWatchers) {
|
|
1930
|
-
cb(value);
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
} catch (error) {
|
|
1935
|
-
}
|
|
1936
|
-
}, this.pollInterval);
|
|
1937
|
-
this.pollIntervals.set(key, interval);
|
|
1938
|
-
}
|
|
1939
|
-
return () => {
|
|
1940
|
-
watchers.delete(wrappedCallback);
|
|
1941
|
-
if (watchers.size === 0) {
|
|
1942
|
-
this.watchers.delete(key);
|
|
1943
|
-
const interval = this.pollIntervals.get(key);
|
|
1944
|
-
if (interval) {
|
|
1945
|
-
clearInterval(interval);
|
|
1946
|
-
this.pollIntervals.delete(key);
|
|
1947
|
-
}
|
|
1948
|
-
this.lastValues.delete(key);
|
|
1949
|
-
}
|
|
1950
|
-
};
|
|
1951
|
-
}
|
|
1952
|
-
/**
|
|
1953
|
-
* Clean up all resources
|
|
1954
|
-
*/
|
|
1955
|
-
dispose() {
|
|
1956
|
-
for (const interval of this.pollIntervals.values()) {
|
|
1957
|
-
clearInterval(interval);
|
|
1958
|
-
}
|
|
1959
|
-
this.pollIntervals.clear();
|
|
1960
|
-
this.watchers.clear();
|
|
1961
|
-
this.lastValues.clear();
|
|
1962
|
-
}
|
|
1963
|
-
};
|
|
1964
|
-
function createPluresDB(config) {
|
|
1965
|
-
return new PluresDBPraxisAdapter(config);
|
|
1966
|
-
}
|
|
2009
|
+
// src/integrations/pluresdb.ts
|
|
2010
|
+
init_adapter();
|
|
1967
2011
|
|
|
1968
2012
|
// src/core/pluresdb/schema-registry.ts
|
|
1969
2013
|
function getSchemaPath(schemaName) {
|
|
@@ -3512,6 +3556,138 @@ function generateTauriConfig(config) {
|
|
|
3512
3556
|
plugins: Object.fromEntries((config.plugins || []).map((p) => [p.name, p.config || {}]))
|
|
3513
3557
|
};
|
|
3514
3558
|
}
|
|
3559
|
+
|
|
3560
|
+
// src/integrations/unified.ts
|
|
3561
|
+
async function createUnifiedApp(config) {
|
|
3562
|
+
const { createPraxisEngine: createPraxisEngine2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
|
|
3563
|
+
const { createInMemoryDB: createInMemoryDB2 } = await Promise.resolve().then(() => (init_adapter(), adapter_exports));
|
|
3564
|
+
const db = config.db || createInMemoryDB2();
|
|
3565
|
+
const pluresdb = createPluresDBAdapter({
|
|
3566
|
+
db,
|
|
3567
|
+
registry: config.registry,
|
|
3568
|
+
initialContext: config.initialContext
|
|
3569
|
+
});
|
|
3570
|
+
const engine = createPraxisEngine2({
|
|
3571
|
+
initialContext: config.initialContext,
|
|
3572
|
+
registry: config.registry
|
|
3573
|
+
});
|
|
3574
|
+
pluresdb.attachEngine(engine);
|
|
3575
|
+
const disposers = [];
|
|
3576
|
+
let unum;
|
|
3577
|
+
let channel;
|
|
3578
|
+
if (config.enableUnum) {
|
|
3579
|
+
const fullIdentity = config.unumIdentity ? {
|
|
3580
|
+
...config.unumIdentity,
|
|
3581
|
+
id: generateId(),
|
|
3582
|
+
createdAt: Date.now()
|
|
3583
|
+
} : void 0;
|
|
3584
|
+
unum = await createUnumAdapter({
|
|
3585
|
+
db,
|
|
3586
|
+
identity: fullIdentity,
|
|
3587
|
+
realtime: true
|
|
3588
|
+
});
|
|
3589
|
+
channel = await unum.createChannel(
|
|
3590
|
+
config.unumIdentity?.name || "praxis-app",
|
|
3591
|
+
[]
|
|
3592
|
+
);
|
|
3593
|
+
const unumDisposer = attachUnumToEngine(engine, unum, channel.id);
|
|
3594
|
+
disposers.push(unumDisposer);
|
|
3595
|
+
}
|
|
3596
|
+
let docs;
|
|
3597
|
+
let generateDocs2;
|
|
3598
|
+
if (config.enableDocs && config.docsConfig) {
|
|
3599
|
+
docs = createStateDocsGenerator({
|
|
3600
|
+
projectTitle: config.docsConfig.projectTitle,
|
|
3601
|
+
target: config.docsConfig.target || "./docs"
|
|
3602
|
+
});
|
|
3603
|
+
generateDocs2 = () => {
|
|
3604
|
+
const module2 = {
|
|
3605
|
+
rules: config.registry.getAllRules(),
|
|
3606
|
+
constraints: config.registry.getAllConstraints()
|
|
3607
|
+
};
|
|
3608
|
+
return docs.generateFromModule(module2);
|
|
3609
|
+
};
|
|
3610
|
+
}
|
|
3611
|
+
let canvas;
|
|
3612
|
+
if (config.schema) {
|
|
3613
|
+
canvas = schemaToCanvas(config.schema, { layout: "hierarchical" });
|
|
3614
|
+
}
|
|
3615
|
+
return {
|
|
3616
|
+
engine,
|
|
3617
|
+
pluresdb,
|
|
3618
|
+
unum,
|
|
3619
|
+
channel,
|
|
3620
|
+
docs,
|
|
3621
|
+
canvas,
|
|
3622
|
+
generateDocs: generateDocs2,
|
|
3623
|
+
dispose: () => {
|
|
3624
|
+
pluresdb.dispose();
|
|
3625
|
+
if (unum) {
|
|
3626
|
+
unum.disconnect().catch((err) => {
|
|
3627
|
+
console.warn("Warning: Error during Unum disconnect:", err);
|
|
3628
|
+
});
|
|
3629
|
+
}
|
|
3630
|
+
for (const disposer of disposers) {
|
|
3631
|
+
disposer();
|
|
3632
|
+
}
|
|
3633
|
+
}
|
|
3634
|
+
};
|
|
3635
|
+
}
|
|
3636
|
+
async function attachAllIntegrations(engine, registry, options = {}) {
|
|
3637
|
+
const { createInMemoryDB: createInMemoryDB2 } = await Promise.resolve().then(() => (init_adapter(), adapter_exports));
|
|
3638
|
+
const db = options.db || createInMemoryDB2();
|
|
3639
|
+
const pluresdb = createPluresDBAdapter({
|
|
3640
|
+
db,
|
|
3641
|
+
registry,
|
|
3642
|
+
initialContext: engine.getContext()
|
|
3643
|
+
});
|
|
3644
|
+
pluresdb.attachEngine(engine);
|
|
3645
|
+
const disposers = [];
|
|
3646
|
+
let unum;
|
|
3647
|
+
let channel;
|
|
3648
|
+
if (options.enableUnum) {
|
|
3649
|
+
const fullIdentity = options.unumIdentity ? {
|
|
3650
|
+
...options.unumIdentity,
|
|
3651
|
+
id: generateId(),
|
|
3652
|
+
createdAt: Date.now()
|
|
3653
|
+
} : void 0;
|
|
3654
|
+
unum = await createUnumAdapter({
|
|
3655
|
+
db,
|
|
3656
|
+
identity: fullIdentity,
|
|
3657
|
+
realtime: true
|
|
3658
|
+
});
|
|
3659
|
+
channel = await unum.createChannel(
|
|
3660
|
+
options.unumIdentity?.name || "praxis-app",
|
|
3661
|
+
[]
|
|
3662
|
+
);
|
|
3663
|
+
const unumDisposer = attachUnumToEngine(engine, unum, channel.id);
|
|
3664
|
+
disposers.push(unumDisposer);
|
|
3665
|
+
}
|
|
3666
|
+
let docs;
|
|
3667
|
+
if (options.enableDocs && options.docsConfig) {
|
|
3668
|
+
docs = createStateDocsGenerator({
|
|
3669
|
+
projectTitle: options.docsConfig.projectTitle,
|
|
3670
|
+
target: options.docsConfig.target || "./docs"
|
|
3671
|
+
});
|
|
3672
|
+
}
|
|
3673
|
+
return {
|
|
3674
|
+
pluresdb,
|
|
3675
|
+
unum,
|
|
3676
|
+
channel,
|
|
3677
|
+
docs,
|
|
3678
|
+
dispose: () => {
|
|
3679
|
+
pluresdb.dispose();
|
|
3680
|
+
if (unum) {
|
|
3681
|
+
unum.disconnect().catch((err) => {
|
|
3682
|
+
console.warn("Warning: Error during Unum disconnect:", err);
|
|
3683
|
+
});
|
|
3684
|
+
}
|
|
3685
|
+
for (const disposer of disposers) {
|
|
3686
|
+
disposer();
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
};
|
|
3690
|
+
}
|
|
3515
3691
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3516
3692
|
0 && (module.exports = {
|
|
3517
3693
|
ActorManager,
|
|
@@ -3529,6 +3705,7 @@ function generateTauriConfig(config) {
|
|
|
3529
3705
|
RegistryIntrospector,
|
|
3530
3706
|
StateDocsGenerator,
|
|
3531
3707
|
TerminalAdapter,
|
|
3708
|
+
attachAllIntegrations,
|
|
3532
3709
|
attachTauriToEngine,
|
|
3533
3710
|
attachToEngine,
|
|
3534
3711
|
attachUnumToEngine,
|
|
@@ -3553,6 +3730,7 @@ function generateTauriConfig(config) {
|
|
|
3553
3730
|
createTauriPraxisAdapter,
|
|
3554
3731
|
createTerminalAdapter,
|
|
3555
3732
|
createTimerActor,
|
|
3733
|
+
createUnifiedApp,
|
|
3556
3734
|
createUnumAdapter,
|
|
3557
3735
|
defineConstraint,
|
|
3558
3736
|
defineEvent,
|