@plures/praxis 1.1.2 → 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 +67 -6
- 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 +284 -22
- 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/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
dotnet build
|
|
2
2
|
dotnet test
|
|
3
|
-
# Praxis
|
|
3
|
+
# Praxis
|
|
4
4
|
|
|
5
5
|
**Typed, visual-first application logic for Svelte, Node, and the browser.**
|
|
6
6
|
|
|
@@ -10,19 +10,20 @@ dotnet test
|
|
|
10
10
|
[](https://nodejs.org/)
|
|
11
11
|
[](https://deno.land/)
|
|
12
12
|
|
|
13
|
-
Praxis is a schema-driven, rule-based engine with first-class Svelte 5 integration, component generation, and optional cloud sync.
|
|
13
|
+
Praxis is a schema-driven, rule-based engine with first-class Svelte 5 integration, component generation, and optional cloud sync. The library delivers a unified ESM/CJS build, curated subpath exports, Svelte runes support, and a slimmer, publish-ready package for npm and JSR.
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
## What’s new
|
|
17
|
+
## What’s new
|
|
18
18
|
- **Unified builds & exports**: `./`, `./svelte`, `./schema`, `./component`, `./cloud`, `./components`, and CLI all ship with ESM, CJS, and type definitions.
|
|
19
19
|
- **Svelte 5 runes native**: Runes-friendly stores and helpers; server+client builds for integrations.
|
|
20
|
+
- **Framework-agnostic reactivity**: Proxy-based reactive engine for use without Svelte, enabling reactive state management in Node.js, browsers, and any JavaScript environment.
|
|
20
21
|
- **Logic engine refinements**: Typed registry, step diagnostics, and trace-friendly rule execution.
|
|
21
22
|
- **Cloud relay & local-first**: Polished cloud connector alongside PluresDB-first workflows.
|
|
22
23
|
- **Publish-ready**: npm public access + JSR exports aligned to source.
|
|
23
24
|
|
|
24
25
|
## Capabilities at a glance
|
|
25
|
-
- **Logic Engine**: Facts, events, rules, constraints, registry, introspection, and reactive engine
|
|
26
|
+
- **Logic Engine**: Facts, events, rules, constraints, registry, introspection, and reactive engine variants (Svelte 5 + framework-agnostic).
|
|
26
27
|
- **Schema & Codegen**: PSF-style schema types plus component generator for Svelte UIs.
|
|
27
28
|
- **Svelte Integration**: Typed helpers, runes-ready builds, and Svelte component typings.
|
|
28
29
|
- **Local-First Data**: PluresDB integrations for offline-first, reactive state.
|
|
@@ -100,16 +101,47 @@ engine.step([Login.create({ username: 'alex' })]);
|
|
|
100
101
|
registry.registerRule(counterRule);
|
|
101
102
|
|
|
102
103
|
const engine = createReactiveEngine({ initialContext: { count: 0 }, registry });
|
|
103
|
-
|
|
104
|
+
|
|
105
|
+
// Use Svelte's $derived with the reactive engine state
|
|
106
|
+
const count = $derived(engine.context.count);
|
|
104
107
|
|
|
105
108
|
function addOne() {
|
|
106
109
|
engine.step([Increment.create({ amount: 1 })]);
|
|
107
110
|
}
|
|
108
111
|
</script>
|
|
109
112
|
|
|
110
|
-
<button on:click={addOne}>Count is {
|
|
113
|
+
<button on:click={addOne}>Count is {count}</button>
|
|
111
114
|
```
|
|
112
115
|
|
|
116
|
+
## Framework-agnostic reactive engine
|
|
117
|
+
For non-Svelte environments, use the framework-agnostic reactive engine with Proxy-based reactivity:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { createFrameworkAgnosticReactiveEngine } from '@plures/praxis';
|
|
121
|
+
|
|
122
|
+
const engine = createFrameworkAgnosticReactiveEngine({
|
|
123
|
+
initialContext: { count: 0 },
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Subscribe to state changes
|
|
127
|
+
engine.subscribe((state) => {
|
|
128
|
+
console.log('Count:', state.context.count);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Create derived/computed values
|
|
132
|
+
const doubled = engine.$derived((state) => state.context.count * 2);
|
|
133
|
+
doubled.subscribe((value) => {
|
|
134
|
+
console.log('Doubled:', value);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Apply mutations (batched for performance)
|
|
138
|
+
engine.apply((state) => {
|
|
139
|
+
state.context.count += 1;
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
See the [reactive counter example](./examples/reactive-counter/README.md) for a complete demonstration.
|
|
144
|
+
|
|
113
145
|
## Cloud relay (optional)
|
|
114
146
|
```ts
|
|
115
147
|
import { connectRelay } from '@plures/praxis/cloud';
|
|
@@ -129,6 +161,35 @@ await relay.sync({
|
|
|
129
161
|
});
|
|
130
162
|
```
|
|
131
163
|
|
|
164
|
+
## PluresDB integration
|
|
165
|
+
```ts
|
|
166
|
+
import { PluresNode } from 'pluresdb';
|
|
167
|
+
import { createPluresDB, createPraxisDBStore } from '@plures/praxis';
|
|
168
|
+
import { PraxisRegistry } from '@plures/praxis';
|
|
169
|
+
|
|
170
|
+
// Initialize the official PluresDB from npm
|
|
171
|
+
const pluresdb = new PluresNode({
|
|
172
|
+
config: {
|
|
173
|
+
port: 34567,
|
|
174
|
+
dataDir: './data',
|
|
175
|
+
},
|
|
176
|
+
autoStart: true,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Wrap it with the Praxis adapter
|
|
180
|
+
const db = createPluresDB(pluresdb);
|
|
181
|
+
|
|
182
|
+
// Use with Praxis store for local-first reactive data
|
|
183
|
+
const registry = new PraxisRegistry();
|
|
184
|
+
const store = createPraxisDBStore(db, registry);
|
|
185
|
+
|
|
186
|
+
// Or use in-memory database for development/testing
|
|
187
|
+
import { createInMemoryDB } from '@plures/praxis';
|
|
188
|
+
const devDb = createInMemoryDB();
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
> **Note:** Praxis now uses the official [PluresDB package from NPM](https://www.npmjs.com/package/pluresdb), which provides P2P sync, CRDT conflict resolution, SQLite compatibility, and more. The `createPluresDB()` function wraps PluresDB to provide the `PraxisDB` interface used by Praxis.
|
|
192
|
+
|
|
132
193
|
## CLI (npx-friendly)
|
|
133
194
|
```bash
|
|
134
195
|
npx praxis --help
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
// src/core/protocol.ts
|
|
2
|
+
var PRAXIS_PROTOCOL_VERSION = "1.0.0";
|
|
3
|
+
|
|
4
|
+
// src/core/rules.ts
|
|
5
|
+
var PraxisRegistry = class {
|
|
6
|
+
rules = /* @__PURE__ */ new Map();
|
|
7
|
+
constraints = /* @__PURE__ */ new Map();
|
|
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
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/core/engine.ts
|
|
76
|
+
function safeClone(value) {
|
|
77
|
+
if (value === null || typeof value !== "object") {
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
if (typeof globalThis.structuredClone === "function") {
|
|
81
|
+
try {
|
|
82
|
+
return globalThis.structuredClone(value);
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
return [...value];
|
|
88
|
+
}
|
|
89
|
+
return { ...value };
|
|
90
|
+
}
|
|
91
|
+
var LogicEngine = class {
|
|
92
|
+
state;
|
|
93
|
+
registry;
|
|
94
|
+
constructor(options) {
|
|
95
|
+
this.registry = options.registry;
|
|
96
|
+
this.state = {
|
|
97
|
+
context: options.initialContext,
|
|
98
|
+
facts: options.initialFacts ?? [],
|
|
99
|
+
meta: options.initialMeta ?? {},
|
|
100
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get the current state (immutable copy)
|
|
105
|
+
*/
|
|
106
|
+
getState() {
|
|
107
|
+
return {
|
|
108
|
+
context: safeClone(this.state.context),
|
|
109
|
+
facts: [...this.state.facts],
|
|
110
|
+
meta: this.state.meta ? safeClone(this.state.meta) : void 0,
|
|
111
|
+
protocolVersion: this.state.protocolVersion
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get the current context
|
|
116
|
+
*/
|
|
117
|
+
getContext() {
|
|
118
|
+
return safeClone(this.state.context);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get current facts
|
|
122
|
+
*/
|
|
123
|
+
getFacts() {
|
|
124
|
+
return [...this.state.facts];
|
|
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
|
+
}
|
|
171
|
+
}
|
|
172
|
+
newState = {
|
|
173
|
+
...newState,
|
|
174
|
+
facts: [...newState.facts, ...newFacts]
|
|
175
|
+
};
|
|
176
|
+
for (const constraintId of config.constraintIds) {
|
|
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
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const result = constraint.impl(newState);
|
|
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
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
diagnostics.push({
|
|
203
|
+
kind: "constraint-violation",
|
|
204
|
+
message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
205
|
+
data: { constraintId, error }
|
|
206
|
+
});
|
|
207
|
+
}
|
|
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
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Reset the engine to initial state
|
|
250
|
+
*/
|
|
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
|
+
// Use Svelte's $state rune for automatic reactivity
|
|
269
|
+
$.state($.proxy({ context: {}, facts: [], meta: {} }))
|
|
270
|
+
);
|
|
271
|
+
get state() {
|
|
272
|
+
return $.get(this.#state);
|
|
273
|
+
}
|
|
274
|
+
set state(value) {
|
|
275
|
+
$.set(this.#state, value, true);
|
|
276
|
+
}
|
|
277
|
+
_engine;
|
|
278
|
+
constructor(options) {
|
|
279
|
+
this.state.context = options.initialContext;
|
|
280
|
+
this.state.facts = options.initialFacts ?? [];
|
|
281
|
+
this.state.meta = options.initialMeta ?? {};
|
|
282
|
+
if (options.registry) {
|
|
283
|
+
this._engine = createPraxisEngine({
|
|
284
|
+
initialContext: options.initialContext,
|
|
285
|
+
registry: options.registry
|
|
286
|
+
});
|
|
287
|
+
} else {
|
|
288
|
+
this._engine = createPraxisEngine({
|
|
289
|
+
initialContext: options.initialContext,
|
|
290
|
+
registry: new PraxisRegistry()
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Access the reactive context.
|
|
296
|
+
* In Svelte 5 components, changes to this object will automatically trigger updates.
|
|
297
|
+
*/
|
|
298
|
+
get context() {
|
|
299
|
+
return this.state.context;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Access the reactive facts list.
|
|
303
|
+
*/
|
|
304
|
+
get facts() {
|
|
305
|
+
return this.state.facts;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Access the reactive metadata.
|
|
309
|
+
*/
|
|
310
|
+
get meta() {
|
|
311
|
+
return this.state.meta;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Apply a mutation to the state.
|
|
315
|
+
* Changes will automatically trigger Svelte reactivity.
|
|
316
|
+
*
|
|
317
|
+
* @param mutator A function that receives the state and modifies it.
|
|
318
|
+
*/
|
|
319
|
+
apply(mutator) {
|
|
320
|
+
mutator(this.state);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Process events through the logic engine and update reactive state.
|
|
324
|
+
*
|
|
325
|
+
* @param events Events to process
|
|
326
|
+
*/
|
|
327
|
+
step(events) {
|
|
328
|
+
const result = this._engine.step(events);
|
|
329
|
+
this.state.context = result.state.context;
|
|
330
|
+
this.state.facts = result.state.facts;
|
|
331
|
+
this.state.meta = result.state.meta ?? {};
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
function createReactiveEngine(options) {
|
|
335
|
+
return new ReactiveLogicEngine(options);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export {
|
|
339
|
+
PRAXIS_PROTOCOL_VERSION,
|
|
340
|
+
PraxisRegistry,
|
|
341
|
+
LogicEngine,
|
|
342
|
+
createPraxisEngine,
|
|
343
|
+
ReactiveLogicEngine,
|
|
344
|
+
createReactiveEngine
|
|
345
|
+
};
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -1,36 +1,85 @@
|
|
|
1
|
-
import { L as LogicEngine, P as PraxisState, a as PraxisEvent, b as PraxisRegistry, R as RuleDescriptor, C as ConstraintDescriptor, c as PraxisFact, d as RuleFn, e as ConstraintFn, f as PraxisModule } from './engine-
|
|
2
|
-
export { m as ConstraintId, k as PRAXIS_PROTOCOL_VERSION, g as PraxisDiagnostics, n as PraxisEngineOptions, h as PraxisStepConfig, j as PraxisStepFn, i as PraxisStepResult, l as RuleId, o as createPraxisEngine } from './engine-
|
|
1
|
+
import { L as LogicEngine, P as PraxisState, a as PraxisEvent, b as PraxisRegistry, R as RuleDescriptor, C as ConstraintDescriptor, c as PraxisFact, d as RuleFn, e as ConstraintFn, f as PraxisModule } from './reactive-engine.svelte-C9OpcTHf.js';
|
|
2
|
+
export { m as ConstraintId, k as PRAXIS_PROTOCOL_VERSION, g as PraxisDiagnostics, n as PraxisEngineOptions, h as PraxisStepConfig, j as PraxisStepFn, i as PraxisStepResult, p as ReactiveEngineOptions, q as ReactiveLogicEngine, l as RuleId, o as createPraxisEngine, r as createReactiveEngine } from './reactive-engine.svelte-C9OpcTHf.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Praxis Reactive Logic Engine
|
|
6
6
|
*
|
|
7
|
-
* A
|
|
8
|
-
* Uses
|
|
7
|
+
* A framework-agnostic reactive implementation of the Praxis Logic Engine.
|
|
8
|
+
* Uses JavaScript Proxies to provide reactivity without Svelte-specific primitives.
|
|
9
|
+
*
|
|
10
|
+
* This implementation provides:
|
|
11
|
+
* - Proxy-based state tracking for automatic reactivity
|
|
12
|
+
* - Subscription-based change notifications
|
|
13
|
+
* - Computed/derived values support
|
|
14
|
+
* - Compatible API with Svelte-based implementation
|
|
9
15
|
*/
|
|
10
16
|
interface ReactiveEngineOptions<TContext> {
|
|
11
17
|
initialContext: TContext;
|
|
12
18
|
initialFacts?: any[];
|
|
13
19
|
initialMeta?: Record<string, unknown>;
|
|
14
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Callback type for state change subscribers
|
|
23
|
+
*/
|
|
24
|
+
type StateChangeCallback<TContext> = (state: {
|
|
25
|
+
context: TContext;
|
|
26
|
+
facts: any[];
|
|
27
|
+
meta: Record<string, unknown>;
|
|
28
|
+
}) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Callback type for unsubscribe function
|
|
31
|
+
*/
|
|
32
|
+
type UnsubscribeFn$1 = () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Framework-agnostic reactive logic engine using JavaScript Proxies
|
|
35
|
+
*/
|
|
15
36
|
declare class ReactiveLogicEngine<TContext extends object> {
|
|
16
|
-
|
|
37
|
+
private _state;
|
|
38
|
+
private _subscribers;
|
|
39
|
+
private _contextProxy;
|
|
40
|
+
private _factsProxy;
|
|
41
|
+
private _metaProxy;
|
|
42
|
+
private _batchDepth;
|
|
43
|
+
private _pendingNotification;
|
|
44
|
+
private _proxyCache;
|
|
45
|
+
private static readonly ARRAY_MUTATORS;
|
|
46
|
+
constructor(options: ReactiveEngineOptions<TContext>);
|
|
47
|
+
/**
|
|
48
|
+
* Create a reactive proxy that notifies subscribers on changes.
|
|
49
|
+
* Uses a WeakMap cache to avoid creating multiple proxies for the same object.
|
|
50
|
+
*/
|
|
51
|
+
private _createReactiveProxy;
|
|
52
|
+
/**
|
|
53
|
+
* Notify all subscribers of state changes
|
|
54
|
+
*/
|
|
55
|
+
private _notify;
|
|
56
|
+
/**
|
|
57
|
+
* Get the full state object
|
|
58
|
+
*/
|
|
59
|
+
get state(): {
|
|
17
60
|
context: TContext;
|
|
18
61
|
facts: any[];
|
|
19
62
|
meta: Record<string, unknown>;
|
|
20
63
|
};
|
|
21
|
-
constructor(options: ReactiveEngineOptions<TContext>);
|
|
22
64
|
/**
|
|
23
|
-
* Access the reactive context
|
|
24
|
-
*
|
|
65
|
+
* Access the reactive context.
|
|
66
|
+
* Changes to this object will trigger subscriber notifications.
|
|
25
67
|
*/
|
|
26
68
|
get context(): TContext;
|
|
27
69
|
/**
|
|
28
70
|
* Access the reactive facts list.
|
|
71
|
+
* Changes to this array will trigger subscriber notifications.
|
|
29
72
|
*/
|
|
30
73
|
get facts(): any[];
|
|
74
|
+
/**
|
|
75
|
+
* Access the reactive metadata.
|
|
76
|
+
* Changes to this object will trigger subscriber notifications.
|
|
77
|
+
*/
|
|
78
|
+
get meta(): Record<string, unknown>;
|
|
31
79
|
/**
|
|
32
80
|
* Apply a mutation to the state.
|
|
33
81
|
* This is the "Action" or "Rule" equivalent.
|
|
82
|
+
* Mutations are batched - notifications only happen once per apply call.
|
|
34
83
|
*
|
|
35
84
|
* @param mutator A function that receives the state and modifies it.
|
|
36
85
|
*/
|
|
@@ -40,10 +89,54 @@ declare class ReactiveLogicEngine<TContext extends object> {
|
|
|
40
89
|
meta: Record<string, unknown>;
|
|
41
90
|
}) => void): void;
|
|
42
91
|
/**
|
|
43
|
-
*
|
|
92
|
+
* Subscribe to state changes.
|
|
93
|
+
* Returns an unsubscribe function.
|
|
94
|
+
*
|
|
95
|
+
* @param callback Function to call when state changes
|
|
96
|
+
* @returns Unsubscribe function
|
|
97
|
+
*/
|
|
98
|
+
subscribe(callback: StateChangeCallback<TContext>): UnsubscribeFn$1;
|
|
99
|
+
/**
|
|
100
|
+
* Create a derived/computed value from the state.
|
|
101
|
+
* The selector function will be called whenever the state changes.
|
|
102
|
+
*
|
|
103
|
+
* @param selector Function to extract derived value from state
|
|
104
|
+
* @returns Object with subscribe method for reactive updates
|
|
44
105
|
*/
|
|
45
|
-
|
|
106
|
+
$derived<TDerived>(selector: (state: {
|
|
107
|
+
context: TContext;
|
|
108
|
+
facts: any[];
|
|
109
|
+
meta: Record<string, unknown>;
|
|
110
|
+
}) => TDerived): {
|
|
111
|
+
subscribe: (callback: (value: TDerived) => void) => UnsubscribeFn$1;
|
|
112
|
+
};
|
|
46
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Create a new reactive logic engine instance.
|
|
116
|
+
*
|
|
117
|
+
* @param options Configuration options for the reactive engine
|
|
118
|
+
* @returns A new ReactiveLogicEngine instance
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const engine = createReactiveEngine({
|
|
123
|
+
* initialContext: { count: 0 },
|
|
124
|
+
* initialFacts: [],
|
|
125
|
+
* initialMeta: {}
|
|
126
|
+
* });
|
|
127
|
+
*
|
|
128
|
+
* // Subscribe to changes
|
|
129
|
+
* engine.subscribe((state) => {
|
|
130
|
+
* console.log('State changed:', state);
|
|
131
|
+
* });
|
|
132
|
+
*
|
|
133
|
+
* // Mutate state (will trigger subscribers)
|
|
134
|
+
* engine.apply((state) => {
|
|
135
|
+
* state.context.count++;
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
declare function createReactiveEngine<TContext extends object>(options: ReactiveEngineOptions<TContext>): ReactiveLogicEngine<TContext>;
|
|
47
140
|
|
|
48
141
|
/**
|
|
49
142
|
* Actors System
|
|
@@ -915,6 +1008,73 @@ declare class InMemoryPraxisDB implements PraxisDB {
|
|
|
915
1008
|
* ```
|
|
916
1009
|
*/
|
|
917
1010
|
declare function createInMemoryDB(): InMemoryPraxisDB;
|
|
1011
|
+
/**
|
|
1012
|
+
* PluresDB instance type - represents either PluresNode or SQLiteCompatibleAPI
|
|
1013
|
+
*/
|
|
1014
|
+
type PluresDBInstance = {
|
|
1015
|
+
get(key: string): Promise<any>;
|
|
1016
|
+
put(key: string, value: any): Promise<void>;
|
|
1017
|
+
};
|
|
1018
|
+
/**
|
|
1019
|
+
* Configuration options for PluresDBPraxisAdapter
|
|
1020
|
+
*/
|
|
1021
|
+
interface PluresDBAdapterConfig {
|
|
1022
|
+
/** PluresDB instance */
|
|
1023
|
+
db: PluresDBInstance;
|
|
1024
|
+
/** Polling interval in milliseconds for watch functionality (default: 1000ms) */
|
|
1025
|
+
pollInterval?: number;
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* PluresDB-backed implementation of PraxisDB
|
|
1029
|
+
*
|
|
1030
|
+
* Wraps the official PluresDB package from NPM to provide
|
|
1031
|
+
* the PraxisDB interface for production use.
|
|
1032
|
+
*/
|
|
1033
|
+
declare class PluresDBPraxisAdapter implements PraxisDB {
|
|
1034
|
+
private db;
|
|
1035
|
+
private watchers;
|
|
1036
|
+
private pollIntervals;
|
|
1037
|
+
private lastValues;
|
|
1038
|
+
private pollInterval;
|
|
1039
|
+
constructor(config: PluresDBAdapterConfig | PluresDBInstance);
|
|
1040
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
1041
|
+
set<T>(key: string, value: T): Promise<void>;
|
|
1042
|
+
watch<T>(key: string, callback: (val: T) => void): UnsubscribeFn;
|
|
1043
|
+
/**
|
|
1044
|
+
* Clean up all resources
|
|
1045
|
+
*/
|
|
1046
|
+
dispose(): void;
|
|
1047
|
+
}
|
|
1048
|
+
/**
|
|
1049
|
+
* Create a PluresDB-backed PraxisDB instance
|
|
1050
|
+
*
|
|
1051
|
+
* Wraps the official PluresDB package from NPM.
|
|
1052
|
+
*
|
|
1053
|
+
* @param config PluresDB instance or configuration object
|
|
1054
|
+
* @returns PluresDBPraxisAdapter instance
|
|
1055
|
+
*
|
|
1056
|
+
* @example
|
|
1057
|
+
* ```typescript
|
|
1058
|
+
* import { PluresNode } from 'pluresdb';
|
|
1059
|
+
* import { createPluresDB } from '@plures/praxis';
|
|
1060
|
+
*
|
|
1061
|
+
* const pluresdb = new PluresNode({ autoStart: true });
|
|
1062
|
+
* const db = createPluresDB(pluresdb);
|
|
1063
|
+
*
|
|
1064
|
+
* await db.set('user:1', { name: 'Alice' });
|
|
1065
|
+
* const user = await db.get('user:1');
|
|
1066
|
+
* ```
|
|
1067
|
+
*
|
|
1068
|
+
* @example
|
|
1069
|
+
* ```typescript
|
|
1070
|
+
* // With custom polling interval
|
|
1071
|
+
* const db = createPluresDB({
|
|
1072
|
+
* db: pluresdb,
|
|
1073
|
+
* pollInterval: 500, // Poll every 500ms
|
|
1074
|
+
* });
|
|
1075
|
+
* ```
|
|
1076
|
+
*/
|
|
1077
|
+
declare function createPluresDB(config: PluresDBAdapterConfig | PluresDBInstance): PluresDBPraxisAdapter;
|
|
918
1078
|
|
|
919
1079
|
/**
|
|
920
1080
|
* PraxisDB Store
|
|
@@ -3001,4 +3161,4 @@ declare function attachTauriToEngine<TContext>(engine: LogicEngine<TContext>, ad
|
|
|
3001
3161
|
*/
|
|
3002
3162
|
declare function generateTauriConfig(config: TauriAppConfig): Record<string, unknown>;
|
|
3003
3163
|
|
|
3004
|
-
export { type ActivityState, type Actor, ActorManager, type CanvasDocument, type CanvasEdge, type CanvasEdgeStyle, type CanvasEditorConfig, type CanvasNode, type CanvasNodeStyle, type ComponentDefinition, ConstraintDescriptor, ConstraintFn, type ConstraintNode, type ConstraintSchema, type DefineConstraintOptions, type DefineModuleOptions, type DefineRuleOptions, type EventDefinition$1 as EventDefinition, type EventStreamEntry, type FactDefinition$1 as FactDefinition, type GeneratedDoc, type GeneratedPluresDBFile, type GraphEdge, type GuardianError, type GuardianResult, type GuardianWarning, InMemoryPraxisDB, type LifecycleState, type LoaderOptions, type LoaderResult, type LogicDefinition, LogicEngine, type ModelDefinition, type NodeBindings, type NodeDefinition, type OrchestrationDefinition, PRAXIS_PATHS, type PluresDBAdapter, type PluresDBAdapterOptions, PluresDBGenerator, type PluresDBGeneratorOptions, type PraxisDB, PraxisDBStore, type PraxisDBStoreOptions, PraxisEvent, PraxisFact, PraxisModule, PraxisRegistry, type PraxisSchema, PraxisSchemaRegistry, PraxisState, type
|
|
3164
|
+
export { type ActivityState, type Actor, ActorManager, type CanvasDocument, type CanvasEdge, type CanvasEdgeStyle, type CanvasEditorConfig, type CanvasNode, type CanvasNodeStyle, type ComponentDefinition, ConstraintDescriptor, ConstraintFn, type ConstraintNode, type ConstraintSchema, type DefineConstraintOptions, type DefineModuleOptions, type DefineRuleOptions, type EventDefinition$1 as EventDefinition, type EventStreamEntry, type FactDefinition$1 as FactDefinition, ReactiveLogicEngine as FrameworkAgnosticReactiveEngine, type ReactiveEngineOptions as FrameworkAgnosticReactiveEngineOptions, type GeneratedDoc, type GeneratedPluresDBFile, type GraphEdge, type GuardianError, type GuardianResult, type GuardianWarning, InMemoryPraxisDB, type LifecycleState, type LoaderOptions, type LoaderResult, type LogicDefinition, LogicEngine, type ModelDefinition, type NodeBindings, type NodeDefinition, type OrchestrationDefinition, PRAXIS_PATHS, type PluresDBAdapter, type PluresDBAdapterConfig, type PluresDBAdapterOptions, PluresDBGenerator, type PluresDBGeneratorOptions, type PluresDBInstance, PluresDBPraxisAdapter, type PraxisDB, PraxisDBStore, type PraxisDBStoreOptions, PraxisEvent, PraxisFact, PraxisModule, PraxisRegistry, type PraxisSchema, PraxisSchemaRegistry, PraxisState, type RegistryGraph, RegistryIntrospector, type RegistrySchema, type RegistryStats, RuleDescriptor, RuleFn, type RuleNode, type RuleSchema, type StateChangeCallback, type StateDoc, type StateDocsConfig, StateDocsGenerator, type StateMachineDoc, type StoredSchema, type TauriAppConfig, type TauriBridge, type TauriCommand, type TauriEvent, type TauriFS, type TauriFileEntry, type TauriMenuItem, type TauriNotification, type TauriNotificationOptions, type TauriPlugin, type TauriPraxisAdapter, type TauriSecurityConfig, type TauriTray, type TauriUpdateConfig, type TauriUpdateInfo, type TauriWindowConfig, type TerminalNodeProps, type TransitionDoc, type UnsubscribeFn, type UnumAdapter, type UnumAdapterConfig, type UnumChannel, type UnumIdentity, type UnumMessage, type UnumStore, type ValidationError, type ValidationResult, attachTauriToEngine, attachToEngine, attachUnumToEngine, canvasToMermaid, canvasToSchema, canvasToYaml, createCanvasEditor, createReactiveEngine as createFrameworkAgnosticReactiveEngine, createInMemoryDB, createIntrospector, createMockTauriBridge, createPluresDB, createPluresDBAdapter, createPluresDBGenerator, createPraxisDBStore, createSchema, createSchemaRegistry, createSchemaTemplate, createStateDocsGenerator, createTauriPraxisAdapter, createTimerActor, createUnumAdapter, defineConstraint, defineEvent, defineFact, defineModule, defineRule, filterEvents, filterFacts, findEvent, findFact, generateDocs, generateId, generateTauriConfig, getEventPath, getFactPath, getSchemaPath, loadSchemaFromJson, loadSchemaFromYaml, registerSchema, schemaToCanvas, validateForGeneration, validateSchema, validateWithGuardian };
|