@plures/praxis 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FRAMEWORK.md +106 -15
- package/README.md +275 -53
- 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-VOMLVI6V.js +197 -0
- package/dist/browser/engine-YJZV4SLD.js +8 -0
- package/dist/browser/index.d.ts +300 -11
- package/dist/browser/index.js +334 -325
- package/dist/browser/integrations/svelte.d.ts +3 -1
- package/dist/browser/integrations/svelte.js +8 -0
- package/dist/browser/{engine-BjdqxeXG.d.ts → reactive-engine.svelte-C9OpcTHf.d.ts} +87 -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-VOMLVI6V.js +197 -0
- package/dist/node/cli/index.cjs +1444 -889
- package/dist/node/cli/index.js +9 -0
- package/dist/node/components/index.d.cts +2 -2
- package/dist/node/components/index.d.ts +2 -2
- package/dist/node/docs-JFNYTOJA.js +102 -0
- package/dist/node/engine-2DQBKBJC.js +9 -0
- package/dist/node/index.cjs +747 -234
- package/dist/node/index.d.cts +237 -15
- package/dist/node/index.d.ts +237 -15
- package/dist/node/index.js +339 -767
- 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 +7 -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/cli/commands/docs.ts +147 -0
- package/src/cli/index.ts +21 -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 +93 -19
- package/src/core/reactive-engine.ts +284 -22
- package/src/index.browser.ts +16 -0
- package/src/index.ts +16 -0
- package/src/integrations/pluresdb.ts +2 -2
- package/src/integrations/svelte.ts +8 -0
- package/src/integrations/unified.ts +350 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
// src/integrations/state-docs.ts
|
|
2
|
+
var StateDocsGenerator = class {
|
|
3
|
+
config;
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.config = {
|
|
6
|
+
target: "./docs",
|
|
7
|
+
globs: ["**/*.ts", "**/*.js"],
|
|
8
|
+
visualization: {
|
|
9
|
+
format: "mermaid",
|
|
10
|
+
exportPng: false,
|
|
11
|
+
theme: "default"
|
|
12
|
+
},
|
|
13
|
+
template: {
|
|
14
|
+
toc: true,
|
|
15
|
+
timestamp: true
|
|
16
|
+
},
|
|
17
|
+
...config
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Generate documentation from a Praxis schema
|
|
22
|
+
*/
|
|
23
|
+
generateFromSchema(schema) {
|
|
24
|
+
const docs = [];
|
|
25
|
+
docs.push(this.generateSchemaReadme(schema));
|
|
26
|
+
if (schema.models && schema.models.length > 0) {
|
|
27
|
+
docs.push(this.generateModelsDoc(schema));
|
|
28
|
+
}
|
|
29
|
+
if (schema.components && schema.components.length > 0) {
|
|
30
|
+
docs.push(this.generateComponentsDoc(schema));
|
|
31
|
+
}
|
|
32
|
+
if (schema.logic && schema.logic.length > 0) {
|
|
33
|
+
for (const logic of schema.logic) {
|
|
34
|
+
docs.push(this.generateLogicDoc(logic));
|
|
35
|
+
docs.push(this.generateLogicDiagram(logic));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return docs;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Generate documentation from a Praxis registry
|
|
42
|
+
*/
|
|
43
|
+
generateFromModule(module) {
|
|
44
|
+
const docs = [];
|
|
45
|
+
const rules = module.rules;
|
|
46
|
+
const constraints = module.constraints;
|
|
47
|
+
docs.push(this.generateRulesDoc(rules));
|
|
48
|
+
docs.push(this.generateConstraintsDoc(constraints));
|
|
49
|
+
docs.push(this.generateRegistryDiagram(rules, constraints));
|
|
50
|
+
return docs;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate the main schema README
|
|
54
|
+
*/
|
|
55
|
+
generateSchemaReadme(schema) {
|
|
56
|
+
const lines = [];
|
|
57
|
+
if (this.config.template?.header) {
|
|
58
|
+
lines.push(this.config.template.header);
|
|
59
|
+
lines.push("");
|
|
60
|
+
}
|
|
61
|
+
lines.push(`# ${schema.name || this.config.projectTitle}`);
|
|
62
|
+
lines.push("");
|
|
63
|
+
if (schema.description) {
|
|
64
|
+
lines.push(schema.description);
|
|
65
|
+
lines.push("");
|
|
66
|
+
}
|
|
67
|
+
if (this.config.template?.toc) {
|
|
68
|
+
lines.push("## Table of Contents");
|
|
69
|
+
lines.push("");
|
|
70
|
+
lines.push("- [Overview](#overview)");
|
|
71
|
+
if (schema.models && schema.models.length > 0) {
|
|
72
|
+
lines.push("- [Models](#models)");
|
|
73
|
+
}
|
|
74
|
+
if (schema.components && schema.components.length > 0) {
|
|
75
|
+
lines.push("- [Components](#components)");
|
|
76
|
+
}
|
|
77
|
+
if (schema.logic && schema.logic.length > 0) {
|
|
78
|
+
lines.push("- [Logic](#logic)");
|
|
79
|
+
}
|
|
80
|
+
lines.push("");
|
|
81
|
+
}
|
|
82
|
+
lines.push("## Overview");
|
|
83
|
+
lines.push("");
|
|
84
|
+
lines.push(`**Version:** ${schema.version}`);
|
|
85
|
+
lines.push("");
|
|
86
|
+
lines.push("### Statistics");
|
|
87
|
+
lines.push("");
|
|
88
|
+
lines.push("| Category | Count |");
|
|
89
|
+
lines.push("|----------|-------|");
|
|
90
|
+
lines.push(`| Models | ${schema.models?.length || 0} |`);
|
|
91
|
+
lines.push(`| Components | ${schema.components?.length || 0} |`);
|
|
92
|
+
lines.push(`| Logic Modules | ${schema.logic?.length || 0} |`);
|
|
93
|
+
lines.push("");
|
|
94
|
+
if (schema.models && schema.models.length > 0) {
|
|
95
|
+
lines.push("## Models");
|
|
96
|
+
lines.push("");
|
|
97
|
+
for (const model of schema.models) {
|
|
98
|
+
lines.push(`### ${model.name}`);
|
|
99
|
+
lines.push("");
|
|
100
|
+
if (model.description) {
|
|
101
|
+
lines.push(model.description);
|
|
102
|
+
lines.push("");
|
|
103
|
+
}
|
|
104
|
+
lines.push("**Fields:**");
|
|
105
|
+
lines.push("");
|
|
106
|
+
lines.push("| Name | Type | Required |");
|
|
107
|
+
lines.push("|------|------|----------|");
|
|
108
|
+
for (const field of model.fields) {
|
|
109
|
+
const required = field.optional ? "No" : "Yes";
|
|
110
|
+
lines.push(`| ${field.name} | ${field.type} | ${required} |`);
|
|
111
|
+
}
|
|
112
|
+
lines.push("");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (schema.components && schema.components.length > 0) {
|
|
116
|
+
lines.push("## Components");
|
|
117
|
+
lines.push("");
|
|
118
|
+
for (const component of schema.components) {
|
|
119
|
+
lines.push(`### ${component.name}`);
|
|
120
|
+
lines.push("");
|
|
121
|
+
lines.push(`**Type:** ${component.type}`);
|
|
122
|
+
lines.push("");
|
|
123
|
+
if (component.description) {
|
|
124
|
+
lines.push(component.description);
|
|
125
|
+
lines.push("");
|
|
126
|
+
}
|
|
127
|
+
if (component.model) {
|
|
128
|
+
lines.push(`**Model:** ${component.model}`);
|
|
129
|
+
lines.push("");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (schema.logic && schema.logic.length > 0) {
|
|
134
|
+
lines.push("## Logic");
|
|
135
|
+
lines.push("");
|
|
136
|
+
for (const logic of schema.logic) {
|
|
137
|
+
lines.push(`### ${logic.id}`);
|
|
138
|
+
lines.push("");
|
|
139
|
+
if (logic.description) {
|
|
140
|
+
lines.push(logic.description);
|
|
141
|
+
lines.push("");
|
|
142
|
+
}
|
|
143
|
+
if (logic.events && logic.events.length > 0) {
|
|
144
|
+
lines.push("**Events:**");
|
|
145
|
+
lines.push("");
|
|
146
|
+
for (const event of logic.events) {
|
|
147
|
+
lines.push(`- \`${event.tag}\`: ${event.description || ""}`);
|
|
148
|
+
}
|
|
149
|
+
lines.push("");
|
|
150
|
+
}
|
|
151
|
+
if (logic.facts && logic.facts.length > 0) {
|
|
152
|
+
lines.push("**Facts:**");
|
|
153
|
+
lines.push("");
|
|
154
|
+
for (const fact of logic.facts) {
|
|
155
|
+
lines.push(`- \`${fact.tag}\`: ${fact.description || ""}`);
|
|
156
|
+
}
|
|
157
|
+
lines.push("");
|
|
158
|
+
}
|
|
159
|
+
if (logic.rules && logic.rules.length > 0) {
|
|
160
|
+
lines.push("**Rules:**");
|
|
161
|
+
lines.push("");
|
|
162
|
+
for (const rule of logic.rules) {
|
|
163
|
+
lines.push(`- \`${rule.id}\`: ${rule.description || ""}`);
|
|
164
|
+
}
|
|
165
|
+
lines.push("");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (this.config.template?.timestamp) {
|
|
170
|
+
lines.push("---");
|
|
171
|
+
lines.push("");
|
|
172
|
+
lines.push(`*Generated on ${(/* @__PURE__ */ new Date()).toISOString()} by State-Docs*`);
|
|
173
|
+
}
|
|
174
|
+
if (this.config.template?.footer) {
|
|
175
|
+
lines.push("");
|
|
176
|
+
lines.push(this.config.template.footer);
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
path: `${this.config.target}/README.md`,
|
|
180
|
+
content: lines.join("\n"),
|
|
181
|
+
type: "markdown"
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Generate models documentation
|
|
186
|
+
*/
|
|
187
|
+
generateModelsDoc(schema) {
|
|
188
|
+
const lines = [
|
|
189
|
+
"# Models",
|
|
190
|
+
"",
|
|
191
|
+
"This document describes all data models defined in the schema.",
|
|
192
|
+
""
|
|
193
|
+
];
|
|
194
|
+
if (schema.models) {
|
|
195
|
+
for (const model of schema.models) {
|
|
196
|
+
lines.push(`## ${model.name}`);
|
|
197
|
+
lines.push("");
|
|
198
|
+
if (model.description) {
|
|
199
|
+
lines.push(model.description);
|
|
200
|
+
lines.push("");
|
|
201
|
+
}
|
|
202
|
+
lines.push("### Fields");
|
|
203
|
+
lines.push("");
|
|
204
|
+
lines.push("| Name | Type | Required | Description |");
|
|
205
|
+
lines.push("|------|------|----------|-------------|");
|
|
206
|
+
for (const field of model.fields) {
|
|
207
|
+
const required = field.optional ? "No" : "Yes";
|
|
208
|
+
const description = field.description || "-";
|
|
209
|
+
lines.push(`| ${field.name} | \`${field.type}\` | ${required} | ${description} |`);
|
|
210
|
+
}
|
|
211
|
+
lines.push("");
|
|
212
|
+
if (model.indexes && model.indexes.length > 0) {
|
|
213
|
+
lines.push("### Indexes");
|
|
214
|
+
lines.push("");
|
|
215
|
+
for (const index of model.indexes) {
|
|
216
|
+
lines.push(`- **${index.name}**: \`${index.fields.join(", ")}\``);
|
|
217
|
+
}
|
|
218
|
+
lines.push("");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
path: `${this.config.target}/models.md`,
|
|
224
|
+
content: lines.join("\n"),
|
|
225
|
+
type: "markdown"
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Generate components documentation
|
|
230
|
+
*/
|
|
231
|
+
generateComponentsDoc(schema) {
|
|
232
|
+
const lines = [
|
|
233
|
+
"# Components",
|
|
234
|
+
"",
|
|
235
|
+
"This document describes all UI components defined in the schema.",
|
|
236
|
+
""
|
|
237
|
+
];
|
|
238
|
+
if (schema.components) {
|
|
239
|
+
for (const component of schema.components) {
|
|
240
|
+
lines.push(`## ${component.name}`);
|
|
241
|
+
lines.push("");
|
|
242
|
+
lines.push(`**Type:** ${component.type}`);
|
|
243
|
+
lines.push("");
|
|
244
|
+
if (component.description) {
|
|
245
|
+
lines.push(component.description);
|
|
246
|
+
lines.push("");
|
|
247
|
+
}
|
|
248
|
+
if (component.model) {
|
|
249
|
+
lines.push(
|
|
250
|
+
`**Associated Model:** [${component.model}](./models.md#${component.model.toLowerCase()})`
|
|
251
|
+
);
|
|
252
|
+
lines.push("");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
path: `${this.config.target}/components.md`,
|
|
258
|
+
content: lines.join("\n"),
|
|
259
|
+
type: "markdown"
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Generate logic documentation
|
|
264
|
+
*/
|
|
265
|
+
generateLogicDoc(logic) {
|
|
266
|
+
const lines = [`# ${logic.id}`, ""];
|
|
267
|
+
if (logic.description) {
|
|
268
|
+
lines.push(logic.description);
|
|
269
|
+
lines.push("");
|
|
270
|
+
}
|
|
271
|
+
if (logic.events && logic.events.length > 0) {
|
|
272
|
+
lines.push("## Events");
|
|
273
|
+
lines.push("");
|
|
274
|
+
lines.push("| Event | Description | Payload |");
|
|
275
|
+
lines.push("|-------|-------------|---------|");
|
|
276
|
+
for (const event of logic.events) {
|
|
277
|
+
const payload = event.payload ? Object.entries(event.payload).map(([k, v]) => `${k}: ${v}`).join(", ") : "-";
|
|
278
|
+
lines.push(`| \`${event.tag}\` | ${event.description || "-"} | ${payload} |`);
|
|
279
|
+
}
|
|
280
|
+
lines.push("");
|
|
281
|
+
}
|
|
282
|
+
if (logic.facts && logic.facts.length > 0) {
|
|
283
|
+
lines.push("## Facts");
|
|
284
|
+
lines.push("");
|
|
285
|
+
lines.push("| Fact | Description | Payload |");
|
|
286
|
+
lines.push("|------|-------------|---------|");
|
|
287
|
+
for (const fact of logic.facts) {
|
|
288
|
+
const payload = fact.payload ? Object.entries(fact.payload).map(([k, v]) => `${k}: ${v}`).join(", ") : "-";
|
|
289
|
+
lines.push(`| \`${fact.tag}\` | ${fact.description || "-"} | ${payload} |`);
|
|
290
|
+
}
|
|
291
|
+
lines.push("");
|
|
292
|
+
}
|
|
293
|
+
if (logic.rules && logic.rules.length > 0) {
|
|
294
|
+
lines.push("## Rules");
|
|
295
|
+
lines.push("");
|
|
296
|
+
for (const rule of logic.rules) {
|
|
297
|
+
lines.push(`### ${rule.id}`);
|
|
298
|
+
lines.push("");
|
|
299
|
+
if (rule.description) {
|
|
300
|
+
lines.push(rule.description);
|
|
301
|
+
lines.push("");
|
|
302
|
+
}
|
|
303
|
+
if (rule.priority !== void 0) {
|
|
304
|
+
lines.push(`**Priority:** ${rule.priority}`);
|
|
305
|
+
lines.push("");
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (logic.constraints && logic.constraints.length > 0) {
|
|
310
|
+
lines.push("## Constraints");
|
|
311
|
+
lines.push("");
|
|
312
|
+
for (const constraint of logic.constraints) {
|
|
313
|
+
lines.push(`### ${constraint.id}`);
|
|
314
|
+
lines.push("");
|
|
315
|
+
if (constraint.description) {
|
|
316
|
+
lines.push(constraint.description);
|
|
317
|
+
lines.push("");
|
|
318
|
+
}
|
|
319
|
+
if (constraint.message) {
|
|
320
|
+
lines.push(`**Error Message:** ${constraint.message}`);
|
|
321
|
+
lines.push("");
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
path: `${this.config.target}/logic/${logic.id}.md`,
|
|
327
|
+
content: lines.join("\n"),
|
|
328
|
+
type: "markdown"
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Generate Mermaid diagram for logic
|
|
333
|
+
*/
|
|
334
|
+
generateLogicDiagram(logic) {
|
|
335
|
+
const lines = ["stateDiagram-v2"];
|
|
336
|
+
if (logic.events && logic.facts) {
|
|
337
|
+
lines.push(" [*] --> Processing");
|
|
338
|
+
for (const event of logic.events) {
|
|
339
|
+
lines.push(` Processing --> ${event.tag.replace(/[^a-zA-Z0-9]/g, "")}: ${event.tag}`);
|
|
340
|
+
}
|
|
341
|
+
for (const fact of logic.facts) {
|
|
342
|
+
lines.push(` ${fact.tag.replace(/[^a-zA-Z0-9]/g, "")} --> [*]`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return {
|
|
346
|
+
path: `${this.config.target}/logic/${logic.id}.mmd`,
|
|
347
|
+
content: lines.join("\n"),
|
|
348
|
+
type: "mermaid"
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Generate rules documentation
|
|
353
|
+
*/
|
|
354
|
+
generateRulesDoc(rules) {
|
|
355
|
+
const lines = [
|
|
356
|
+
"# Rules",
|
|
357
|
+
"",
|
|
358
|
+
"This document describes all rules registered in the Praxis engine.",
|
|
359
|
+
""
|
|
360
|
+
];
|
|
361
|
+
for (const rule of rules) {
|
|
362
|
+
lines.push(`## ${rule.id}`);
|
|
363
|
+
lines.push("");
|
|
364
|
+
if (rule.description) {
|
|
365
|
+
lines.push(rule.description);
|
|
366
|
+
lines.push("");
|
|
367
|
+
}
|
|
368
|
+
if (rule.meta?.eventType) {
|
|
369
|
+
lines.push(`**Triggers on:** \`${rule.meta.eventType}\``);
|
|
370
|
+
lines.push("");
|
|
371
|
+
}
|
|
372
|
+
if (rule.meta?.priority !== void 0) {
|
|
373
|
+
lines.push(`**Priority:** ${rule.meta.priority}`);
|
|
374
|
+
lines.push("");
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return {
|
|
378
|
+
path: `${this.config.target}/rules.md`,
|
|
379
|
+
content: lines.join("\n"),
|
|
380
|
+
type: "markdown"
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Generate constraints documentation
|
|
385
|
+
*/
|
|
386
|
+
generateConstraintsDoc(constraints) {
|
|
387
|
+
const lines = [
|
|
388
|
+
"# Constraints",
|
|
389
|
+
"",
|
|
390
|
+
"This document describes all constraints (invariants) registered in the Praxis engine.",
|
|
391
|
+
""
|
|
392
|
+
];
|
|
393
|
+
for (const constraint of constraints) {
|
|
394
|
+
lines.push(`## ${constraint.id}`);
|
|
395
|
+
lines.push("");
|
|
396
|
+
if (constraint.description) {
|
|
397
|
+
lines.push(constraint.description);
|
|
398
|
+
lines.push("");
|
|
399
|
+
}
|
|
400
|
+
if (constraint.meta?.errorMessage) {
|
|
401
|
+
lines.push(`**Error Message:** ${constraint.meta.errorMessage}`);
|
|
402
|
+
lines.push("");
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
path: `${this.config.target}/constraints.md`,
|
|
407
|
+
content: lines.join("\n"),
|
|
408
|
+
type: "markdown"
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Generate state diagram from registry
|
|
413
|
+
*/
|
|
414
|
+
generateRegistryDiagram(rules, constraints) {
|
|
415
|
+
const lines = ["graph TD", " subgraph Rules"];
|
|
416
|
+
for (const rule of rules) {
|
|
417
|
+
const id = rule.id.replace(/[^a-zA-Z0-9]/g, "_");
|
|
418
|
+
lines.push(` ${id}["${rule.id}"]`);
|
|
419
|
+
}
|
|
420
|
+
lines.push(" end");
|
|
421
|
+
lines.push(" subgraph Constraints");
|
|
422
|
+
for (const constraint of constraints) {
|
|
423
|
+
const id = constraint.id.replace(/[^a-zA-Z0-9]/g, "_");
|
|
424
|
+
lines.push(` ${id}["${constraint.id}"]`);
|
|
425
|
+
}
|
|
426
|
+
lines.push(" end");
|
|
427
|
+
return {
|
|
428
|
+
path: `${this.config.target}/state-diagram.mmd`,
|
|
429
|
+
content: lines.join("\n"),
|
|
430
|
+
type: "mermaid"
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
function createStateDocsGenerator(config) {
|
|
435
|
+
return new StateDocsGenerator(config);
|
|
436
|
+
}
|
|
437
|
+
function generateDocs(schema, config) {
|
|
438
|
+
const generator = createStateDocsGenerator(config);
|
|
439
|
+
return generator.generateFromSchema(schema);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export {
|
|
443
|
+
StateDocsGenerator,
|
|
444
|
+
createStateDocsGenerator,
|
|
445
|
+
generateDocs
|
|
446
|
+
};
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// src/core/protocol.ts
|
|
2
|
+
var PRAXIS_PROTOCOL_VERSION = "1.0.0";
|
|
3
|
+
|
|
4
|
+
// src/core/engine.ts
|
|
5
|
+
function safeClone(value) {
|
|
6
|
+
if (value === null || typeof value !== "object") {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
if (typeof globalThis.structuredClone === "function") {
|
|
10
|
+
try {
|
|
11
|
+
return globalThis.structuredClone(value);
|
|
12
|
+
} catch {
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
return [...value];
|
|
17
|
+
}
|
|
18
|
+
return { ...value };
|
|
19
|
+
}
|
|
20
|
+
var LogicEngine = class {
|
|
21
|
+
state;
|
|
22
|
+
registry;
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.registry = options.registry;
|
|
25
|
+
this.state = {
|
|
26
|
+
context: options.initialContext,
|
|
27
|
+
facts: options.initialFacts ?? [],
|
|
28
|
+
meta: options.initialMeta ?? {},
|
|
29
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the current state (immutable copy)
|
|
34
|
+
*/
|
|
35
|
+
getState() {
|
|
36
|
+
return {
|
|
37
|
+
context: safeClone(this.state.context),
|
|
38
|
+
facts: [...this.state.facts],
|
|
39
|
+
meta: this.state.meta ? safeClone(this.state.meta) : void 0,
|
|
40
|
+
protocolVersion: this.state.protocolVersion
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the current context
|
|
45
|
+
*/
|
|
46
|
+
getContext() {
|
|
47
|
+
return safeClone(this.state.context);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get current facts
|
|
51
|
+
*/
|
|
52
|
+
getFacts() {
|
|
53
|
+
return [...this.state.facts];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Process events through the engine.
|
|
57
|
+
* Applies all registered rules and checks all registered constraints.
|
|
58
|
+
*
|
|
59
|
+
* @param events Events to process
|
|
60
|
+
* @returns Result with new state and diagnostics
|
|
61
|
+
*/
|
|
62
|
+
step(events) {
|
|
63
|
+
const config = {
|
|
64
|
+
ruleIds: this.registry.getRuleIds(),
|
|
65
|
+
constraintIds: this.registry.getConstraintIds()
|
|
66
|
+
};
|
|
67
|
+
return this.stepWithConfig(events, config);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Process events with specific rule and constraint configuration.
|
|
71
|
+
*
|
|
72
|
+
* @param events Events to process
|
|
73
|
+
* @param config Step configuration
|
|
74
|
+
* @returns Result with new state and diagnostics
|
|
75
|
+
*/
|
|
76
|
+
stepWithConfig(events, config) {
|
|
77
|
+
const diagnostics = [];
|
|
78
|
+
let newState = { ...this.state };
|
|
79
|
+
const newFacts = [];
|
|
80
|
+
for (const ruleId of config.ruleIds) {
|
|
81
|
+
const rule = this.registry.getRule(ruleId);
|
|
82
|
+
if (!rule) {
|
|
83
|
+
diagnostics.push({
|
|
84
|
+
kind: "rule-error",
|
|
85
|
+
message: `Rule "${ruleId}" not found in registry`,
|
|
86
|
+
data: { ruleId }
|
|
87
|
+
});
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const ruleFacts = rule.impl(newState, events);
|
|
92
|
+
newFacts.push(...ruleFacts);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
diagnostics.push({
|
|
95
|
+
kind: "rule-error",
|
|
96
|
+
message: `Error executing rule "${ruleId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
97
|
+
data: { ruleId, error }
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
newState = {
|
|
102
|
+
...newState,
|
|
103
|
+
facts: [...newState.facts, ...newFacts]
|
|
104
|
+
};
|
|
105
|
+
for (const constraintId of config.constraintIds) {
|
|
106
|
+
const constraint = this.registry.getConstraint(constraintId);
|
|
107
|
+
if (!constraint) {
|
|
108
|
+
diagnostics.push({
|
|
109
|
+
kind: "constraint-violation",
|
|
110
|
+
message: `Constraint "${constraintId}" not found in registry`,
|
|
111
|
+
data: { constraintId }
|
|
112
|
+
});
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const result = constraint.impl(newState);
|
|
117
|
+
if (result === false) {
|
|
118
|
+
diagnostics.push({
|
|
119
|
+
kind: "constraint-violation",
|
|
120
|
+
message: `Constraint "${constraintId}" violated`,
|
|
121
|
+
data: { constraintId, description: constraint.description }
|
|
122
|
+
});
|
|
123
|
+
} else if (typeof result === "string") {
|
|
124
|
+
diagnostics.push({
|
|
125
|
+
kind: "constraint-violation",
|
|
126
|
+
message: result,
|
|
127
|
+
data: { constraintId, description: constraint.description }
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
diagnostics.push({
|
|
132
|
+
kind: "constraint-violation",
|
|
133
|
+
message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
134
|
+
data: { constraintId, error }
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
this.state = newState;
|
|
139
|
+
return {
|
|
140
|
+
state: newState,
|
|
141
|
+
diagnostics
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Update the context directly (for exceptional cases).
|
|
146
|
+
* Generally, context should be updated through rules.
|
|
147
|
+
*
|
|
148
|
+
* @param updater Function that produces new context from old context
|
|
149
|
+
*/
|
|
150
|
+
updateContext(updater) {
|
|
151
|
+
this.state = {
|
|
152
|
+
...this.state,
|
|
153
|
+
context: updater(this.state.context)
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Add facts directly (for exceptional cases).
|
|
158
|
+
* Generally, facts should be added through rules.
|
|
159
|
+
*
|
|
160
|
+
* @param facts Facts to add
|
|
161
|
+
*/
|
|
162
|
+
addFacts(facts) {
|
|
163
|
+
this.state = {
|
|
164
|
+
...this.state,
|
|
165
|
+
facts: [...this.state.facts, ...facts]
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Clear all facts
|
|
170
|
+
*/
|
|
171
|
+
clearFacts() {
|
|
172
|
+
this.state = {
|
|
173
|
+
...this.state,
|
|
174
|
+
facts: []
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Reset the engine to initial state
|
|
179
|
+
*/
|
|
180
|
+
reset(options) {
|
|
181
|
+
this.state = {
|
|
182
|
+
context: options.initialContext,
|
|
183
|
+
facts: options.initialFacts ?? [],
|
|
184
|
+
meta: options.initialMeta ?? {},
|
|
185
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
function createPraxisEngine(options) {
|
|
190
|
+
return new LogicEngine(options);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export {
|
|
194
|
+
PRAXIS_PROTOCOL_VERSION,
|
|
195
|
+
LogicEngine,
|
|
196
|
+
createPraxisEngine
|
|
197
|
+
};
|