Skip to content

plures/praxis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

98 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

dotnet build dotnet test

Praxis

Typed, visual-first application logic for Svelte, Node, and the browser.

npm version JSR License: MIT Node.js Version Deno Compatible

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.


What’s new

  • Unified builds & exports: ./, ./svelte, ./schema, ./component, ./cloud, ./components, and CLI all ship with ESM, CJS, and type definitions.
  • Svelte 5 runes native: Runes-friendly stores and helpers; server+client builds for integrations.
  • Framework-agnostic reactivity: Proxy-based reactive engine for use without Svelte, enabling reactive state management in Node.js, browsers, and any JavaScript environment.
  • Logic engine refinements: Typed registry, step diagnostics, and trace-friendly rule execution.
  • Cloud relay & local-first: Polished cloud connector alongside PluresDB-first workflows.
  • Publish-ready: npm public access + JSR exports aligned to source.

Capabilities at a glance

  • Logic Engine: Facts, events, rules, constraints, registry, introspection, and reactive engine variants (Svelte 5 + framework-agnostic).
  • Schema & Codegen: PSF-style schema types plus component generator for Svelte UIs.
  • Svelte Integration: Typed helpers, runes-ready builds, and Svelte component typings.
  • Local-First Data: PluresDB integrations for offline-first, reactive state.
  • Cloud Relay: Optional sync layer (GitHub-auth friendly) for distributed teams.
  • CLI: Scaffolding, generation, canvas helpers, and cloud commands.

Install

Node 18+ recommended.

# npm
npm install @plures/praxis

# pnpm
pnpm add @plures/praxis

JSR (Deno):

const result = engine.step([Login.create({ username: 'alice' })]);
# or via import map pointing to npm:
# {
#   "imports": { "@plures/praxis": "npm:@plures/praxis@^1.1.2" }
# }

Quick start (logic engine)

import {
  createPraxisEngine,
  PraxisRegistry,
  defineFact,
  defineEvent,
  defineRule,
} from '@plures/praxis';

const UserLoggedIn = defineFact<'UserLoggedIn', { userId: string }>('UserLoggedIn');
const Login = defineEvent<'LOGIN', { username: string }>('LOGIN');

const loginRule = defineRule<{ currentUser: string | null }>({
  id: 'auth.login',
  description: 'Authenticate and emit fact',
  impl: (state, events) => {
    const evt = events.find(Login.is);
    if (!evt) return [];
    state.context.currentUser = evt.payload.username;
    return [UserLoggedIn.create({ userId: evt.payload.username })];
  },
});

const registry = new PraxisRegistry();
registry.registerRule(loginRule);

const engine = createPraxisEngine({ initialContext: { currentUser: null }, registry });
engine.step([Login.create({ username: 'alex' })]);

Svelte integration (runes-ready)

<script lang="ts">
  import { createReactiveEngine, defineEvent, defineRule, PraxisRegistry } from '@plures/praxis/svelte';

  const Increment = defineEvent<'INCREMENT', { amount: number }>('INCREMENT');
  const counterRule = defineRule<{ count: number }>({
    id: 'counter.increment',
    description: 'Add to count',
    impl: (state, events) => {
      const evt = events.find(Increment.is);
      if (evt) state.context.count += evt.payload.amount;
      return [];
    },
  });

  const registry = new PraxisRegistry();
  registry.registerRule(counterRule);

  const engine = createReactiveEngine({ initialContext: { count: 0 }, registry });
  
  // Use Svelte's $derived with the reactive engine state
  const count = $derived(engine.context.count);

  function addOne() {
    engine.step([Increment.create({ amount: 1 })]);
  }
</script>

<button on:click={addOne}>Count is {count}</button>

Framework-agnostic reactive engine

For non-Svelte environments, use the framework-agnostic reactive engine with Proxy-based reactivity:

import { createFrameworkAgnosticReactiveEngine } from '@plures/praxis';

const engine = createFrameworkAgnosticReactiveEngine({
  initialContext: { count: 0 },
});

// Subscribe to state changes
engine.subscribe((state) => {
  console.log('Count:', state.context.count);
});

// Create derived/computed values
const doubled = engine.$derived((state) => state.context.count * 2);
doubled.subscribe((value) => {
  console.log('Doubled:', value);
});

// Apply mutations (batched for performance)
engine.apply((state) => {
  state.context.count += 1;
});

See the reactive counter example for a complete demonstration.

Cloud relay (optional)

import { connectRelay } from '@plures/praxis/cloud';

const relay = await connectRelay('https://my-relay.example.com', {
  appId: 'my-app',
  authToken: process.env.GITHUB_TOKEN,
  autoSync: true,
});

await relay.sync({
  type: 'delta',
  appId: 'my-app',
  clock: {},
  facts: [],
  timestamp: Date.now(),
});

PluresDB integration

import { PluresNode } from 'pluresdb';
import { createPluresDB, createPraxisDBStore } from '@plures/praxis';
import { PraxisRegistry } from '@plures/praxis';

// Initialize the official PluresDB from npm
const pluresdb = new PluresNode({
  config: {
    port: 34567,
    dataDir: './data',
  },
  autoStart: true,
});

// Wrap it with the Praxis adapter
const db = createPluresDB(pluresdb);

// Use with Praxis store for local-first reactive data
const registry = new PraxisRegistry();
const store = createPraxisDBStore(db, registry);

// Or use in-memory database for development/testing
import { createInMemoryDB } from '@plures/praxis';
const devDb = createInMemoryDB();

Note: Praxis now uses the official PluresDB package from NPM, which provides P2P sync, CRDT conflict resolution, SQLite compatibility, and more. The createPluresDB() function wraps PluresDB to provide the PraxisDB interface used by Praxis.

CLI (npx-friendly)

npx praxis --help
npx praxis create app my-app
npx praxis generate --schema src/schemas/app.schema.ts
npx praxis canvas src/schemas/app.schema.ts

Exports map

  • @plures/praxis β†’ main engine (ESM/CJS/types)
  • @plures/praxis/svelte β†’ Svelte 5 integrations
  • @plures/praxis/schema β†’ Schema types
  • @plures/praxis/component β†’ Component generator
  • @plures/praxis/cloud β†’ Cloud relay APIs
  • @plures/praxis/components β†’ TS props for Svelte components (e.g., TerminalNode)
  • praxis (bin) β†’ CLI entrypoint

Documentation

Contributing

PRs and discussions welcome. Please see CONTRIBUTING.md and SECURITY.md. console.log(result.state.facts); // [{ tag: "UserLoggedIn", payload: { userId: "alice" } }] console.log(engine.getContext()); // { currentUser: "alice" }


### With Constraints

```typescript
import { defineConstraint } from '@plures/praxis';

const maxSessionsConstraint = defineConstraint<AuthContext>({
  id: 'auth.maxSessions',
  description: 'Only one user can be logged in at a time',
  impl: (state) => {
    return state.context.currentUser === null || 'User already logged in';
  },
});

registry.registerConstraint(maxSessionsConstraint);

Svelte 5 Integration

Store API (Svelte 4/5 Compatible)

import { createPraxisStore, createDerivedStore } from '@plures/praxis/svelte';

const stateStore = createPraxisStore(engine);
const userStore = createDerivedStore(engine, (ctx) => ctx.currentUser);

// In Svelte component:
// $: currentUser = $userStore;
// <button on:click={() => stateStore.dispatch([Login.create({ username: "alice" })])}>
//   Login
// </button>

Runes API (Svelte 5 Only)

<script lang="ts">
  import { usePraxisEngine } from '@plures/praxis/svelte';
  import { createMyEngine, Login } from './my-engine';

  const engine = createMyEngine();
  const {
    context,      // Reactive context
    dispatch,     // Dispatch events
    undo,         // Undo last action
    redo,         // Redo action
    canUndo,      // Boolean: can undo?
    canRedo,      // Boolean: can redo?
  } = usePraxisEngine(engine, {
    enableHistory: true,    // Enable undo/redo
    maxHistorySize: 50,     // Keep last 50 snapshots
  });
</script>

<div>
  <p>User: {context.currentUser || 'Guest'}</p>

  <button onclick={() => dispatch([Login.create({ username: 'alice' })])}>
    Login
  </button>

  <button onclick={undo} disabled={!canUndo}>
    ⟲ Undo
  </button>

  <button onclick={redo} disabled={!canRedo}>
    ⟳ Redo
  </button>
</div>

See the Advanced Todo Example for a complete demo with:

  • Undo/redo functionality
  • Time-travel debugging
  • Keyboard shortcuts
  • Beautiful UI

For comprehensive guides:

Core Protocol

The language-neutral core protocol forms the foundation of Praxis:

// Facts and Events
interface PraxisFact {
  tag: string;
  payload: unknown;
}

interface PraxisEvent {
  tag: string;
  payload: unknown;
}

// State
interface PraxisState {
  context: unknown;
  facts: PraxisFact[];
  meta?: Record<string, unknown>;
}

// Step Function (the conceptual core)
type PraxisStepFn = (
  state: PraxisState,
  events: PraxisEvent[],
  config: PraxisStepConfig
) => PraxisStepResult;

This protocol is:

  • Pure and deterministic (data in β†’ data out)
  • No side effects, no global state
  • JSON-friendly for cross-language compatibility
  • The foundation for all higher-level TypeScript APIs

Framework Architecture

/praxis
β”œβ”€β”€ core/                          # Core framework
β”‚   β”œβ”€β”€ schema/                    # Schema system
β”‚   β”‚   └── types.ts              # Schema type definitions
β”‚   β”œβ”€β”€ logic/                     # Logic engine (existing src/core/)
β”‚   β”‚   β”œβ”€β”€ protocol.ts           # Language-neutral protocol
β”‚   β”‚   β”œβ”€β”€ rules.ts              # Rules, constraints, and registry
β”‚   β”‚   β”œβ”€β”€ engine.ts             # LogicEngine implementation
β”‚   β”‚   β”œβ”€β”€ actors.ts             # Actor system
β”‚   β”‚   └── introspection.ts      # Introspection and visualization
β”‚   β”œβ”€β”€ component/                 # Component generation
β”‚   β”‚   └── generator.ts          # Svelte component generator
β”‚   β”œβ”€β”€ pluresdb/                  # PluresDB integration core
β”‚   β”‚   β”œβ”€β”€ adapter.ts            # Database adapter interface
β”‚   β”‚   β”œβ”€β”€ store.ts              # Reactive store implementation
β”‚   β”‚   β”œβ”€β”€ schema-registry.ts    # Schema registry for PluresDB
β”‚   β”‚   └── generator.ts          # PluresDB config generator
β”‚   └── runtime/                   # Runtime abstractions
β”œβ”€β”€ cloud/                         # Praxis Cloud integration
β”‚   β”œβ”€β”€ auth.ts                   # GitHub OAuth authentication
β”‚   β”œβ”€β”€ billing.ts                # Tier-based billing
β”‚   β”œβ”€β”€ provisioning.ts           # Tenant provisioning
β”‚   └── relay/                    # Azure relay service
β”œβ”€β”€ integrations/                  # Ecosystem integrations
β”‚   β”œβ”€β”€ pluresdb.ts               # PluresDB integration exports
β”‚   β”œβ”€β”€ svelte.ts                 # Svelte 5 integration
β”‚   β”œβ”€β”€ unum/                     # Unum identity and channels
β”‚   β”œβ”€β”€ adp/                      # Architectural Decision Protocol
β”‚   β”œβ”€β”€ state-docs/               # State-Docs documentation
β”‚   └── canvas/                   # CodeCanvas visual editor
β”œβ”€β”€ components/                    # Svelte components
β”‚   └── TerminalNode.svelte       # Terminal node component
β”œβ”€β”€ cli/                          # Command-line interface
β”‚   β”œβ”€β”€ index.ts                  # CLI entry point
β”‚   └── commands/                 # Command implementations
β”œβ”€β”€ templates/                     # Project templates
β”‚   β”œβ”€β”€ basic-app/                # Basic application template
β”‚   └── fullstack-app/            # Full-stack template
β”œβ”€β”€ examples/                      # Example applications
β”‚   β”œβ”€β”€ offline-chat/             # Offline-first chat demo
β”‚   β”œβ”€β”€ knowledge-canvas/         # Knowledge management with Canvas
β”‚   β”œβ”€β”€ distributed-node/         # Self-orchestrating node demo
β”‚   β”œβ”€β”€ terminal-node/            # Terminal node demo
β”‚   β”œβ”€β”€ terminal-canvas/          # Terminal + canvas demo
β”‚   β”œβ”€β”€ cloud-sync/               # Cloud sync demo
β”‚   β”œβ”€β”€ github-monetization/      # GitHub monetization demo
β”‚   β”œβ”€β”€ simple-app/               # Simple app demo
β”‚   β”œβ”€β”€ auth-basic/               # Login/logout example
β”‚   β”œβ”€β”€ cart/                     # Shopping cart example
β”‚   β”œβ”€β”€ svelte-counter/           # Svelte integration example
β”‚   └── hero-ecommerce/           # Comprehensive e-commerce demo
└── docs/                         # Framework documentation
    β”œβ”€β”€ guides/                   # User guides
    β”‚   β”œβ”€β”€ getting-started.md   # Getting started guide
    β”‚   β”œβ”€β”€ canvas.md            # CodeCanvas guide
    β”‚   └── orchestration.md     # Orchestration guide
    β”œβ”€β”€ api/                      # API reference
    └── architecture/             # Architecture documentation

See FRAMEWORK.md for complete architecture documentation.

Examples

The repository includes multiple complete examples:

1. Hero E-Commerce (src/examples/hero-ecommerce)

Comprehensive example demonstrating all Praxis features in a single application:

  • Authentication with session management
  • Shopping cart with discount rules
  • Feature flags for A/B testing
  • Loyalty program with points
  • Actors for logging and analytics
  • Constraints enforcing business rules
npm run build
node dist/examples/hero-ecommerce/index.js

2. Offline-First Chat (examples/offline-chat)

Demonstrates local-first architecture with PluresDB:

  • Offline message composition and storage
  • Automatic sync when connected
  • Message queue for offline messages
  • Conflict resolution for concurrent edits
  • Real-time features (typing indicators, read receipts)

See examples/offline-chat/README.md

3. Knowledge Canvas (examples/knowledge-canvas)

Showcases CodeCanvas integration for visual knowledge management:

  • Visual knowledge graph editing
  • Schema-driven content types
  • Generated UI components
  • State-Docs integration
  • Collaborative editing

See examples/knowledge-canvas/README.md

4. Self-Orchestrating Node (examples/distributed-node)

Demonstrates distributed orchestration with DSC/MCP:

  • Automatic node discovery
  • Self-healing behavior
  • State synchronization across nodes
  • Health monitoring and auto-scaling
  • Failover and recovery

See examples/distributed-node/README.md

5. Terminal Node (examples/terminal-node)

Demonstrates the terminal node feature for command execution:

  • Terminal adapter creation and configuration
  • Command execution and history tracking
  • YAML schema loading with terminal nodes
  • PluresDB binding configuration (ready for integration)
  • Both text and widget input modes
npm run build
node examples/terminal-node/index.js

See examples/terminal-node/README.md and docs/TERMINAL_NODE.md

6. Auth Basic (src/examples/auth-basic)

Login/logout with facts, rules, and constraints.

npm run build
node dist/examples/auth-basic/index.js

7. Cart (src/examples/cart)

Shopping cart with multiple rules, constraints, and complex state management.

npm run build
node dist/examples/cart/index.js

8. Svelte Counter (src/examples/svelte-counter)

Counter example showing Svelte v5 integration with reactive stores.

npm run build
node dist/examples/svelte-counter/index.js

9. Terminal Canvas (examples/terminal-canvas)

Combines terminal nodes with visual canvas features in a Svelte app.

See examples/terminal-canvas/README.md

10. GitHub Monetization (examples/github-monetization)

Example of GitHub-based monetization integration with Praxis Cloud.

See examples/github-monetization/README.md

11. Simple App (examples/simple-app)

A minimal example demonstrating basic Praxis schema usage.

See examples/simple-app/README.md

12. Cloud Sync (examples/cloud-sync)

Demonstrates real-time synchronization with Praxis Cloud relay service.

See examples/cloud-sync/README.md

API Reference

Core Types

  • PraxisFact, PraxisEvent, PraxisState - Protocol types
  • LogicEngine<TContext> - Main engine class
  • PraxisRegistry<TContext> - Rule and constraint registry
  • Actor<TContext> - Actor interface
  • ActorManager<TContext> - Actor lifecycle management

DSL Functions

  • defineFact<TTag, TPayload>(tag) - Define a typed fact
  • defineEvent<TTag, TPayload>(tag) - Define a typed event
  • defineRule<TContext>(options) - Define a rule
  • defineConstraint<TContext>(options) - Define a constraint
  • defineModule<TContext>(options) - Bundle rules and constraints

Helpers

  • findEvent(events, definition) - Find first matching event
  • findFact(facts, definition) - Find first matching fact
  • filterEvents(events, definition) - Filter events by type
  • filterFacts(facts, definition) - Filter facts by type

Introspection & Visualization

Tools for examining and visualizing your Praxis logic:

import { createIntrospector, PRAXIS_PROTOCOL_VERSION } from '@plures/praxis';

const introspector = createIntrospector(registry);

// Get statistics
const stats = introspector.getStats();
console.log(`Rules: ${stats.ruleCount}, Constraints: ${stats.constraintCount}`);

// Generate JSON schema
const schema = introspector.generateSchema(PRAXIS_PROTOCOL_VERSION);

// Generate graph visualization
const graph = introspector.generateGraph();

// Export to Graphviz DOT format
const dot = introspector.exportDOT();
fs.writeFileSync('registry.dot', dot);

// Export to Mermaid format
const mermaid = introspector.exportMermaid();

// Search rules and constraints
const authRules = introspector.searchRules('auth');
const maxConstraints = introspector.searchConstraints('max');

Available methods:

  • getStats() - Get registry statistics
  • generateSchema(protocolVersion) - Generate JSON schema
  • generateGraph() - Generate graph representation
  • exportDOT() - Export to Graphviz DOT format
  • exportMermaid() - Export to Mermaid diagram format
  • getRuleInfo(id) - Get detailed rule information
  • getConstraintInfo(id) - Get detailed constraint information
  • searchRules(query) - Search rules by text
  • searchConstraints(query) - Search constraints by text

Ecosystem Integration

Praxis integrates with the full Plures ecosystem:

PluresDB Integration

Local-first reactive datastore for offline-capable applications. Now fully implemented with 32 tests covering all features.

import {
  createInMemoryDB,
  createPraxisDBStore,
  createPluresDBAdapter,
  attachToEngine,
} from '@plures/praxis/pluresdb';

// Create an in-memory database
const db = createInMemoryDB();

// Create a PraxisDB store for facts and events
const store = createPraxisDBStore({ db });

// Or create an adapter to attach to an engine
const adapter = createPluresDBAdapter({
  db,
  registry,
  initialContext: {},
});

// Attach adapter to engine for automatic persistence
adapter.attachEngine(engine);

// Persist facts and events
await adapter.persistFacts([{ tag: 'UserLoggedIn', payload: { userId: 'alice' } }]);
await adapter.persistEvents([{ tag: 'LOGIN', payload: { username: 'alice' } }]);

// Subscribe to changes
adapter.subscribeToEvents((events) => {
  console.log('New events:', events);
});

Features:

  • In-memory adapter: Ready-to-use implementation for development and testing
  • Reactive store: Watch for changes with callbacks
  • Schema registry: Store and retrieve schemas in PluresDB
  • Config generator: Generate PluresDB configuration from Praxis schemas
  • Engine integration: Automatic fact/event persistence

Status: βœ… Available (src/core/pluresdb/, src/integrations/pluresdb.ts)
Tests: 32 tests covering adapter, store, registry, and engine integration

Unum Integration

Identity and channels for distributed systems.

import { createUnumIdentity, createChannel } from '@plures/unum';

// Create identity
const identity = await createUnumIdentity({
  name: 'my-app-node',
  keys: await generateKeys(),
});

// Create channel for messaging
const channel = await createChannel({
  name: 'app-events',
  participants: [identity.id],
});

// Integrate with Praxis actors
const unumActor = createActor('unum-bridge', identity, async (event) => {
  // Bridge Praxis events to Unum channels
  await channel.publish(event);
});

Status: Planned
Use Cases: Distributed messaging, identity management, authentication

ADP Integration

Architectural Decision Protocol for guardrails and governance.

import { createADP } from '@plures/adp';

// Track architectural decisions from schemas
const adp = createADP({
  source: 'praxis-schema',
  decisions: [
    {
      id: 'ADR-001',
      title: 'Use PluresDB for local-first storage',
      context: 'Need offline-capable data storage',
      decision: 'Adopt PluresDB',
      consequences: ['Offline support', 'Sync complexity'],
    },
  ],
});

// Enforce guardrails
adp.enforce({
  rule: 'no-direct-database-access',
  check: (code) => !code.includes('direct-sql'),
});

Status: Planned
Use Cases: Architecture documentation, compliance checking, guardrails

State-Docs Integration

Living documentation generated from Praxis schemas.

import { generateStateDocs } from '@plures/state-docs';

// Generate documentation from schema
const docs = await generateStateDocs({
  schema: appSchema,
  logic: logicDefinitions,
  components: componentDefinitions,
  output: './docs',
  format: 'markdown', // or 'html', 'pdf'
});

// Documentation includes:
// - Data model diagrams
// - Logic flow diagrams
// - Component catalog
// - API reference
// - Usage examples

Status: Planned
Documentation: See examples for State-Docs integration patterns

CodeCanvas Integration

Visual IDE for schema and logic editing.

# Open Canvas for visual editing
praxis canvas src/schemas/app.schema.ts

# Features:
# - Visual schema design
# - Logic flow editor
# - Component preview
# - Real-time collaboration
# - Export to code

Status: Planned
Documentation: docs/guides/canvas.md

Svelte + Tauri Runtime

Cross-platform runtime for web, desktop, and mobile.

// Svelte v5 integration (available now)
import { createPraxisStore } from '@plures/praxis/svelte';

const stateStore = createPraxisStore(engine);
const userStore = createDerivedStore(engine, (ctx) => ctx.currentUser);

// In Svelte component:
// $: currentUser = $userStore;

// Desktop app with Tauri
npm run tauri:dev    // Development
npm run tauri:build  // Production

Status: Svelte integration available, Tauri templates planned
Platform Support: Web (now), Desktop (planned), Mobile (future)

Cross-Language Usage

PowerShell

Full PowerShell adapter for using Praxis from PowerShell scripts:

# Import module
Import-Module ./powershell/Praxis.psm1

# Initialize adapter
Initialize-PraxisAdapter -EnginePath "./dist/adapters/cli.js"

# Create state and events
$state = New-PraxisState -Context @{ count = 0 }
$event = New-PraxisEvent -Tag "INCREMENT" -Payload @{}

# Process step
$result = Invoke-PraxisStep -State $state -Events @($event) -ConfigPath "./config.json"

# Use result
Write-Host "Count: $($result.state.context.count)"

See powershell/README.md for complete documentation and examples.

C# (.NET 8+)

Full C# implementation with functional, immutable design:

using Praxis.Core;
using Praxis.Dsl;

// Define facts and events
var UserLoggedIn = PraxisDsl.DefineFact<UserPayload>("UserLoggedIn");
var Login = PraxisDsl.DefineEvent<LoginPayload>("LOGIN");

record UserPayload(string UserId);
record LoginPayload(string Username);

// Define rules
var loginRule = PraxisDsl.DefineRule<AuthContext>(
    id: "auth.login",
    description: "Process login event",
    impl: (state, context, events) =>
    {
        var loginEvent = events.FindEvent(Login);
        if (loginEvent != null)
        {
            var payload = Login.GetPayload(loginEvent);
            return [UserLoggedIn.Create(new UserPayload(payload?.Username ?? "unknown"))];
        }
        return [];
    });

// Create engine
var registry = new PraxisRegistry<AuthContext>();
registry.RegisterRule(loginRule);

var engine = PraxisEngine.Create(new PraxisEngineOptions<AuthContext>
{
    InitialContext = new AuthContext(null),
    Registry = registry
});

// Dispatch events
var result = engine.Step([Login.Create(new LoginPayload("alice"))]);
Console.WriteLine($"Facts: {result.State.Facts.Count}"); // Facts: 1

See csharp/Praxis/README.md for complete documentation.

Roadmap

Current Focus

  • Full CodeCanvas integration
  • Enhanced Unum identity support
  • Advanced State-Docs generation
  • Multi-language schema support
  • Real PluresDB sync with CRDT/offline-first capabilities

Long Term

  • Mobile templates (iOS, Android)
  • Enterprise features
  • Advanced orchestration
  • Performance optimizations
  • Plugin ecosystem

Cross-Language Support

The core protocol is implemented across multiple languages:

TypeScript (Primary, npm: @plures/praxis)

import { createPraxisEngine, PraxisRegistry } from '@plures/praxis';

const engine = createPraxisEngine({
  initialContext: {},
  registry: new PraxisRegistry(),
});
const result = engine.step(events);

C# (.NET 8+, NuGet: Plures.Praxis)

var engine = PraxisEngine.Create(new PraxisEngineOptions<TContext> { ... });
var result = engine.Step(events);

See csharp/Praxis/README.md for full documentation.

PowerShell (GitHub: Praxis.psm1)

$newState = Invoke-PraxisStep -State $state -Events $events

See powershell/README.md for full documentation.

All implementations share the same protocol version and JSON format for interoperability. See CROSS_LANGUAGE_SYNC.md for details on keeping implementations in sync.

Development

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Type check
npm run typecheck

Deno Development

# Run with Deno
deno task dev

# Run tests
deno task test

# Lint and format
deno task lint
deno task fmt

For more detailed development information, see CONTRIBUTING.md.

License

MIT License - see LICENSE for details.

Contributing

Contributions are welcome! Please read our Contributing Guide to get started.

Please review our Code of Conduct before participating.

Support


Praxis – Because application logic should be practical, provable, and portable.


Built with ❀️ by the plures team