@plures/praxis 1.0.1 → 1.0.2
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 +36 -432
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
| Category | Status |
|
|
28
28
|
|----------|--------|
|
|
29
29
|
| **CI/CD** | ✅ Automated testing & builds |
|
|
30
|
-
| **Version** |
|
|
30
|
+
| **Version** | 1.0.2 (Stable) |
|
|
31
31
|
| **Runtime Support** | Node.js 18+, Deno (experimental), .NET 8+ |
|
|
32
|
-
| **Package Registries** | npm ✅ / NuGet
|
|
33
|
-
| **Test Coverage** |
|
|
32
|
+
| **Package Registries** | npm ✅ / NuGet ✅ / JSR ✅ |
|
|
33
|
+
| **Test Coverage** | 327 TypeScript + 95 C# tests passing |
|
|
34
34
|
| **Documentation** | 📚 Comprehensive guides available |
|
|
35
35
|
|
|
36
36
|
### Language Support
|
|
@@ -191,7 +191,7 @@ Praxis provides these integrated capabilities:
|
|
|
191
191
|
- **Svelte 5**: Full runes support with history and time-travel
|
|
192
192
|
- **Tauri**: Cross-platform runtime (web/desktop/mobile)
|
|
193
193
|
|
|
194
|
-
### ⚡ Svelte 5 Integration
|
|
194
|
+
### ⚡ Svelte 5 Integration
|
|
195
195
|
- **Runes API**: Modern `$state`, `$derived`, `$effect` support
|
|
196
196
|
- **History States**: Built-in undo/redo and time-travel debugging
|
|
197
197
|
- **Store API**: Backward-compatible stores for Svelte 4/5
|
|
@@ -208,83 +208,10 @@ Praxis provides these integrated capabilities:
|
|
|
208
208
|
- 📦 **JSON-Friendly**: All types are serializable for cross-platform use
|
|
209
209
|
- 🔒 **Type-Safe**: Full TypeScript support with strict typing
|
|
210
210
|
- 🔍 **Introspection**: Generate schemas, graphs, and visualizations of your logic
|
|
211
|
-
- 🌐 **Cross-Language**: PowerShell
|
|
212
|
-
- 📊 **Comprehensive Testing**:
|
|
211
|
+
- 🌐 **Cross-Language**: C#, PowerShell, and TypeScript implementations with protocol versioning
|
|
212
|
+
- 📊 **Comprehensive Testing**: 327 TypeScript and 95 C# tests covering all features
|
|
213
213
|
- 🎭 **Hero Example**: Full e-commerce demo with auth, cart, features, and actors
|
|
214
214
|
|
|
215
|
-
## What's New in v0.2.0
|
|
216
|
-
|
|
217
|
-
### 🎉 Major Features
|
|
218
|
-
|
|
219
|
-
#### Full Application Framework
|
|
220
|
-
Praxis 0.2.0 transforms from a logic engine into a **complete application framework**:
|
|
221
|
-
- **Complete Schema System**: Comprehensive type definitions for models, components, logic, and orchestration
|
|
222
|
-
- **Component Generation**: Automatic Svelte component generation from schemas
|
|
223
|
-
- **CLI Tools**: `praxis create`, `praxis generate`, `praxis canvas` commands
|
|
224
|
-
- **Cloud Integration**: GitHub-based authentication and tier-based billing
|
|
225
|
-
- **PluresDB Integration**: Local-first reactive datastore with full implementation
|
|
226
|
-
|
|
227
|
-
#### Svelte 5 Integration (@plures/praxis/svelte)
|
|
228
|
-
- **Runes Composables**: `usePraxisState`, `usePraxisHistory`, `usePraxisComputed`
|
|
229
|
-
- **History State Pattern**: Time-travel debugging with undo/redo
|
|
230
|
-
- **Store API**: Compatible with Svelte 4 and 5
|
|
231
|
-
- **Full TypeScript support** with generics
|
|
232
|
-
|
|
233
|
-
#### Documentation & Guides
|
|
234
|
-
- **[Svelte Integration Guide](docs/guides/svelte-integration.md)**: Complete guide to Svelte 5 integration
|
|
235
|
-
- **[History State Pattern](docs/guides/history-state-pattern.md)**: Undo/redo and time-travel patterns
|
|
236
|
-
- **[Parallel State Pattern](docs/guides/parallel-state-pattern.md)**: Multiple engine coordination
|
|
237
|
-
- **[Advanced Todo Example](src/examples/advanced-todo/)**: Full-featured demo with history
|
|
238
|
-
|
|
239
|
-
### 🧪 Hardened TypeScript Core
|
|
240
|
-
- **197 comprehensive tests** (up from 9 in v0.1.0) covering:
|
|
241
|
-
- Svelte integration with runes and stores
|
|
242
|
-
- PluresDB integration (32 tests)
|
|
243
|
-
- History state management and navigation
|
|
244
|
-
- Edge cases and failure paths
|
|
245
|
-
- Actor lifecycle and state change notifications
|
|
246
|
-
- Constraint violations and rule errors
|
|
247
|
-
- Registry operations and module composition
|
|
248
|
-
- Cloud integration and billing
|
|
249
|
-
- Terminal node functionality
|
|
250
|
-
- Full test coverage ensures production-ready reliability
|
|
251
|
-
|
|
252
|
-
### 🔒 C# Implementation
|
|
253
|
-
- **95 comprehensive C# tests** with full parity to TypeScript features
|
|
254
|
-
- Functional, immutable design with records
|
|
255
|
-
- NuGet package available
|
|
256
|
-
|
|
257
|
-
### 📖 Protocol Versioning
|
|
258
|
-
- **Explicit protocol version** (`protocolVersion` field in state)
|
|
259
|
-
- **Stability guarantees** for cross-language compatibility
|
|
260
|
-
- **Semantic versioning** with migration paths
|
|
261
|
-
- See [PROTOCOL_VERSIONING.md](./PROTOCOL_VERSIONING.md) for details
|
|
262
|
-
|
|
263
|
-
### 🔍 Visualization & Introspection
|
|
264
|
-
- **Registry introspection API** for examining rules and constraints
|
|
265
|
-
- **Graph export** in DOT (Graphviz) and Mermaid formats
|
|
266
|
-
- **JSON schema generation** for documentation and tooling
|
|
267
|
-
- **Search and query** capabilities for rules and constraints
|
|
268
|
-
- **Dependency tracking** and relationship visualization
|
|
269
|
-
|
|
270
|
-
### 💻 PowerShell Adapter
|
|
271
|
-
- **Full PowerShell module** (`Praxis.psm1`) for cross-language usage
|
|
272
|
-
- **CLI boundary** via JSON stdin/stdout
|
|
273
|
-
- **Protocol version checking** ensures compatibility
|
|
274
|
-
- **Complete example** with counter application
|
|
275
|
-
- See [powershell/README.md](./powershell/README.md) for usage
|
|
276
|
-
|
|
277
|
-
### 🎭 Hero Example: E-Commerce Platform
|
|
278
|
-
A comprehensive example demonstrating all Praxis features:
|
|
279
|
-
- **Authentication** with session management and timeouts
|
|
280
|
-
- **Shopping cart** with item management and calculations
|
|
281
|
-
- **Feature flags** for A/B testing (free shipping, loyalty program)
|
|
282
|
-
- **Discount rules** with conditional logic
|
|
283
|
-
- **Loyalty points** and order history
|
|
284
|
-
- **Actors** for logging and analytics
|
|
285
|
-
- **Constraints** enforcing business rules
|
|
286
|
-
- See [src/examples/hero-ecommerce/](./src/examples/hero-ecommerce/) for code
|
|
287
|
-
|
|
288
215
|
## Installation
|
|
289
216
|
|
|
290
217
|
### npm (Node.js)
|
|
@@ -389,7 +316,7 @@ Available CLI commands:
|
|
|
389
316
|
|
|
390
317
|
See [docs/guides/getting-started.md](./docs/guides/getting-started.md) for detailed instructions.
|
|
391
318
|
|
|
392
|
-
### Praxis Cloud
|
|
319
|
+
### Praxis Cloud
|
|
393
320
|
|
|
394
321
|
Connect your application to Praxis Cloud for automatic synchronization with GitHub-native authentication and billing:
|
|
395
322
|
|
|
@@ -486,7 +413,7 @@ const maxSessionsConstraint = defineConstraint<AuthContext>({
|
|
|
486
413
|
registry.registerConstraint(maxSessionsConstraint);
|
|
487
414
|
```
|
|
488
415
|
|
|
489
|
-
### Svelte 5 Integration
|
|
416
|
+
### Svelte 5 Integration
|
|
490
417
|
|
|
491
418
|
#### Store API (Svelte 4/5 Compatible)
|
|
492
419
|
|
|
@@ -656,10 +583,10 @@ See [FRAMEWORK.md](./FRAMEWORK.md) for complete architecture documentation.
|
|
|
656
583
|
|
|
657
584
|
## Examples
|
|
658
585
|
|
|
659
|
-
The repository includes
|
|
586
|
+
The repository includes multiple complete examples:
|
|
660
587
|
|
|
661
588
|
### 1. Hero E-Commerce (`src/examples/hero-ecommerce`)
|
|
662
|
-
|
|
589
|
+
Comprehensive example demonstrating all Praxis features in a single application:
|
|
663
590
|
- Authentication with session management
|
|
664
591
|
- Shopping cart with discount rules
|
|
665
592
|
- Feature flags for A/B testing
|
|
@@ -673,7 +600,7 @@ node dist/examples/hero-ecommerce/index.js
|
|
|
673
600
|
```
|
|
674
601
|
|
|
675
602
|
### 2. Offline-First Chat (`examples/offline-chat`)
|
|
676
|
-
|
|
603
|
+
Demonstrates local-first architecture with PluresDB:
|
|
677
604
|
- Offline message composition and storage
|
|
678
605
|
- Automatic sync when connected
|
|
679
606
|
- Message queue for offline messages
|
|
@@ -683,7 +610,7 @@ node dist/examples/hero-ecommerce/index.js
|
|
|
683
610
|
See [examples/offline-chat/README.md](./examples/offline-chat/README.md)
|
|
684
611
|
|
|
685
612
|
### 3. Knowledge Canvas (`examples/knowledge-canvas`)
|
|
686
|
-
|
|
613
|
+
Showcases CodeCanvas integration for visual knowledge management:
|
|
687
614
|
- Visual knowledge graph editing
|
|
688
615
|
- Schema-driven content types
|
|
689
616
|
- Generated UI components
|
|
@@ -693,7 +620,7 @@ See [examples/offline-chat/README.md](./examples/offline-chat/README.md)
|
|
|
693
620
|
See [examples/knowledge-canvas/README.md](./examples/knowledge-canvas/README.md)
|
|
694
621
|
|
|
695
622
|
### 4. Self-Orchestrating Node (`examples/distributed-node`)
|
|
696
|
-
|
|
623
|
+
Demonstrates distributed orchestration with DSC/MCP:
|
|
697
624
|
- Automatic node discovery
|
|
698
625
|
- Self-healing behavior
|
|
699
626
|
- State synchronization across nodes
|
|
@@ -703,7 +630,7 @@ See [examples/knowledge-canvas/README.md](./examples/knowledge-canvas/README.md)
|
|
|
703
630
|
See [examples/distributed-node/README.md](./examples/distributed-node/README.md)
|
|
704
631
|
|
|
705
632
|
### 5. Terminal Node (`examples/terminal-node`)
|
|
706
|
-
|
|
633
|
+
Demonstrates the terminal node feature for command execution:
|
|
707
634
|
- Terminal adapter creation and configuration
|
|
708
635
|
- Command execution and history tracking
|
|
709
636
|
- YAML schema loading with terminal nodes
|
|
@@ -788,7 +715,7 @@ See [examples/cloud-sync/README.md](./examples/cloud-sync/README.md)
|
|
|
788
715
|
|
|
789
716
|
### Introspection & Visualization
|
|
790
717
|
|
|
791
|
-
|
|
718
|
+
Tools for examining and visualizing your Praxis logic:
|
|
792
719
|
|
|
793
720
|
```typescript
|
|
794
721
|
import { createIntrospector, PRAXIS_PROTOCOL_VERSION } from "@plures/praxis";
|
|
@@ -1012,7 +939,7 @@ npm run tauri:build // Production
|
|
|
1012
939
|
|
|
1013
940
|
### PowerShell
|
|
1014
941
|
|
|
1015
|
-
|
|
942
|
+
Full PowerShell adapter for using Praxis from PowerShell scripts:
|
|
1016
943
|
|
|
1017
944
|
```powershell
|
|
1018
945
|
# Import module
|
|
@@ -1036,7 +963,7 @@ See [powershell/README.md](./powershell/README.md) for complete documentation an
|
|
|
1036
963
|
|
|
1037
964
|
### C# (.NET 8+)
|
|
1038
965
|
|
|
1039
|
-
|
|
966
|
+
Full C# implementation with functional, immutable design:
|
|
1040
967
|
|
|
1041
968
|
```csharp
|
|
1042
969
|
using Praxis.Core;
|
|
@@ -1081,22 +1008,14 @@ Console.WriteLine($"Facts: {result.State.Facts.Count}"); // Facts: 1
|
|
|
1081
1008
|
|
|
1082
1009
|
See [csharp/Praxis/README.md](./csharp/Praxis/README.md) for complete documentation.
|
|
1083
1010
|
|
|
1084
|
-
##
|
|
1011
|
+
## Roadmap
|
|
1085
1012
|
|
|
1086
|
-
###
|
|
1087
|
-
- ✅ Complete CLI implementation
|
|
1088
|
-
- ✅ Basic project templates
|
|
1089
|
-
- ✅ Component generation MVP
|
|
1090
|
-
- ✅ C# implementation with NuGet publishing (95 tests)
|
|
1091
|
-
- ✅ PluresDB integration with full test coverage (32 tests)
|
|
1092
|
-
- ✅ Praxis Cloud with GitHub authentication and billing
|
|
1093
|
-
|
|
1094
|
-
### Medium Term (v0.3.0 - v0.5.0)
|
|
1013
|
+
### Current Focus
|
|
1095
1014
|
- Full CodeCanvas integration
|
|
1096
|
-
- Unum identity support
|
|
1097
|
-
- State-Docs generation
|
|
1098
|
-
- Multi-language
|
|
1099
|
-
- Real PluresDB sync
|
|
1015
|
+
- Enhanced Unum identity support
|
|
1016
|
+
- Advanced State-Docs generation
|
|
1017
|
+
- Multi-language schema support
|
|
1018
|
+
- Real PluresDB sync with CRDT/offline-first capabilities
|
|
1100
1019
|
|
|
1101
1020
|
### Long Term
|
|
1102
1021
|
- Mobile templates (iOS, Android)
|
|
@@ -1105,354 +1024,39 @@ See [csharp/Praxis/README.md](./csharp/Praxis/README.md) for complete documentat
|
|
|
1105
1024
|
- Performance optimizations
|
|
1106
1025
|
- Plugin ecosystem
|
|
1107
1026
|
|
|
1108
|
-
##
|
|
1109
|
-
|
|
1110
|
-
### Ecosystem Integration
|
|
1027
|
+
## Cross-Language Support
|
|
1111
1028
|
|
|
1112
|
-
|
|
1113
|
-
- **PluresDB**: ✅ Reactive datastore integration with 32 tests
|
|
1114
|
-
- **Cloud**: ✅ GitHub-based auth and tier billing
|
|
1115
|
-
- **unum**: 🚧 Identity/channels and messaging
|
|
1116
|
-
- **Visualization**: VSCode extension, docs generator, canvas tools (introspection API ready)
|
|
1117
|
-
- **ADP**: Architectural guardrails and static checks
|
|
1029
|
+
The core protocol is implemented across multiple languages:
|
|
1118
1030
|
|
|
1119
|
-
|
|
1031
|
+
**TypeScript** (Primary, npm: `@plures/praxis`)
|
|
1032
|
+
```typescript
|
|
1033
|
+
import { createPraxisEngine, PraxisRegistry } from "@plures/praxis";
|
|
1120
1034
|
|
|
1121
|
-
|
|
1035
|
+
const engine = createPraxisEngine({
|
|
1036
|
+
initialContext: {},
|
|
1037
|
+
registry: new PraxisRegistry(),
|
|
1038
|
+
});
|
|
1039
|
+
const result = engine.step(events);
|
|
1040
|
+
```
|
|
1122
1041
|
|
|
1123
|
-
**C
|
|
1042
|
+
**C#** (.NET 8+, NuGet: `Plures.Praxis`)
|
|
1124
1043
|
```csharp
|
|
1125
|
-
// Full functional C# implementation with immutable records
|
|
1126
1044
|
var engine = PraxisEngine.Create(new PraxisEngineOptions<TContext> { ... });
|
|
1127
1045
|
var result = engine.Step(events);
|
|
1128
1046
|
```
|
|
1129
1047
|
|
|
1130
1048
|
See [csharp/Praxis/README.md](./csharp/Praxis/README.md) for full documentation.
|
|
1131
1049
|
|
|
1132
|
-
**PowerShell (
|
|
1050
|
+
**PowerShell** (GitHub: `Praxis.psm1`)
|
|
1133
1051
|
```powershell
|
|
1134
1052
|
$newState = Invoke-PraxisStep -State $state -Events $events
|
|
1135
1053
|
```
|
|
1136
1054
|
|
|
1137
1055
|
See [powershell/README.md](./powershell/README.md) for full documentation.
|
|
1138
1056
|
|
|
1139
|
-
### Cross-Language Sync Strategy
|
|
1140
|
-
|
|
1141
1057
|
All implementations share the same protocol version and JSON format for interoperability.
|
|
1142
1058
|
See [CROSS_LANGUAGE_SYNC.md](./CROSS_LANGUAGE_SYNC.md) for details on keeping implementations in sync.
|
|
1143
1059
|
|
|
1144
|
-
### Advanced Features
|
|
1145
|
-
|
|
1146
|
-
- Prolog/CLP-inspired features (facts, rules, declarative constraints, goal-style interactions)
|
|
1147
|
-
- Backtracking/search over state space
|
|
1148
|
-
- Property-based testing support
|
|
1149
|
-
- Automatic documentation generation
|
|
1150
|
-
- Static analysis tools
|
|
1151
|
-
```typescript
|
|
1152
|
-
import {
|
|
1153
|
-
createRegistry,
|
|
1154
|
-
createStepFunction,
|
|
1155
|
-
rule,
|
|
1156
|
-
constraint,
|
|
1157
|
-
type PraxisState,
|
|
1158
|
-
type PraxisEvent,
|
|
1159
|
-
} from '@plures/praxis';
|
|
1160
|
-
|
|
1161
|
-
// Define your state
|
|
1162
|
-
interface AppState extends PraxisState {
|
|
1163
|
-
facts: {
|
|
1164
|
-
count: number;
|
|
1165
|
-
lastAction?: string;
|
|
1166
|
-
};
|
|
1167
|
-
}
|
|
1168
|
-
|
|
1169
|
-
// Create a registry
|
|
1170
|
-
const registry = createRegistry<AppState, PraxisEvent>();
|
|
1171
|
-
|
|
1172
|
-
// Define rules using the DSL
|
|
1173
|
-
const incrementRule = rule<AppState, PraxisEvent>()
|
|
1174
|
-
.id('increment')
|
|
1175
|
-
.describe('Increment counter when increment event occurs')
|
|
1176
|
-
.on('INCREMENT')
|
|
1177
|
-
.when((state, event) => true)
|
|
1178
|
-
.then((state, event) => [{
|
|
1179
|
-
type: 'LOG',
|
|
1180
|
-
payload: { message: 'Counter incremented' }
|
|
1181
|
-
}])
|
|
1182
|
-
.build();
|
|
1183
|
-
|
|
1184
|
-
// Define constraints
|
|
1185
|
-
const positiveCountConstraint = constraint<AppState>()
|
|
1186
|
-
.id('positive-count')
|
|
1187
|
-
.describe('Count must be non-negative')
|
|
1188
|
-
.check((state) => state.facts.count >= 0)
|
|
1189
|
-
.message('Count cannot be negative')
|
|
1190
|
-
.build();
|
|
1191
|
-
|
|
1192
|
-
// Register rules and constraints
|
|
1193
|
-
registry.registerRule(incrementRule);
|
|
1194
|
-
registry.registerConstraint(positiveCountConstraint);
|
|
1195
|
-
|
|
1196
|
-
// Create a step function with custom reducer
|
|
1197
|
-
const step = createStepFunction<AppState, PraxisEvent>({
|
|
1198
|
-
registry,
|
|
1199
|
-
checkConstraints: true,
|
|
1200
|
-
reducer: (state, event) => {
|
|
1201
|
-
if (event.type === 'INCREMENT') {
|
|
1202
|
-
return {
|
|
1203
|
-
...state,
|
|
1204
|
-
facts: {
|
|
1205
|
-
...state.facts,
|
|
1206
|
-
count: state.facts.count + 1,
|
|
1207
|
-
lastAction: 'increment',
|
|
1208
|
-
},
|
|
1209
|
-
};
|
|
1210
|
-
}
|
|
1211
|
-
return state;
|
|
1212
|
-
},
|
|
1213
|
-
});
|
|
1214
|
-
|
|
1215
|
-
// Use the step function
|
|
1216
|
-
const initialState: AppState = {
|
|
1217
|
-
facts: { count: 0 },
|
|
1218
|
-
};
|
|
1219
|
-
|
|
1220
|
-
const event: PraxisEvent = {
|
|
1221
|
-
type: 'INCREMENT',
|
|
1222
|
-
timestamp: Date.now(),
|
|
1223
|
-
};
|
|
1224
|
-
|
|
1225
|
-
const result = step(initialState, event);
|
|
1226
|
-
console.log(result.state.facts.count); // 1
|
|
1227
|
-
console.log(result.effects); // [{ type: 'LOG', payload: { message: 'Counter incremented' } }]
|
|
1228
|
-
```
|
|
1229
|
-
|
|
1230
|
-
## Core Concepts
|
|
1231
|
-
|
|
1232
|
-
### State and Events
|
|
1233
|
-
|
|
1234
|
-
**PraxisState** represents the current facts and context:
|
|
1235
|
-
|
|
1236
|
-
```typescript
|
|
1237
|
-
interface PraxisState {
|
|
1238
|
-
facts: Record<string, unknown>;
|
|
1239
|
-
metadata?: {
|
|
1240
|
-
version?: number;
|
|
1241
|
-
lastUpdated?: number;
|
|
1242
|
-
[key: string]: unknown;
|
|
1243
|
-
};
|
|
1244
|
-
}
|
|
1245
|
-
```
|
|
1246
|
-
|
|
1247
|
-
**PraxisEvent** represents things that have happened:
|
|
1248
|
-
|
|
1249
|
-
```typescript
|
|
1250
|
-
interface PraxisEvent {
|
|
1251
|
-
type: string;
|
|
1252
|
-
timestamp: number;
|
|
1253
|
-
data?: Record<string, unknown>;
|
|
1254
|
-
metadata?: {
|
|
1255
|
-
correlationId?: string;
|
|
1256
|
-
source?: string;
|
|
1257
|
-
[key: string]: unknown;
|
|
1258
|
-
};
|
|
1259
|
-
}
|
|
1260
|
-
```
|
|
1261
|
-
|
|
1262
|
-
### Rules
|
|
1263
|
-
|
|
1264
|
-
Rules are condition-action pairs that fire when conditions are met:
|
|
1265
|
-
|
|
1266
|
-
```typescript
|
|
1267
|
-
const myRule = rule<MyState, MyEvent>()
|
|
1268
|
-
.id('my-rule')
|
|
1269
|
-
.describe('What this rule does')
|
|
1270
|
-
.priority(10) // Higher priority rules execute first
|
|
1271
|
-
.on('EVENT_TYPE') // Optional: only check for specific event types
|
|
1272
|
-
.when((state, event) => {
|
|
1273
|
-
// Condition: return true to fire the rule
|
|
1274
|
-
return state.facts.someValue > 10;
|
|
1275
|
-
})
|
|
1276
|
-
.then((state, event) => {
|
|
1277
|
-
// Action: return effects to execute
|
|
1278
|
-
return [
|
|
1279
|
-
{ type: 'SEND_EMAIL', payload: { to: 'user@example.com' } },
|
|
1280
|
-
{ type: 'LOG', payload: { level: 'info', message: 'Rule fired' } },
|
|
1281
|
-
];
|
|
1282
|
-
})
|
|
1283
|
-
.build();
|
|
1284
|
-
```
|
|
1285
|
-
|
|
1286
|
-
### Constraints
|
|
1287
|
-
|
|
1288
|
-
Constraints are invariants that must hold true:
|
|
1289
|
-
|
|
1290
|
-
```typescript
|
|
1291
|
-
const myConstraint = constraint<MyState>()
|
|
1292
|
-
.id('my-constraint')
|
|
1293
|
-
.describe('What this constraint ensures')
|
|
1294
|
-
.check((state) => {
|
|
1295
|
-
// Return true if constraint is satisfied
|
|
1296
|
-
return state.facts.balance >= 0;
|
|
1297
|
-
})
|
|
1298
|
-
.message('Balance cannot be negative')
|
|
1299
|
-
.build();
|
|
1300
|
-
```
|
|
1301
|
-
|
|
1302
|
-
### Registry
|
|
1303
|
-
|
|
1304
|
-
The registry manages rules and constraints:
|
|
1305
|
-
|
|
1306
|
-
```typescript
|
|
1307
|
-
const registry = createRegistry<MyState, MyEvent>();
|
|
1308
|
-
|
|
1309
|
-
// Register rules and constraints
|
|
1310
|
-
registry.registerRule(myRule);
|
|
1311
|
-
registry.registerConstraint(myConstraint);
|
|
1312
|
-
|
|
1313
|
-
// Evaluate rules for a state transition
|
|
1314
|
-
const effects = registry.evaluateRules(state, event);
|
|
1315
|
-
|
|
1316
|
-
// Check constraints
|
|
1317
|
-
const violations = registry.checkConstraints(state);
|
|
1318
|
-
|
|
1319
|
-
// Get statistics
|
|
1320
|
-
const stats = registry.getStats();
|
|
1321
|
-
```
|
|
1322
|
-
|
|
1323
|
-
### Step Functions
|
|
1324
|
-
|
|
1325
|
-
Step functions are pure functions that transition state:
|
|
1326
|
-
|
|
1327
|
-
```typescript
|
|
1328
|
-
// With registry integration
|
|
1329
|
-
const step = createStepFunction({
|
|
1330
|
-
registry,
|
|
1331
|
-
checkConstraints: true,
|
|
1332
|
-
reducer: (state, event) => {
|
|
1333
|
-
// Your state transition logic
|
|
1334
|
-
return newState;
|
|
1335
|
-
},
|
|
1336
|
-
});
|
|
1337
|
-
|
|
1338
|
-
// Simple step without registry
|
|
1339
|
-
const simpleStep = step((state, event) => {
|
|
1340
|
-
// Direct state transformation
|
|
1341
|
-
return { ...state, facts: { ...state.facts, updated: true } };
|
|
1342
|
-
});
|
|
1343
|
-
|
|
1344
|
-
// Compose multiple step functions
|
|
1345
|
-
const composedStep = compose(step1, step2, step3);
|
|
1346
|
-
```
|
|
1347
|
-
|
|
1348
|
-
### Actors
|
|
1349
|
-
|
|
1350
|
-
Actors maintain their own state and respond to events:
|
|
1351
|
-
|
|
1352
|
-
```typescript
|
|
1353
|
-
import { createActor, createActorSystem } from '@plures/praxis';
|
|
1354
|
-
|
|
1355
|
-
// Create an actor
|
|
1356
|
-
const myActor = createActor(
|
|
1357
|
-
'actor-1',
|
|
1358
|
-
initialState,
|
|
1359
|
-
stepFunction,
|
|
1360
|
-
'counter-actor'
|
|
1361
|
-
);
|
|
1362
|
-
|
|
1363
|
-
// Create an actor system
|
|
1364
|
-
const system = createActorSystem();
|
|
1365
|
-
system.register(myActor);
|
|
1366
|
-
|
|
1367
|
-
// Send events to actors
|
|
1368
|
-
const result = system.send('actor-1', event);
|
|
1369
|
-
|
|
1370
|
-
// Broadcast to all actors
|
|
1371
|
-
const results = system.broadcast(event);
|
|
1372
|
-
```
|
|
1373
|
-
|
|
1374
|
-
### Flows
|
|
1375
|
-
|
|
1376
|
-
Flows represent sequences of events:
|
|
1377
|
-
|
|
1378
|
-
```typescript
|
|
1379
|
-
import { createFlow, advanceFlow } from '@plures/praxis';
|
|
1380
|
-
|
|
1381
|
-
// Define a flow
|
|
1382
|
-
const flow = createFlow('onboarding-flow', [
|
|
1383
|
-
{ id: 'step1', expectedEventType: 'USER_REGISTERED' },
|
|
1384
|
-
{ id: 'step2', expectedEventType: 'EMAIL_VERIFIED' },
|
|
1385
|
-
{ id: 'step3', expectedEventType: 'PROFILE_COMPLETED' },
|
|
1386
|
-
]);
|
|
1387
|
-
|
|
1388
|
-
// Advance the flow with events
|
|
1389
|
-
const { flow: updatedFlow, accepted } = advanceFlow(flow, event);
|
|
1390
|
-
|
|
1391
|
-
if (updatedFlow.complete) {
|
|
1392
|
-
console.log('Flow completed!');
|
|
1393
|
-
}
|
|
1394
|
-
```
|
|
1395
|
-
|
|
1396
|
-
## Architecture Principles
|
|
1397
|
-
|
|
1398
|
-
1. **Pure Functions**: State transitions are pure, predictable, and testable
|
|
1399
|
-
2. **JSON-Friendly**: All data structures serialize to JSON for interoperability
|
|
1400
|
-
3. **Logic-First**: Focus on business logic, not implementation details
|
|
1401
|
-
4. **Composable**: Build complex behavior from simple, reusable pieces
|
|
1402
|
-
5. **Type-Safe**: Leverage TypeScript for compile-time guarantees
|
|
1403
|
-
|
|
1404
|
-
## Advanced Usage
|
|
1405
|
-
|
|
1406
|
-
### Custom Event Types
|
|
1407
|
-
|
|
1408
|
-
```typescript
|
|
1409
|
-
interface UserEvent extends PraxisEvent {
|
|
1410
|
-
type: 'USER_LOGIN' | 'USER_LOGOUT';
|
|
1411
|
-
data: {
|
|
1412
|
-
userId: string;
|
|
1413
|
-
sessionId: string;
|
|
1414
|
-
};
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
|
-
const registry = createRegistry<AppState, UserEvent>();
|
|
1418
|
-
```
|
|
1419
|
-
|
|
1420
|
-
### Effect Handlers
|
|
1421
|
-
|
|
1422
|
-
Effects are side-effect descriptions that can be executed outside the pure core:
|
|
1423
|
-
|
|
1424
|
-
```typescript
|
|
1425
|
-
async function executeEffects(effects: Effect[]) {
|
|
1426
|
-
for (const effect of effects) {
|
|
1427
|
-
switch (effect.type) {
|
|
1428
|
-
case 'SEND_EMAIL':
|
|
1429
|
-
await emailService.send(effect.payload);
|
|
1430
|
-
break;
|
|
1431
|
-
case 'LOG':
|
|
1432
|
-
console.log(effect.payload);
|
|
1433
|
-
break;
|
|
1434
|
-
// Add more effect handlers as needed
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
const result = step(state, event);
|
|
1440
|
-
if (result.effects) {
|
|
1441
|
-
await executeEffects(result.effects);
|
|
1442
|
-
}
|
|
1443
|
-
```
|
|
1444
|
-
|
|
1445
|
-
## Future Roadmap
|
|
1446
|
-
|
|
1447
|
-
- ✅ **Svelte v5 Integration**: First-class support for Svelte 5 runes (available)
|
|
1448
|
-
- ✅ **PluresDB Integration**: Reactive datastore with 32 tests (available)
|
|
1449
|
-
- ✅ **C# Port**: Cross-platform compatibility with 95 tests (available)
|
|
1450
|
-
- ✅ **PowerShell Module**: Scripting and automation support (available)
|
|
1451
|
-
- 🚧 **Unum Integration**: Identity and channels (in progress)
|
|
1452
|
-
- 🚧 **CodeCanvas**: Visual schema and logic editor (planned)
|
|
1453
|
-
- 🚧 **State-Docs**: Documentation generation (planned)
|
|
1454
|
-
- 📊 **Visualization**: Flow and state visualization tools (introspection ready)
|
|
1455
|
-
|
|
1456
1060
|
## Development
|
|
1457
1061
|
|
|
1458
1062
|
```bash
|
package/package.json
CHANGED