@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 CHANGED
@@ -143,28 +143,104 @@ PluresDB provides the data storage and synchronization layer.
143
143
  - Logic engine fact/event storage
144
144
  - Component data binding
145
145
  - Distributed state management
146
+ - CRDT-based synchronization
147
+ - Event sourcing and replay
146
148
 
147
- ### 5. Visual IDE (CodeCanvas Integration)
149
+ **Status**: Fully implemented with comprehensive test coverage
148
150
 
149
- CodeCanvas provides visual development capabilities.
151
+ ### 5. Identity & Channels (Unum Integration)
152
+
153
+ Unum provides identity management and channel-based communication for distributed systems.
150
154
 
151
155
  **Features:**
152
156
 
153
- - Visual schema editor
154
- - Logic flow designer
155
- - Component preview
156
- - Orchestrator visualization
157
- - Documentation navigation
157
+ - Identity creation and management
158
+ - Channel-based messaging
159
+ - Event and fact broadcasting
160
+ - Member management
161
+ - Real-time synchronization with PluresDB
162
+
163
+ **Use Cases:**
164
+
165
+ - Multi-user collaboration
166
+ - Distributed event streaming
167
+ - Node-to-node communication
168
+ - Identity-based access control
169
+ - Real-time state synchronization
170
+
171
+ **Integration Points:**
172
+
173
+ - Praxis event broadcasting to channels
174
+ - Fact synchronization across nodes
175
+ - PluresDB backend for persistence
176
+ - Engine attachment for automatic distribution
177
+
178
+ **Status**: ✅ Fully implemented with comprehensive API
179
+
180
+ ### 6. Documentation (State-Docs Integration)
181
+
182
+ State-Docs generates living documentation from Praxis schemas and logic definitions.
183
+
184
+ **Features:**
185
+
186
+ - Auto-generated Markdown documentation
187
+ - Mermaid and DOT diagram generation
188
+ - Model and component catalogs
189
+ - Logic flow visualization
190
+ - Event → Rule → Fact diagrams
191
+ - Customizable templates
192
+
193
+ **Use Cases:**
194
+
195
+ - API documentation
196
+ - Architecture diagrams
197
+ - Onboarding documentation
198
+ - Design reviews
199
+ - GitHub Pages integration
200
+
201
+ **Integration Points:**
202
+
203
+ - Schema documentation generation
204
+ - Registry introspection
205
+ - Automatic ToC and index generation
206
+ - Diagram export (Mermaid, DOT)
207
+
208
+ **Status**: ✅ Fully implemented with CLI support (`praxis docs`)
209
+
210
+ ### 7. Visual IDE (CodeCanvas Integration)
211
+
212
+ CodeCanvas provides visual development capabilities for schemas and logic flows.
213
+
214
+ **Features:**
215
+
216
+ - Visual schema editor with node-based UI
217
+ - Schema ↔ Canvas bi-directional sync
218
+ - Mermaid and YAML export
219
+ - Obsidian Canvas compatibility
220
+ - FSM visualization
221
+ - Guardian pre-commit validation
222
+ - Activity lifecycle tracking
158
223
 
159
224
  **Use Cases:**
160
225
 
161
226
  - Design schemas visually
162
- - Build logic flows with drag-and-drop
163
- - Preview generated components
164
- - Visualize distributed orchestration
165
- - Navigate living documentation
227
+ - Build logic flows with visual tools
228
+ - Export schemas to diagrams
229
+ - Integrate with Obsidian workflows
230
+ - Visualize state machines
231
+ - Enforce development lifecycle
166
232
 
167
- ### 6. Orchestration (DSC/MCP Support)
233
+ **Integration Points:**
234
+
235
+ - Schema conversion (`schemaToCanvas`)
236
+ - Canvas export (YAML, Mermaid, JSON)
237
+ - Visual editor API
238
+ - FSM lifecycle management
239
+ - Guardian validation hooks
240
+
241
+ **Status**: ✅ Fully implemented with CLI support (`praxis canvas`)
242
+
243
+ ### 8. Orchestration (DSC/MCP Support)
168
244
 
169
245
  Support for distributed system coordination.
170
246
 
@@ -213,17 +289,32 @@ Generate code from schemas.
213
289
 
214
290
  Options:
215
291
 
216
- - `--target`: Generation target (components, models, docs, all)
292
+ - `--target`: Generation target (components, models, pluresdb, docs, all)
217
293
  - `--watch`: Watch for schema changes
294
+ - `--auto-index`: Auto-indexing strategy for PluresDB
295
+
296
+ #### `praxis docs [schema]`
297
+
298
+ Generate documentation from schemas or registries.
299
+
300
+ Options:
301
+
302
+ - `--output`: Output directory (default: ./docs)
303
+ - `--title`: Documentation title
304
+ - `--format`: Diagram format (mermaid, dot)
305
+ - `--no-toc`: Disable table of contents
306
+ - `--from-registry`: Generate from registry instead of schema
218
307
 
219
308
  #### `praxis canvas [schema]`
220
309
 
221
- Open CodeCanvas for visual editing.
310
+ Open CodeCanvas for visual editing or export schemas to canvas formats.
222
311
 
223
312
  Options:
224
313
 
225
- - `--port`: Port for Canvas server
314
+ - `--port`: Port for Canvas server (default: 3000)
226
315
  - `--mode`: Mode (edit, view, present)
316
+ - `--export`: Export format (yaml, mermaid, json)
317
+ - `--output`: Output file for export
227
318
 
228
319
  #### `praxis orchestrate`
229
320
 
package/README.md CHANGED
@@ -10,7 +10,16 @@ dotnet test
10
10
  [![Node.js Version](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org/)
11
11
  [![Deno Compatible](https://img.shields.io/badge/deno-compatible-brightgreen)](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. The library delivers a unified ESM/CJS build, curated subpath exports, Svelte runes support, and a slimmer, publish-ready package for npm and JSR.
13
+ Praxis is **the unified solution for declarative application development**, combining:
14
+
15
+ - **Logic Modeling**: Typed facts, events, rules, and constraints for domain logic
16
+ - **Component Auto-Generation**: Svelte 5 components generated from schemas
17
+ - **Data Persistence**: PluresDB for local-first, reactive data storage
18
+ - **Documentation**: Auto-generated docs with State-Docs and visual diagrams
19
+ - **Visual Editing**: CodeCanvas for schema design and FSM visualization
20
+ - **Distributed Systems**: Unum for identity and multi-node communication
21
+
22
+ 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
23
 
15
24
  ---
16
25
 
@@ -26,9 +35,12 @@ Praxis is a schema-driven, rule-based engine with first-class Svelte 5 integrati
26
35
  - **Logic Engine**: Facts, events, rules, constraints, registry, introspection, and reactive engine variants (Svelte 5 + framework-agnostic).
27
36
  - **Schema & Codegen**: PSF-style schema types plus component generator for Svelte UIs.
28
37
  - **Svelte Integration**: Typed helpers, runes-ready builds, and Svelte component typings.
29
- - **Local-First Data**: PluresDB integrations for offline-first, reactive state.
38
+ - **Local-First Data**: PluresDB integration for offline-first, reactive state with full persistence.
39
+ - **Distributed Systems**: Unum integration for identity management and multi-node channels.
40
+ - **Documentation**: State-Docs integration for auto-generated Markdown docs and Mermaid diagrams.
41
+ - **Visual Editing**: CodeCanvas integration for visual schema design and FSM visualization.
30
42
  - **Cloud Relay**: Optional sync layer (GitHub-auth friendly) for distributed teams.
31
- - **CLI**: Scaffolding, generation, canvas helpers, and cloud commands.
43
+ - **CLI**: Scaffolding, generation, canvas helpers, docs generation, and cloud commands.
32
44
 
33
45
  ## Install
34
46
  Node 18+ recommended.
@@ -81,6 +93,64 @@ const engine = createPraxisEngine({ initialContext: { currentUser: null }, regis
81
93
  engine.step([Login.create({ username: 'alex' })]);
82
94
  ```
83
95
 
96
+ ## Unified workflow example
97
+
98
+ See all Praxis integrations working together - from schema definition to persistence, documentation, and distributed communication:
99
+
100
+ ```ts
101
+ import {
102
+ createPraxisEngine,
103
+ PraxisRegistry,
104
+ defineRule,
105
+ createInMemoryDB,
106
+ createPluresDBAdapter,
107
+ createUnumAdapter,
108
+ createStateDocsGenerator,
109
+ schemaToCanvas,
110
+ } from '@plures/praxis';
111
+
112
+ // 1. Define logic with Praxis engine
113
+ const registry = new PraxisRegistry();
114
+ registry.registerRule(/* your rules */);
115
+ const engine = createPraxisEngine({ initialContext: {}, registry });
116
+
117
+ // 2. Add PluresDB for local-first persistence
118
+ const db = createInMemoryDB();
119
+ const pluresAdapter = createPluresDBAdapter({ db, registry });
120
+ pluresAdapter.attachEngine(engine);
121
+
122
+ // 3. Add Unum for distributed communication
123
+ const unum = await createUnumAdapter({
124
+ db,
125
+ identity: { name: 'node-1' },
126
+ realtime: true,
127
+ });
128
+ const channel = await unum.createChannel('app-sync');
129
+
130
+ // Subscribe to distribute events across nodes
131
+ unum.subscribeToEvents(channel.id, (event) => {
132
+ engine.step([event]);
133
+ });
134
+
135
+ // 4. Generate documentation with State-Docs
136
+ const docsGenerator = createStateDocsGenerator({
137
+ projectTitle: 'My App',
138
+ target: './docs',
139
+ });
140
+ const docs = docsGenerator.generateFromModule(registry.module);
141
+
142
+ // 5. Export schema to CodeCanvas for visual editing
143
+ const canvas = schemaToCanvas(mySchema);
144
+ // Canvas can be edited visually and converted back to schema
145
+
146
+ // Now you have:
147
+ // ✅ Logic engine running
148
+ // ✅ Auto-persisting to PluresDB
149
+ // ✅ Distributing events across nodes via Unum
150
+ // ✅ Auto-generated documentation
151
+ // ✅ Visual schema representation
152
+ ```
153
+
84
154
  ## Svelte integration (runes-ready)
85
155
  ```svelte
86
156
  <script lang="ts">
@@ -652,32 +722,55 @@ adapter.subscribeToEvents((events) => {
652
722
 
653
723
  ### Unum Integration
654
724
 
655
- Identity and channels for distributed systems.
725
+ Identity and channels for distributed systems. **Now fully implemented** with comprehensive channel and identity management.
656
726
 
657
727
  ```typescript
658
- import { createUnumIdentity, createChannel } from '@plures/unum';
728
+ import {
729
+ createUnumAdapter,
730
+ attachUnumToEngine,
731
+ } from '@plures/praxis';
659
732
 
660
- // Create identity
661
- const identity = await createUnumIdentity({
662
- name: 'my-app-node',
663
- keys: await generateKeys(),
733
+ // Create Unum adapter with identity
734
+ const unum = await createUnumAdapter({
735
+ db: pluresDB,
736
+ identity: {
737
+ name: 'my-app-node',
738
+ metadata: { role: 'coordinator' },
739
+ },
740
+ realtime: true,
664
741
  });
665
742
 
666
- // Create channel for messaging
667
- const channel = await createChannel({
668
- name: 'app-events',
669
- participants: [identity.id],
743
+ // Create a channel for messaging
744
+ const channel = await unum.createChannel('app-events', ['member-1', 'member-2']);
745
+
746
+ // Broadcast Praxis events to channel
747
+ await unum.broadcastEvent(channel.id, {
748
+ tag: 'USER_JOINED',
749
+ payload: { userId: 'alice' },
670
750
  });
671
751
 
672
- // Integrate with Praxis actors
673
- const unumActor = createActor('unum-bridge', identity, async (event) => {
674
- // Bridge Praxis events to Unum channels
675
- await channel.publish(event);
752
+ // Subscribe to events from channel
753
+ const unsubscribe = unum.subscribeToEvents(channel.id, (event) => {
754
+ console.log('Received event:', event);
755
+ // Feed into local Praxis engine
756
+ engine.step([event]);
676
757
  });
758
+
759
+ // Attach to engine for automatic event broadcasting
760
+ attachUnumToEngine(engine, unum, channel.id);
677
761
  ```
678
762
 
679
- **Status**: Planned
680
- **Use Cases**: Distributed messaging, identity management, authentication
763
+ **Features:**
764
+
765
+ - **Identity Management**: Create and manage user/node identities
766
+ - **Channel Communication**: Real-time messaging between distributed nodes
767
+ - **Event Broadcasting**: Share Praxis events across channels
768
+ - **Fact Synchronization**: Distribute facts to connected participants
769
+ - **PluresDB Integration**: Persists identities and messages
770
+
771
+ **Status**: ✅ Available (`src/integrations/unum.ts`)
772
+ **Tests**: Comprehensive integration tests
773
+ **Use Cases**: Distributed messaging, identity management, multi-user collaboration
681
774
 
682
775
  ### ADP Integration
683
776
 
@@ -712,48 +805,116 @@ adp.enforce({
712
805
 
713
806
  ### State-Docs Integration
714
807
 
715
- Living documentation generated from Praxis schemas.
808
+ Living documentation generated from Praxis schemas. **Now fully implemented** with Markdown and Mermaid diagram generation.
716
809
 
717
810
  ```typescript
718
- import { generateStateDocs } from '@plures/state-docs';
719
-
720
- // Generate documentation from schema
721
- const docs = await generateStateDocs({
722
- schema: appSchema,
723
- logic: logicDefinitions,
724
- components: componentDefinitions,
725
- output: './docs',
726
- format: 'markdown', // or 'html', 'pdf'
811
+ import {
812
+ createStateDocsGenerator,
813
+ generateDocs,
814
+ } from '@plures/praxis';
815
+
816
+ // Create generator
817
+ const generator = createStateDocsGenerator({
818
+ projectTitle: 'My Praxis App',
819
+ target: './docs',
820
+ visualization: {
821
+ format: 'mermaid',
822
+ theme: 'default',
823
+ },
824
+ template: {
825
+ toc: true,
826
+ timestamp: true,
827
+ },
727
828
  });
728
829
 
729
- // Documentation includes:
730
- // - Data model diagrams
731
- // - Logic flow diagrams
732
- // - Component catalog
733
- // - API reference
734
- // - Usage examples
830
+ // Generate docs from schema
831
+ const docs = generator.generateFromSchema(appSchema);
832
+
833
+ // Or from registry
834
+ const registryDocs = generator.generateFromModule(myModule);
835
+
836
+ // Write generated docs
837
+ for (const doc of docs) {
838
+ await writeFile(doc.path, doc.content);
839
+ }
840
+
841
+ // Quick helper
842
+ const allDocs = generateDocs(appSchema, {
843
+ projectTitle: 'My App',
844
+ target: './docs',
845
+ });
735
846
  ```
736
847
 
737
- **Status**: Planned
738
- **Documentation**: See examples for State-Docs integration patterns
848
+ **Features:**
849
+
850
+ - **Schema Documentation**: Auto-generate docs from Praxis schemas
851
+ - **Mermaid Diagrams**: Visual state machine and flow diagrams
852
+ - **Markdown Output**: GitHub-ready documentation
853
+ - **Model & Component Docs**: Detailed API documentation
854
+ - **Logic Flow Visualization**: Event → Rule → Fact diagrams
855
+ - **Table of Contents**: Automatic ToC generation
856
+
857
+ **Status**: ✅ Available (`src/integrations/state-docs.ts`)
858
+ **CLI**: Use `praxis generate` with `--docs` flag (coming soon)
859
+ **Documentation**: Auto-generates README, models.md, logic diagrams
739
860
 
740
861
  ### CodeCanvas Integration
741
862
 
742
- Visual IDE for schema and logic editing.
863
+ Visual IDE for schema and logic editing. **Now fully implemented** with schema visualization and canvas export.
743
864
 
744
- ```bash
745
- # Open Canvas for visual editing
746
- praxis canvas src/schemas/app.schema.ts
865
+ ```typescript
866
+ import {
867
+ schemaToCanvas,
868
+ canvasToSchema,
869
+ canvasToMermaid,
870
+ createCanvasEditor,
871
+ } from '@plures/praxis';
872
+
873
+ // Convert schema to canvas document
874
+ const canvas = schemaToCanvas(mySchema, {
875
+ layout: 'hierarchical',
876
+ });
877
+
878
+ // Export to YAML (Obsidian Canvas compatible)
879
+ const yaml = canvasToYaml(canvas);
880
+ await writeFile('./schema.canvas.yaml', yaml);
881
+
882
+ // Export to Mermaid diagram
883
+ const mermaid = canvasToMermaid(canvas);
747
884
 
748
- # Features:
749
- # - Visual schema design
750
- # - Logic flow editor
751
- # - Component preview
752
- # - Real-time collaboration
753
- # - Export to code
885
+ // Create canvas editor instance
886
+ const editor = createCanvasEditor({
887
+ schema: mySchema,
888
+ enableFSM: true,
889
+ layout: 'hierarchical',
890
+ });
891
+
892
+ // Add nodes programmatically
893
+ editor.addNode({
894
+ type: 'model',
895
+ label: 'User',
896
+ x: 100,
897
+ y: 100,
898
+ width: 150,
899
+ height: 60,
900
+ data: userModel,
901
+ });
902
+
903
+ // Convert back to schema
904
+ const updatedSchema = editor.toSchema();
754
905
  ```
755
906
 
756
- **Status**: Planned
907
+ **Features:**
908
+
909
+ - **Visual Schema Design**: Node-based schema editor
910
+ - **Canvas Export**: YAML and Mermaid diagram formats
911
+ - **Obsidian Compatible**: Works with Obsidian Canvas format
912
+ - **FSM Visualization**: State machine and flow diagrams
913
+ - **Bi-directional Sync**: Canvas ↔ Schema round-tripping
914
+ - **Guardian Validation**: Pre-commit lifecycle checks
915
+
916
+ **Status**: ✅ Available (`src/integrations/code-canvas.ts`)
917
+ **CLI**: Use `praxis canvas` commands (coming soon)
757
918
  **Documentation**: [docs/guides/canvas.md](./docs/guides/canvas.md)
758
919
 
759
920
  ### Svelte + Tauri Runtime
@@ -0,0 +1,12 @@
1
+ import {
2
+ InMemoryPraxisDB,
3
+ PluresDBPraxisAdapter,
4
+ createInMemoryDB,
5
+ createPluresDB
6
+ } from "./chunk-JQ64KMLN.js";
7
+ export {
8
+ InMemoryPraxisDB,
9
+ PluresDBPraxisAdapter,
10
+ createInMemoryDB,
11
+ createPluresDB
12
+ };
@@ -0,0 +1,141 @@
1
+ // src/core/pluresdb/adapter.ts
2
+ var InMemoryPraxisDB = class {
3
+ store = /* @__PURE__ */ new Map();
4
+ watchers = /* @__PURE__ */ new Map();
5
+ async get(key) {
6
+ return this.store.get(key);
7
+ }
8
+ async set(key, value) {
9
+ this.store.set(key, value);
10
+ const keyWatchers = this.watchers.get(key);
11
+ if (keyWatchers) {
12
+ for (const callback of keyWatchers) {
13
+ callback(value);
14
+ }
15
+ }
16
+ }
17
+ watch(key, callback) {
18
+ if (!this.watchers.has(key)) {
19
+ this.watchers.set(key, /* @__PURE__ */ new Set());
20
+ }
21
+ const watchers = this.watchers.get(key);
22
+ const wrappedCallback = (val) => callback(val);
23
+ watchers.add(wrappedCallback);
24
+ return () => {
25
+ watchers.delete(wrappedCallback);
26
+ if (watchers.size === 0) {
27
+ this.watchers.delete(key);
28
+ }
29
+ };
30
+ }
31
+ /**
32
+ * Get all keys (for testing/debugging)
33
+ */
34
+ keys() {
35
+ return Array.from(this.store.keys());
36
+ }
37
+ /**
38
+ * Clear all data (for testing)
39
+ */
40
+ clear() {
41
+ this.store.clear();
42
+ this.watchers.clear();
43
+ }
44
+ };
45
+ function createInMemoryDB() {
46
+ return new InMemoryPraxisDB();
47
+ }
48
+ var PluresDBPraxisAdapter = class {
49
+ db;
50
+ watchers = /* @__PURE__ */ new Map();
51
+ pollIntervals = /* @__PURE__ */ new Map();
52
+ lastValues = /* @__PURE__ */ new Map();
53
+ pollInterval;
54
+ constructor(config) {
55
+ if ("get" in config && "put" in config) {
56
+ this.db = config;
57
+ this.pollInterval = 1e3;
58
+ } else {
59
+ this.db = config.db;
60
+ this.pollInterval = config.pollInterval ?? 1e3;
61
+ }
62
+ }
63
+ async get(key) {
64
+ try {
65
+ const value = await this.db.get(key);
66
+ return value;
67
+ } catch (error) {
68
+ return void 0;
69
+ }
70
+ }
71
+ async set(key, value) {
72
+ await this.db.put(key, value);
73
+ this.lastValues.set(key, value);
74
+ const keyWatchers = this.watchers.get(key);
75
+ if (keyWatchers) {
76
+ for (const callback of keyWatchers) {
77
+ callback(value);
78
+ }
79
+ }
80
+ }
81
+ watch(key, callback) {
82
+ if (!this.watchers.has(key)) {
83
+ this.watchers.set(key, /* @__PURE__ */ new Set());
84
+ }
85
+ const watchers = this.watchers.get(key);
86
+ const wrappedCallback = (val) => callback(val);
87
+ watchers.add(wrappedCallback);
88
+ if (!this.pollIntervals.has(key)) {
89
+ const interval = setInterval(async () => {
90
+ try {
91
+ const value = await this.db.get(key);
92
+ const lastValue = this.lastValues.get(key);
93
+ if (JSON.stringify(value) !== JSON.stringify(lastValue)) {
94
+ this.lastValues.set(key, value);
95
+ const currentWatchers = this.watchers.get(key);
96
+ if (currentWatchers) {
97
+ for (const cb of currentWatchers) {
98
+ cb(value);
99
+ }
100
+ }
101
+ }
102
+ } catch (error) {
103
+ }
104
+ }, this.pollInterval);
105
+ this.pollIntervals.set(key, interval);
106
+ }
107
+ return () => {
108
+ watchers.delete(wrappedCallback);
109
+ if (watchers.size === 0) {
110
+ this.watchers.delete(key);
111
+ const interval = this.pollIntervals.get(key);
112
+ if (interval) {
113
+ clearInterval(interval);
114
+ this.pollIntervals.delete(key);
115
+ }
116
+ this.lastValues.delete(key);
117
+ }
118
+ };
119
+ }
120
+ /**
121
+ * Clean up all resources
122
+ */
123
+ dispose() {
124
+ for (const interval of this.pollIntervals.values()) {
125
+ clearInterval(interval);
126
+ }
127
+ this.pollIntervals.clear();
128
+ this.watchers.clear();
129
+ this.lastValues.clear();
130
+ }
131
+ };
132
+ function createPluresDB(config) {
133
+ return new PluresDBPraxisAdapter(config);
134
+ }
135
+
136
+ export {
137
+ InMemoryPraxisDB,
138
+ createInMemoryDB,
139
+ PluresDBPraxisAdapter,
140
+ createPluresDB
141
+ };