@plures/praxis 0.2.1 → 1.0.1
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 +191 -64
- package/core/codegen/docs-generator.ts +808 -0
- package/core/codegen/index.ts +27 -0
- package/core/codegen/ts-generator.ts +15 -0
- package/core/db-adapter/index.ts +52 -0
- package/core/db-adapter/sync-engine.ts +450 -0
- package/core/logic-engine/engine.ts +12 -0
- package/core/logic-engine/index.ts +16 -0
- package/core/logic-engine/protocol.ts +16 -0
- package/core/logic-engine/psf-adapter.ts +269 -0
- package/core/logic-engine/rules.ts +16 -0
- package/core/schema-engine/compiler.ts +431 -0
- package/core/schema-engine/generator.ts +635 -0
- package/core/schema-engine/index.ts +18 -0
- package/core/schema-engine/psf.ts +664 -0
- package/core/schema-engine/types.ts +63 -0
- package/core/schema-engine/validator.ts +541 -0
- package/dist/core/codegen/docs-generator.d.ts +123 -0
- package/dist/core/codegen/docs-generator.d.ts.map +1 -0
- package/dist/core/codegen/docs-generator.js +674 -0
- package/dist/core/codegen/docs-generator.js.map +1 -0
- package/dist/core/codegen/index.d.ts +11 -0
- package/dist/core/codegen/index.d.ts.map +1 -0
- package/dist/core/codegen/index.js +13 -0
- package/dist/core/codegen/index.js.map +1 -0
- package/dist/core/codegen/ts-generator.d.ts +8 -0
- package/dist/core/codegen/ts-generator.d.ts.map +1 -0
- package/dist/core/codegen/ts-generator.js +8 -0
- package/dist/core/codegen/ts-generator.js.map +1 -0
- package/dist/core/db-adapter/index.d.ts +18 -0
- package/dist/core/db-adapter/index.d.ts.map +1 -0
- package/dist/core/db-adapter/index.js +23 -0
- package/dist/core/db-adapter/index.js.map +1 -0
- package/dist/core/db-adapter/sync-engine.d.ts +180 -0
- package/dist/core/db-adapter/sync-engine.d.ts.map +1 -0
- package/dist/core/db-adapter/sync-engine.js +342 -0
- package/dist/core/db-adapter/sync-engine.js.map +1 -0
- package/dist/core/logic-engine/engine.d.ts +8 -0
- package/dist/core/logic-engine/engine.d.ts.map +1 -0
- package/dist/core/logic-engine/engine.js +8 -0
- package/dist/core/logic-engine/engine.js.map +1 -0
- package/dist/core/logic-engine/index.d.ts +16 -0
- package/dist/core/logic-engine/index.d.ts.map +1 -0
- package/dist/core/logic-engine/index.js +16 -0
- package/dist/core/logic-engine/index.js.map +1 -0
- package/dist/core/logic-engine/protocol.d.ts +7 -0
- package/dist/core/logic-engine/protocol.d.ts.map +1 -0
- package/dist/core/logic-engine/protocol.js +7 -0
- package/dist/core/logic-engine/protocol.js.map +1 -0
- package/dist/core/logic-engine/psf-adapter.d.ts +88 -0
- package/dist/core/logic-engine/psf-adapter.d.ts.map +1 -0
- package/dist/core/logic-engine/psf-adapter.js +207 -0
- package/dist/core/logic-engine/psf-adapter.js.map +1 -0
- package/dist/core/logic-engine/rules.d.ts +7 -0
- package/dist/core/logic-engine/rules.d.ts.map +1 -0
- package/dist/core/logic-engine/rules.js +7 -0
- package/dist/core/logic-engine/rules.js.map +1 -0
- package/dist/core/schema-engine/compiler.d.ts +198 -0
- package/dist/core/schema-engine/compiler.d.ts.map +1 -0
- package/dist/core/schema-engine/compiler.js +262 -0
- package/dist/core/schema-engine/compiler.js.map +1 -0
- package/dist/core/schema-engine/generator.d.ts +115 -0
- package/dist/core/schema-engine/generator.d.ts.map +1 -0
- package/dist/core/schema-engine/generator.js +506 -0
- package/dist/core/schema-engine/generator.js.map +1 -0
- package/dist/core/schema-engine/index.d.ts +18 -0
- package/dist/core/schema-engine/index.d.ts.map +1 -0
- package/dist/core/schema-engine/index.js +18 -0
- package/dist/core/schema-engine/index.js.map +1 -0
- package/dist/core/schema-engine/psf.d.ts +612 -0
- package/dist/core/schema-engine/psf.d.ts.map +1 -0
- package/dist/core/schema-engine/psf.js +45 -0
- package/dist/core/schema-engine/psf.js.map +1 -0
- package/dist/core/schema-engine/types.d.ts +10 -0
- package/dist/core/schema-engine/types.d.ts.map +1 -0
- package/dist/core/schema-engine/types.js +7 -0
- package/dist/core/schema-engine/types.js.map +1 -0
- package/dist/core/schema-engine/validator.d.ts +140 -0
- package/dist/core/schema-engine/validator.d.ts.map +1 -0
- package/dist/core/schema-engine/validator.js +407 -0
- package/dist/core/schema-engine/validator.js.map +1 -0
- package/dist/src/adapters/cli.d.ts.map +1 -0
- package/dist/src/adapters/cli.js.map +1 -0
- package/dist/src/cli/commands/auth.d.ts.map +1 -0
- package/dist/src/cli/commands/auth.js.map +1 -0
- package/dist/src/cli/commands/build.d.ts +23 -0
- package/dist/src/cli/commands/build.d.ts.map +1 -0
- package/dist/src/cli/commands/build.js +162 -0
- package/dist/src/cli/commands/build.js.map +1 -0
- package/dist/src/cli/commands/canvas.d.ts +23 -0
- package/dist/src/cli/commands/canvas.d.ts.map +1 -0
- package/dist/src/cli/commands/canvas.js +215 -0
- package/dist/src/cli/commands/canvas.js.map +1 -0
- package/dist/src/cli/commands/cloud.d.ts.map +1 -0
- package/dist/src/cli/commands/cloud.js.map +1 -0
- package/dist/src/cli/commands/create.d.ts +21 -0
- package/dist/src/cli/commands/create.d.ts.map +1 -0
- package/dist/src/cli/commands/create.js +621 -0
- package/dist/src/cli/commands/create.js.map +1 -0
- package/dist/src/cli/commands/dev.d.ts +21 -0
- package/dist/src/cli/commands/dev.d.ts.map +1 -0
- package/dist/src/cli/commands/dev.js +71 -0
- package/dist/src/cli/commands/dev.js.map +1 -0
- package/dist/src/cli/commands/generate.d.ts.map +1 -0
- package/dist/src/cli/commands/generate.js.map +1 -0
- package/dist/src/cli/commands/orchestrate.d.ts +44 -0
- package/dist/src/cli/commands/orchestrate.d.ts.map +1 -0
- package/dist/src/cli/commands/orchestrate.js +150 -0
- package/dist/src/cli/commands/orchestrate.js.map +1 -0
- package/dist/{cli → src/cli}/index.d.ts.map +1 -1
- package/dist/{cli → src/cli}/index.js +53 -21
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cloud/auth.d.ts.map +1 -0
- package/dist/src/cloud/auth.js.map +1 -0
- package/dist/src/cloud/billing.d.ts.map +1 -0
- package/dist/src/cloud/billing.js.map +1 -0
- package/dist/src/cloud/client.d.ts.map +1 -0
- package/dist/src/cloud/client.js.map +1 -0
- package/dist/src/cloud/index.d.ts.map +1 -0
- package/dist/src/cloud/index.js.map +1 -0
- package/dist/src/cloud/marketplace.d.ts.map +1 -0
- package/dist/src/cloud/marketplace.js.map +1 -0
- package/dist/src/cloud/provisioning.d.ts.map +1 -0
- package/dist/src/cloud/provisioning.js.map +1 -0
- package/dist/src/cloud/relay/endpoints.d.ts.map +1 -0
- package/dist/src/cloud/relay/endpoints.js.map +1 -0
- package/dist/src/cloud/relay/health/index.d.ts.map +1 -0
- package/dist/src/cloud/relay/health/index.js.map +1 -0
- package/dist/src/cloud/relay/stats/index.d.ts.map +1 -0
- package/dist/src/cloud/relay/stats/index.js.map +1 -0
- package/dist/src/cloud/relay/sync/index.d.ts.map +1 -0
- package/dist/src/cloud/relay/sync/index.js.map +1 -0
- package/dist/src/cloud/relay/usage/index.d.ts.map +1 -0
- package/dist/src/cloud/relay/usage/index.js.map +1 -0
- package/dist/src/cloud/sponsors.d.ts.map +1 -0
- package/dist/src/cloud/sponsors.js.map +1 -0
- package/dist/src/cloud/types.d.ts.map +1 -0
- package/dist/src/cloud/types.js.map +1 -0
- package/dist/src/components/index.d.ts.map +1 -0
- package/dist/src/components/index.js.map +1 -0
- package/dist/src/core/actors.d.ts.map +1 -0
- package/dist/src/core/actors.js.map +1 -0
- package/dist/src/core/component/generator.d.ts.map +1 -0
- package/dist/{core → src/core}/component/generator.js +45 -3
- package/dist/src/core/component/generator.js.map +1 -0
- package/dist/src/core/engine.d.ts.map +1 -0
- package/dist/src/core/engine.js.map +1 -0
- package/dist/src/core/introspection.d.ts.map +1 -0
- package/dist/src/core/introspection.js.map +1 -0
- package/dist/src/core/logic/generator.d.ts.map +1 -0
- package/dist/{core → src/core}/logic/generator.js +35 -4
- package/dist/src/core/logic/generator.js.map +1 -0
- package/dist/src/core/pluresdb/adapter.d.ts +72 -0
- package/dist/src/core/pluresdb/adapter.d.ts.map +1 -0
- package/dist/src/core/pluresdb/adapter.js +73 -0
- package/dist/src/core/pluresdb/adapter.js.map +1 -0
- package/dist/src/core/pluresdb/generator.d.ts.map +1 -0
- package/dist/{core → src/core}/pluresdb/generator.js +33 -4
- package/dist/src/core/pluresdb/generator.js.map +1 -0
- package/dist/src/core/pluresdb/index.d.ts +15 -0
- package/dist/src/core/pluresdb/index.d.ts.map +1 -0
- package/dist/src/core/pluresdb/index.js +11 -0
- package/dist/src/core/pluresdb/index.js.map +1 -0
- package/dist/src/core/pluresdb/schema-registry.d.ts +104 -0
- package/dist/src/core/pluresdb/schema-registry.d.ts.map +1 -0
- package/dist/src/core/pluresdb/schema-registry.js +130 -0
- package/dist/src/core/pluresdb/schema-registry.js.map +1 -0
- package/dist/src/core/pluresdb/store.d.ts +199 -0
- package/dist/src/core/pluresdb/store.d.ts.map +1 -0
- package/dist/src/core/pluresdb/store.js +344 -0
- package/dist/src/core/pluresdb/store.js.map +1 -0
- package/dist/src/core/protocol.d.ts.map +1 -0
- package/dist/src/core/protocol.js.map +1 -0
- package/dist/src/core/rules.d.ts.map +1 -0
- package/dist/src/core/rules.js.map +1 -0
- package/dist/src/core/schema/loader.d.ts.map +1 -0
- package/dist/src/core/schema/loader.js.map +1 -0
- package/dist/src/core/schema/normalize.d.ts.map +1 -0
- package/dist/src/core/schema/normalize.js.map +1 -0
- package/dist/src/core/schema/types.d.ts.map +1 -0
- package/dist/src/core/schema/types.js.map +1 -0
- package/dist/src/dsl/index.d.ts.map +1 -0
- package/dist/src/dsl/index.js.map +1 -0
- package/dist/src/dsl.d.ts.map +1 -0
- package/dist/src/dsl.js.map +1 -0
- package/dist/src/examples/advanced-todo/index.d.ts.map +1 -0
- package/dist/src/examples/advanced-todo/index.js.map +1 -0
- package/dist/src/examples/auth-basic/index.d.ts.map +1 -0
- package/dist/src/examples/auth-basic/index.js.map +1 -0
- package/dist/src/examples/cart/index.d.ts.map +1 -0
- package/dist/src/examples/cart/index.js.map +1 -0
- package/dist/src/examples/hero-ecommerce/index.d.ts.map +1 -0
- package/dist/src/examples/hero-ecommerce/index.js.map +1 -0
- package/dist/src/examples/svelte-counter/index.d.ts.map +1 -0
- package/dist/src/examples/svelte-counter/index.js.map +1 -0
- package/dist/src/flows.d.ts.map +1 -0
- package/dist/src/flows.js.map +1 -0
- package/dist/{index.d.ts → src/index.d.ts} +12 -2
- package/dist/src/index.d.ts.map +1 -0
- package/dist/{index.js → src/index.js} +6 -1
- package/dist/src/index.js.map +1 -0
- package/dist/src/integrations/code-canvas.d.ts +265 -0
- package/dist/src/integrations/code-canvas.d.ts.map +1 -0
- package/dist/src/integrations/code-canvas.js +451 -0
- package/dist/src/integrations/code-canvas.js.map +1 -0
- package/dist/src/integrations/pluresdb.d.ts +117 -0
- package/dist/src/integrations/pluresdb.d.ts.map +1 -0
- package/dist/src/integrations/pluresdb.js +117 -0
- package/dist/src/integrations/pluresdb.js.map +1 -0
- package/dist/src/integrations/state-docs.d.ts +191 -0
- package/dist/src/integrations/state-docs.d.ts.map +1 -0
- package/dist/src/integrations/state-docs.js +515 -0
- package/dist/src/integrations/state-docs.js.map +1 -0
- package/dist/src/integrations/svelte.d.ts.map +1 -0
- package/dist/src/integrations/svelte.js.map +1 -0
- package/dist/src/integrations/tauri.d.ts +360 -0
- package/dist/src/integrations/tauri.d.ts.map +1 -0
- package/dist/src/integrations/tauri.js +278 -0
- package/dist/src/integrations/tauri.js.map +1 -0
- package/dist/src/integrations/unum.d.ts +159 -0
- package/dist/src/integrations/unum.d.ts.map +1 -0
- package/dist/src/integrations/unum.js +240 -0
- package/dist/src/integrations/unum.js.map +1 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/{runtime → src/runtime}/terminal-adapter.d.ts +58 -7
- package/dist/src/runtime/terminal-adapter.d.ts.map +1 -0
- package/dist/src/runtime/terminal-adapter.js +239 -0
- package/dist/src/runtime/terminal-adapter.js.map +1 -0
- package/dist/src/step.d.ts.map +1 -0
- package/dist/src/step.js.map +1 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/{cloud → src}/types.js.map +1 -1
- package/dist/tools/cli/commands/index.d.ts +7 -0
- package/dist/tools/cli/commands/index.d.ts.map +1 -0
- package/dist/tools/cli/commands/index.js +7 -0
- package/dist/tools/cli/commands/index.js.map +1 -0
- package/dist/tools/cli/index.d.ts +8 -0
- package/dist/tools/cli/index.d.ts.map +1 -0
- package/dist/tools/cli/index.js +9 -0
- package/dist/tools/cli/index.js.map +1 -0
- package/dist/tools/watcher/index.d.ts +105 -0
- package/dist/tools/watcher/index.d.ts.map +1 -0
- package/dist/tools/watcher/index.js +213 -0
- package/dist/tools/watcher/index.js.map +1 -0
- package/dist/ui/canvas/canvas-projection.d.ts +78 -0
- package/dist/ui/canvas/canvas-projection.d.ts.map +1 -0
- package/dist/ui/canvas/canvas-projection.js +416 -0
- package/dist/ui/canvas/canvas-projection.js.map +1 -0
- package/dist/ui/canvas/canvas-state.d.ts +200 -0
- package/dist/ui/canvas/canvas-state.d.ts.map +1 -0
- package/dist/ui/canvas/canvas-state.js +464 -0
- package/dist/ui/canvas/canvas-state.js.map +1 -0
- package/dist/ui/canvas/components/index.d.ts +95 -0
- package/dist/ui/canvas/components/index.d.ts.map +1 -0
- package/dist/ui/canvas/components/index.js +19 -0
- package/dist/ui/canvas/components/index.js.map +1 -0
- package/dist/ui/canvas/index.d.ts +32 -0
- package/dist/ui/canvas/index.d.ts.map +1 -0
- package/dist/ui/canvas/index.js +32 -0
- package/dist/ui/canvas/index.js.map +1 -0
- package/dist/ui/svelte-generator/index.d.ts +9 -0
- package/dist/ui/svelte-generator/index.d.ts.map +1 -0
- package/dist/ui/svelte-generator/index.js +11 -0
- package/dist/ui/svelte-generator/index.js.map +1 -0
- package/dist/ui/svelte-generator/psf-generator.d.ts +128 -0
- package/dist/ui/svelte-generator/psf-generator.d.ts.map +1 -0
- package/dist/ui/svelte-generator/psf-generator.js +506 -0
- package/dist/ui/svelte-generator/psf-generator.js.map +1 -0
- package/docs/README.md +155 -0
- package/docs/core/building-extensions.md +553 -0
- package/docs/core/cli-usage.md +498 -0
- package/docs/core/code-canvas-sync.md +468 -0
- package/docs/core/logic-engine.md +566 -0
- package/docs/core/pluresdb-integration.md +646 -0
- package/docs/core/schema-model.md +414 -0
- package/docs/core/ui-generation.md +580 -0
- package/docs/core/what-is-praxis.md +240 -0
- package/docs/tutorials/README.md +84 -0
- package/docs/tutorials/ecommerce-cart.md +631 -0
- package/docs/tutorials/first-app.md +529 -0
- package/docs/tutorials/form-builder.md +620 -0
- package/docs/tutorials/todo-pluresdb.md +589 -0
- package/package.json +16 -16
- package/src/__tests__/canvas-components.test.ts +450 -0
- package/src/__tests__/cli-create.test.ts +178 -0
- package/src/__tests__/code-canvas-integration.test.ts +277 -0
- package/src/__tests__/docs-generator.test.ts +181 -0
- package/src/__tests__/generators.test.ts +3 -2
- package/src/__tests__/pluresdb.test.ts +457 -0
- package/src/__tests__/psf-schema-engine.test.ts +450 -0
- package/src/__tests__/state-docs-integration.test.ts +297 -0
- package/src/__tests__/tauri-integration.test.ts +298 -0
- package/src/__tests__/terminal-node.test.ts +1 -1
- package/src/__tests__/unum-integration.test.ts +142 -0
- package/src/cli/commands/build.ts +203 -0
- package/src/cli/commands/canvas.ts +246 -0
- package/src/cli/commands/create.ts +666 -0
- package/src/cli/commands/dev.ts +95 -0
- package/src/cli/commands/orchestrate.ts +212 -0
- package/src/cli/index.ts +48 -21
- package/src/core/component/generator.ts +45 -3
- package/src/core/logic/generator.ts +39 -4
- package/src/core/pluresdb/adapter.ts +117 -0
- package/src/core/pluresdb/generator.ts +33 -4
- package/src/core/pluresdb/index.ts +37 -0
- package/src/core/pluresdb/schema-registry.ts +162 -0
- package/src/core/pluresdb/store.ts +446 -0
- package/src/index.ts +109 -0
- package/src/integrations/code-canvas.ts +717 -0
- package/src/integrations/pluresdb.ts +140 -29
- package/src/integrations/state-docs.ts +710 -0
- package/src/integrations/tauri.ts +638 -0
- package/src/integrations/unum.ts +395 -0
- package/src/runtime/terminal-adapter.ts +184 -23
- package/dist/adapters/cli.d.ts.map +0 -1
- package/dist/adapters/cli.js.map +0 -1
- package/dist/cli/commands/auth.d.ts.map +0 -1
- package/dist/cli/commands/auth.js.map +0 -1
- package/dist/cli/commands/cloud.d.ts.map +0 -1
- package/dist/cli/commands/cloud.js.map +0 -1
- package/dist/cli/commands/generate.d.ts.map +0 -1
- package/dist/cli/commands/generate.js.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cloud/auth.d.ts.map +0 -1
- package/dist/cloud/auth.js.map +0 -1
- package/dist/cloud/billing.d.ts.map +0 -1
- package/dist/cloud/billing.js.map +0 -1
- package/dist/cloud/client.d.ts.map +0 -1
- package/dist/cloud/client.js.map +0 -1
- package/dist/cloud/index.d.ts.map +0 -1
- package/dist/cloud/index.js.map +0 -1
- package/dist/cloud/marketplace.d.ts.map +0 -1
- package/dist/cloud/marketplace.js.map +0 -1
- package/dist/cloud/provisioning.d.ts.map +0 -1
- package/dist/cloud/provisioning.js.map +0 -1
- package/dist/cloud/relay/endpoints.d.ts.map +0 -1
- package/dist/cloud/relay/endpoints.js.map +0 -1
- package/dist/cloud/relay/health/index.d.ts.map +0 -1
- package/dist/cloud/relay/health/index.js.map +0 -1
- package/dist/cloud/relay/stats/index.d.ts.map +0 -1
- package/dist/cloud/relay/stats/index.js.map +0 -1
- package/dist/cloud/relay/sync/index.d.ts.map +0 -1
- package/dist/cloud/relay/sync/index.js.map +0 -1
- package/dist/cloud/relay/usage/index.d.ts.map +0 -1
- package/dist/cloud/relay/usage/index.js.map +0 -1
- package/dist/cloud/sponsors.d.ts.map +0 -1
- package/dist/cloud/sponsors.js.map +0 -1
- package/dist/cloud/types.d.ts.map +0 -1
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/index.js.map +0 -1
- package/dist/core/actors.d.ts.map +0 -1
- package/dist/core/actors.js.map +0 -1
- package/dist/core/component/generator.d.ts.map +0 -1
- package/dist/core/component/generator.js.map +0 -1
- package/dist/core/engine.d.ts.map +0 -1
- package/dist/core/engine.js.map +0 -1
- package/dist/core/introspection.d.ts.map +0 -1
- package/dist/core/introspection.js.map +0 -1
- package/dist/core/logic/generator.d.ts.map +0 -1
- package/dist/core/logic/generator.js.map +0 -1
- package/dist/core/pluresdb/generator.d.ts.map +0 -1
- package/dist/core/pluresdb/generator.js.map +0 -1
- package/dist/core/protocol.d.ts.map +0 -1
- package/dist/core/protocol.js.map +0 -1
- package/dist/core/rules.d.ts.map +0 -1
- package/dist/core/rules.js.map +0 -1
- package/dist/core/schema/loader.d.ts.map +0 -1
- package/dist/core/schema/loader.js.map +0 -1
- package/dist/core/schema/normalize.d.ts.map +0 -1
- package/dist/core/schema/normalize.js.map +0 -1
- package/dist/core/schema/types.d.ts.map +0 -1
- package/dist/core/schema/types.js.map +0 -1
- package/dist/dsl/index.d.ts.map +0 -1
- package/dist/dsl/index.js.map +0 -1
- package/dist/dsl.d.ts.map +0 -1
- package/dist/dsl.js.map +0 -1
- package/dist/examples/advanced-todo/index.d.ts.map +0 -1
- package/dist/examples/advanced-todo/index.js.map +0 -1
- package/dist/examples/auth-basic/index.d.ts.map +0 -1
- package/dist/examples/auth-basic/index.js.map +0 -1
- package/dist/examples/cart/index.d.ts.map +0 -1
- package/dist/examples/cart/index.js.map +0 -1
- package/dist/examples/hero-ecommerce/index.d.ts.map +0 -1
- package/dist/examples/hero-ecommerce/index.js.map +0 -1
- package/dist/examples/svelte-counter/index.d.ts.map +0 -1
- package/dist/examples/svelte-counter/index.js.map +0 -1
- package/dist/flows.d.ts.map +0 -1
- package/dist/flows.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/integrations/pluresdb.d.ts +0 -56
- package/dist/integrations/pluresdb.d.ts.map +0 -1
- package/dist/integrations/pluresdb.js +0 -46
- package/dist/integrations/pluresdb.js.map +0 -1
- package/dist/integrations/svelte.d.ts.map +0 -1
- package/dist/integrations/svelte.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/runtime/terminal-adapter.d.ts.map +0 -1
- package/dist/runtime/terminal-adapter.js +0 -113
- package/dist/runtime/terminal-adapter.js.map +0 -1
- package/dist/step.d.ts.map +0 -1
- package/dist/step.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{adapters → src/adapters}/cli.d.ts +0 -0
- /package/dist/{adapters → src/adapters}/cli.js +0 -0
- /package/dist/{cli → src/cli}/commands/auth.d.ts +0 -0
- /package/dist/{cli → src/cli}/commands/auth.js +0 -0
- /package/dist/{cli → src/cli}/commands/cloud.d.ts +0 -0
- /package/dist/{cli → src/cli}/commands/cloud.js +0 -0
- /package/dist/{cli → src/cli}/commands/generate.d.ts +0 -0
- /package/dist/{cli → src/cli}/commands/generate.js +0 -0
- /package/dist/{cli → src/cli}/index.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/auth.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/auth.js +0 -0
- /package/dist/{cloud → src/cloud}/billing.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/billing.js +0 -0
- /package/dist/{cloud → src/cloud}/client.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/client.js +0 -0
- /package/dist/{cloud → src/cloud}/index.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/index.js +0 -0
- /package/dist/{cloud → src/cloud}/marketplace.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/marketplace.js +0 -0
- /package/dist/{cloud → src/cloud}/provisioning.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/provisioning.js +0 -0
- /package/dist/{cloud → src/cloud}/relay/endpoints.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/relay/endpoints.js +0 -0
- /package/dist/{cloud → src/cloud}/relay/health/index.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/relay/health/index.js +0 -0
- /package/dist/{cloud → src/cloud}/relay/stats/index.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/relay/stats/index.js +0 -0
- /package/dist/{cloud → src/cloud}/relay/sync/index.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/relay/sync/index.js +0 -0
- /package/dist/{cloud → src/cloud}/relay/usage/index.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/relay/usage/index.js +0 -0
- /package/dist/{cloud → src/cloud}/sponsors.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/sponsors.js +0 -0
- /package/dist/{cloud → src/cloud}/types.d.ts +0 -0
- /package/dist/{cloud → src/cloud}/types.js +0 -0
- /package/dist/{components → src/components}/index.d.ts +0 -0
- /package/dist/{components → src/components}/index.js +0 -0
- /package/dist/{core → src/core}/actors.d.ts +0 -0
- /package/dist/{core → src/core}/actors.js +0 -0
- /package/dist/{core → src/core}/component/generator.d.ts +0 -0
- /package/dist/{core → src/core}/engine.d.ts +0 -0
- /package/dist/{core → src/core}/engine.js +0 -0
- /package/dist/{core → src/core}/introspection.d.ts +0 -0
- /package/dist/{core → src/core}/introspection.js +0 -0
- /package/dist/{core → src/core}/logic/generator.d.ts +0 -0
- /package/dist/{core → src/core}/pluresdb/generator.d.ts +0 -0
- /package/dist/{core → src/core}/protocol.d.ts +0 -0
- /package/dist/{core → src/core}/protocol.js +0 -0
- /package/dist/{core → src/core}/rules.d.ts +0 -0
- /package/dist/{core → src/core}/rules.js +0 -0
- /package/dist/{core → src/core}/schema/loader.d.ts +0 -0
- /package/dist/{core → src/core}/schema/loader.js +0 -0
- /package/dist/{core → src/core}/schema/normalize.d.ts +0 -0
- /package/dist/{core → src/core}/schema/normalize.js +0 -0
- /package/dist/{core → src/core}/schema/types.d.ts +0 -0
- /package/dist/{core → src/core}/schema/types.js +0 -0
- /package/dist/{dsl → src/dsl}/index.d.ts +0 -0
- /package/dist/{dsl → src/dsl}/index.js +0 -0
- /package/dist/{dsl.d.ts → src/dsl.d.ts} +0 -0
- /package/dist/{dsl.js → src/dsl.js} +0 -0
- /package/dist/{examples → src/examples}/advanced-todo/index.d.ts +0 -0
- /package/dist/{examples → src/examples}/advanced-todo/index.js +0 -0
- /package/dist/{examples → src/examples}/auth-basic/index.d.ts +0 -0
- /package/dist/{examples → src/examples}/auth-basic/index.js +0 -0
- /package/dist/{examples → src/examples}/cart/index.d.ts +0 -0
- /package/dist/{examples → src/examples}/cart/index.js +0 -0
- /package/dist/{examples → src/examples}/hero-ecommerce/index.d.ts +0 -0
- /package/dist/{examples → src/examples}/hero-ecommerce/index.js +0 -0
- /package/dist/{examples → src/examples}/svelte-counter/index.d.ts +0 -0
- /package/dist/{examples → src/examples}/svelte-counter/index.js +0 -0
- /package/dist/{flows.d.ts → src/flows.d.ts} +0 -0
- /package/dist/{flows.js → src/flows.js} +0 -0
- /package/dist/{integrations → src/integrations}/svelte.d.ts +0 -0
- /package/dist/{integrations → src/integrations}/svelte.js +0 -0
- /package/dist/{registry.d.ts → src/registry.d.ts} +0 -0
- /package/dist/{registry.js → src/registry.js} +0 -0
- /package/dist/{step.d.ts → src/step.d.ts} +0 -0
- /package/dist/{step.js → src/step.js} +0 -0
- /package/dist/{types.d.ts → src/types.d.ts} +0 -0
- /package/dist/{types.js → src/types.js} +0 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
# Praxis Logic Engine
|
|
2
|
+
|
|
3
|
+
The Praxis Logic Engine is the computational core of every Praxis application. It provides a pure, functional approach to application logic using facts, events, rules, and constraints.
|
|
4
|
+
|
|
5
|
+
## Core Concepts
|
|
6
|
+
|
|
7
|
+
### Facts
|
|
8
|
+
|
|
9
|
+
Facts are typed propositions about your domain. They represent "what is true" or "what happened."
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { defineFact } from '@plures/praxis';
|
|
13
|
+
|
|
14
|
+
// Define a fact type
|
|
15
|
+
const UserLoggedIn = defineFact<'UserLoggedIn', { userId: string; timestamp: number }>('UserLoggedIn');
|
|
16
|
+
|
|
17
|
+
// Create a fact instance
|
|
18
|
+
const fact = UserLoggedIn.create({ userId: 'user-123', timestamp: Date.now() });
|
|
19
|
+
|
|
20
|
+
// Check if a value is this fact type
|
|
21
|
+
if (UserLoggedIn.is(someFact)) {
|
|
22
|
+
console.log(someFact.payload.userId);
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
#### Fact Properties
|
|
27
|
+
|
|
28
|
+
| Property | Type | Description |
|
|
29
|
+
|----------|------|-------------|
|
|
30
|
+
| `tag` | string | Unique identifier for the fact type |
|
|
31
|
+
| `payload` | object | Data associated with the fact |
|
|
32
|
+
| `timestamp` | number | When the fact was created |
|
|
33
|
+
| `metadata` | object | Optional additional metadata |
|
|
34
|
+
|
|
35
|
+
### Events
|
|
36
|
+
|
|
37
|
+
Events are temporally ordered facts that drive state changes. They represent user actions, external triggers, or system events.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { defineEvent } from '@plures/praxis';
|
|
41
|
+
|
|
42
|
+
// Define an event type
|
|
43
|
+
const Login = defineEvent<'LOGIN', { username: string; password: string }>('LOGIN');
|
|
44
|
+
|
|
45
|
+
// Create an event instance
|
|
46
|
+
const event = Login.create({ username: 'alice', password: 'secret' });
|
|
47
|
+
|
|
48
|
+
// Dispatch events to the engine
|
|
49
|
+
engine.dispatch([event]);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Rules
|
|
53
|
+
|
|
54
|
+
Rules are pure functions that produce facts from events and current state.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { defineRule } from '@plures/praxis';
|
|
58
|
+
|
|
59
|
+
const loginRule = defineRule<AuthContext>({
|
|
60
|
+
id: 'auth.login',
|
|
61
|
+
description: 'Process login and emit UserLoggedIn fact',
|
|
62
|
+
impl: (state, events) => {
|
|
63
|
+
const loginEvent = events.find(Login.is);
|
|
64
|
+
if (!loginEvent) return [];
|
|
65
|
+
|
|
66
|
+
// Validate credentials (pure logic only)
|
|
67
|
+
const user = state.context.users.find(u =>
|
|
68
|
+
u.username === loginEvent.payload.username
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (user) {
|
|
72
|
+
// Modify state (within the pure function)
|
|
73
|
+
state.context.currentUser = user;
|
|
74
|
+
|
|
75
|
+
// Return facts to emit
|
|
76
|
+
return [UserLoggedIn.create({
|
|
77
|
+
userId: user.id,
|
|
78
|
+
timestamp: Date.now()
|
|
79
|
+
})];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return [LoginFailed.create({
|
|
83
|
+
reason: 'Invalid credentials'
|
|
84
|
+
})];
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### Rule Properties
|
|
90
|
+
|
|
91
|
+
| Property | Type | Required | Description |
|
|
92
|
+
|----------|------|----------|-------------|
|
|
93
|
+
| `id` | string | Yes | Unique rule identifier |
|
|
94
|
+
| `description` | string | Yes | What the rule does |
|
|
95
|
+
| `impl` | function | Yes | Pure function implementation |
|
|
96
|
+
| `priority` | number | No | Execution order (higher = first) |
|
|
97
|
+
| `triggers` | string[] | No | Event types that activate this rule |
|
|
98
|
+
|
|
99
|
+
### Constraints
|
|
100
|
+
|
|
101
|
+
Constraints are invariants that must always hold true. They validate state after rules execute.
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { defineConstraint } from '@plures/praxis';
|
|
105
|
+
|
|
106
|
+
const positiveBalance = defineConstraint<BankContext>({
|
|
107
|
+
id: 'bank.positiveBalance',
|
|
108
|
+
description: 'Account balance must be non-negative',
|
|
109
|
+
check: (state) => state.context.balance >= 0,
|
|
110
|
+
errorMessage: 'Insufficient funds',
|
|
111
|
+
severity: 'error',
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Constraint Properties
|
|
116
|
+
|
|
117
|
+
| Property | Type | Required | Description |
|
|
118
|
+
|----------|------|----------|-------------|
|
|
119
|
+
| `id` | string | Yes | Unique constraint identifier |
|
|
120
|
+
| `description` | string | Yes | What the constraint ensures |
|
|
121
|
+
| `check` | function | Yes | Returns true if valid |
|
|
122
|
+
| `errorMessage` | string | Yes | Error when violated |
|
|
123
|
+
| `severity` | string | Yes | `error` or `warning` |
|
|
124
|
+
|
|
125
|
+
## Creating an Engine
|
|
126
|
+
|
|
127
|
+
### Basic Setup
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { createPraxisEngine, PraxisRegistry } from '@plures/praxis';
|
|
131
|
+
|
|
132
|
+
// Define your context type
|
|
133
|
+
interface AppContext {
|
|
134
|
+
count: number;
|
|
135
|
+
user: { id: string; name: string } | null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Create a registry
|
|
139
|
+
const registry = new PraxisRegistry<AppContext>();
|
|
140
|
+
|
|
141
|
+
// Register rules and constraints
|
|
142
|
+
registry.registerRule(myRule);
|
|
143
|
+
registry.registerConstraint(myConstraint);
|
|
144
|
+
|
|
145
|
+
// Create the engine
|
|
146
|
+
const engine = createPraxisEngine({
|
|
147
|
+
initialContext: { count: 0, user: null },
|
|
148
|
+
registry,
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Engine Options
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const engine = createPraxisEngine({
|
|
156
|
+
// Required: Initial application state
|
|
157
|
+
initialContext: { count: 0 },
|
|
158
|
+
|
|
159
|
+
// Required: Registry with rules and constraints
|
|
160
|
+
registry,
|
|
161
|
+
|
|
162
|
+
// Optional: Enable history for undo/redo
|
|
163
|
+
enableHistory: true,
|
|
164
|
+
maxHistorySize: 100,
|
|
165
|
+
|
|
166
|
+
// Optional: Custom reducer for state transitions
|
|
167
|
+
reducer: (state, event) => {
|
|
168
|
+
// Custom state transition logic
|
|
169
|
+
return state;
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
// Optional: Middleware
|
|
173
|
+
middleware: [
|
|
174
|
+
(state, events, next) => {
|
|
175
|
+
console.log('Before:', events);
|
|
176
|
+
const result = next(state, events);
|
|
177
|
+
console.log('After:', result);
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
],
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Processing Events
|
|
185
|
+
|
|
186
|
+
### Basic Dispatch
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Dispatch a single event
|
|
190
|
+
engine.dispatch([Increment.create({})]);
|
|
191
|
+
|
|
192
|
+
// Dispatch multiple events
|
|
193
|
+
engine.dispatch([
|
|
194
|
+
AddItem.create({ id: '1', name: 'Product' }),
|
|
195
|
+
UpdateQuantity.create({ id: '1', quantity: 2 }),
|
|
196
|
+
]);
|
|
197
|
+
|
|
198
|
+
// Get current state
|
|
199
|
+
const context = engine.getContext();
|
|
200
|
+
console.log(context);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Step Function
|
|
204
|
+
|
|
205
|
+
For more control, use the step function directly:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
const result = engine.step([Login.create({ username: 'alice', password: 'secret' })]);
|
|
209
|
+
|
|
210
|
+
console.log(result.state.context); // Updated context
|
|
211
|
+
console.log(result.state.facts); // Emitted facts
|
|
212
|
+
console.log(result.effects); // Side effects to execute
|
|
213
|
+
console.log(result.violations); // Constraint violations
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Step Result
|
|
217
|
+
|
|
218
|
+
| Property | Type | Description |
|
|
219
|
+
|----------|------|-------------|
|
|
220
|
+
| `state.context` | object | Updated application state |
|
|
221
|
+
| `state.facts` | array | Facts emitted by rules |
|
|
222
|
+
| `effects` | array | Side effects to execute |
|
|
223
|
+
| `violations` | array | Constraint violations |
|
|
224
|
+
|
|
225
|
+
## State Management
|
|
226
|
+
|
|
227
|
+
### Immutability
|
|
228
|
+
|
|
229
|
+
The engine maintains immutable state. Each step creates a new state:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
const state1 = engine.getState();
|
|
233
|
+
engine.dispatch([Increment.create({})]);
|
|
234
|
+
const state2 = engine.getState();
|
|
235
|
+
|
|
236
|
+
console.log(state1 === state2); // false
|
|
237
|
+
console.log(state1.context.count); // 0
|
|
238
|
+
console.log(state2.context.count); // 1
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Subscriptions
|
|
242
|
+
|
|
243
|
+
Subscribe to state changes:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
// Subscribe to all changes
|
|
247
|
+
const unsubscribe = engine.subscribe((state) => {
|
|
248
|
+
console.log('State changed:', state.context);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Later: unsubscribe
|
|
252
|
+
unsubscribe();
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### History and Undo/Redo
|
|
256
|
+
|
|
257
|
+
When history is enabled:
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
const engine = createPraxisEngine({
|
|
261
|
+
initialContext: { count: 0 },
|
|
262
|
+
registry,
|
|
263
|
+
enableHistory: true,
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
engine.dispatch([Increment.create({})]); // count: 1
|
|
267
|
+
engine.dispatch([Increment.create({})]); // count: 2
|
|
268
|
+
|
|
269
|
+
engine.undo(); // count: 1
|
|
270
|
+
engine.redo(); // count: 2
|
|
271
|
+
|
|
272
|
+
// Access history
|
|
273
|
+
const snapshots = engine.getSnapshots();
|
|
274
|
+
console.log(snapshots.length); // 3 (initial + 2 changes)
|
|
275
|
+
|
|
276
|
+
// Go to specific snapshot
|
|
277
|
+
engine.goToSnapshot(0); // count: 0
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Rule Execution
|
|
281
|
+
|
|
282
|
+
### Priority
|
|
283
|
+
|
|
284
|
+
Rules execute in priority order (highest first):
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
const highPriorityRule = defineRule({
|
|
288
|
+
id: 'important',
|
|
289
|
+
priority: 100, // Executes first
|
|
290
|
+
impl: (state, events) => { ... }
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const lowPriorityRule = defineRule({
|
|
294
|
+
id: 'less-important',
|
|
295
|
+
priority: 1, // Executes later
|
|
296
|
+
impl: (state, events) => { ... }
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Triggers
|
|
301
|
+
|
|
302
|
+
Rules can specify which events activate them:
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
const loginRule = defineRule({
|
|
306
|
+
id: 'auth.login',
|
|
307
|
+
triggers: ['LOGIN', 'OAUTH_CALLBACK'], // Only runs for these events
|
|
308
|
+
impl: (state, events) => { ... }
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Rule Chaining
|
|
313
|
+
|
|
314
|
+
Facts emitted by rules can trigger other rules:
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
// Rule 1: Login produces UserLoggedIn
|
|
318
|
+
const loginRule = defineRule({
|
|
319
|
+
id: 'auth.login',
|
|
320
|
+
triggers: ['LOGIN'],
|
|
321
|
+
impl: (state, events) => [UserLoggedIn.create({ userId: '123' })]
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Rule 2: UserLoggedIn triggers welcome notification
|
|
325
|
+
const welcomeRule = defineRule({
|
|
326
|
+
id: 'notify.welcome',
|
|
327
|
+
impl: (state, events) => {
|
|
328
|
+
// This runs after loginRule because facts are processed
|
|
329
|
+
const loggedIn = state.facts.find(f => f.tag === 'UserLoggedIn');
|
|
330
|
+
if (loggedIn) {
|
|
331
|
+
return [ShowNotification.create({ message: 'Welcome!' })];
|
|
332
|
+
}
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Constraint Checking
|
|
339
|
+
|
|
340
|
+
### Validation Flow
|
|
341
|
+
|
|
342
|
+
1. Events are dispatched
|
|
343
|
+
2. Rules execute and modify state
|
|
344
|
+
3. Constraints are checked
|
|
345
|
+
4. If violations occur, state can be rolled back
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
const result = engine.step([WithdrawMoney.create({ amount: 1000 })]);
|
|
349
|
+
|
|
350
|
+
if (result.violations.length > 0) {
|
|
351
|
+
console.log('Constraint violated:', result.violations[0].message);
|
|
352
|
+
// State was not applied
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Severity Levels
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
const softConstraint = defineConstraint({
|
|
360
|
+
id: 'warn.lowBalance',
|
|
361
|
+
severity: 'warning', // Allows state change, logs warning
|
|
362
|
+
check: (state) => state.context.balance > 100,
|
|
363
|
+
errorMessage: 'Balance is getting low',
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
const hardConstraint = defineConstraint({
|
|
367
|
+
id: 'error.overdraft',
|
|
368
|
+
severity: 'error', // Prevents state change
|
|
369
|
+
check: (state) => state.context.balance >= 0,
|
|
370
|
+
errorMessage: 'Insufficient funds',
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Effects and Side Effects
|
|
375
|
+
|
|
376
|
+
Rules return facts (pure data), but applications need side effects. Use the effects pattern:
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
const sendEmailRule = defineRule({
|
|
380
|
+
id: 'notify.email',
|
|
381
|
+
impl: (state, events) => {
|
|
382
|
+
const orderPlaced = events.find(e => e.tag === 'OrderPlaced');
|
|
383
|
+
if (orderPlaced) {
|
|
384
|
+
// Return an effect descriptor (not the actual side effect)
|
|
385
|
+
return [
|
|
386
|
+
EmailQueued.create({
|
|
387
|
+
to: state.context.user.email,
|
|
388
|
+
template: 'order-confirmation',
|
|
389
|
+
data: { orderId: orderPlaced.payload.orderId }
|
|
390
|
+
})
|
|
391
|
+
];
|
|
392
|
+
}
|
|
393
|
+
return [];
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// Execute effects after step
|
|
398
|
+
const result = engine.step([PlaceOrder.create({ ... })]);
|
|
399
|
+
for (const fact of result.state.facts) {
|
|
400
|
+
if (fact.tag === 'EmailQueued') {
|
|
401
|
+
await emailService.send(fact.payload);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Introspection
|
|
407
|
+
|
|
408
|
+
### Registry Introspection
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
// Get all registered rules
|
|
412
|
+
const rules = registry.getRules();
|
|
413
|
+
console.log(rules.map(r => r.id));
|
|
414
|
+
|
|
415
|
+
// Get all constraints
|
|
416
|
+
const constraints = registry.getConstraints();
|
|
417
|
+
|
|
418
|
+
// Get registry statistics
|
|
419
|
+
const stats = registry.getStats();
|
|
420
|
+
console.log(stats);
|
|
421
|
+
// { ruleCount: 5, constraintCount: 3, ... }
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### State Introspection
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
// Get current state
|
|
428
|
+
const state = engine.getState();
|
|
429
|
+
|
|
430
|
+
// Get context (application data)
|
|
431
|
+
const context = engine.getContext();
|
|
432
|
+
|
|
433
|
+
// Get facts (emitted by rules)
|
|
434
|
+
const facts = engine.getFacts();
|
|
435
|
+
|
|
436
|
+
// Get history (if enabled)
|
|
437
|
+
const snapshots = engine.getSnapshots();
|
|
438
|
+
const currentIndex = engine.getHistoryIndex();
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Advanced Patterns
|
|
442
|
+
|
|
443
|
+
### Actors
|
|
444
|
+
|
|
445
|
+
For isolated stateful units:
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
import { createActor, createActorSystem } from '@plures/praxis';
|
|
449
|
+
|
|
450
|
+
const counterActor = createActor(
|
|
451
|
+
'counter-1',
|
|
452
|
+
{ count: 0 },
|
|
453
|
+
counterStepFunction,
|
|
454
|
+
'counter'
|
|
455
|
+
);
|
|
456
|
+
|
|
457
|
+
const system = createActorSystem();
|
|
458
|
+
system.register(counterActor);
|
|
459
|
+
|
|
460
|
+
// Send to specific actor
|
|
461
|
+
system.send('counter-1', Increment.create({}));
|
|
462
|
+
|
|
463
|
+
// Broadcast to all actors
|
|
464
|
+
system.broadcast(Reset.create({}));
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Flows
|
|
468
|
+
|
|
469
|
+
For multi-step processes:
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
import { createFlow, advanceFlow } from '@plures/praxis';
|
|
473
|
+
|
|
474
|
+
const checkoutFlow = createFlow('checkout', [
|
|
475
|
+
{ id: 'cart', expectedEventType: 'REVIEW_CART' },
|
|
476
|
+
{ id: 'shipping', expectedEventType: 'ENTER_SHIPPING' },
|
|
477
|
+
{ id: 'payment', expectedEventType: 'PROCESS_PAYMENT' },
|
|
478
|
+
{ id: 'confirm', expectedEventType: 'CONFIRM_ORDER' },
|
|
479
|
+
]);
|
|
480
|
+
|
|
481
|
+
// Advance through the flow
|
|
482
|
+
const { flow, accepted } = advanceFlow(checkoutFlow, event);
|
|
483
|
+
if (flow.complete) {
|
|
484
|
+
console.log('Checkout complete!');
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Best Practices
|
|
489
|
+
|
|
490
|
+
### 1. Keep Rules Pure
|
|
491
|
+
|
|
492
|
+
Rules should have no side effects:
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
// ❌ Bad: Side effect in rule
|
|
496
|
+
const badRule = defineRule({
|
|
497
|
+
impl: (state, events) => {
|
|
498
|
+
fetch('/api/data'); // Side effect!
|
|
499
|
+
return [];
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
// ✅ Good: Return effect descriptor
|
|
504
|
+
const goodRule = defineRule({
|
|
505
|
+
impl: (state, events) => {
|
|
506
|
+
return [FetchDataRequested.create({ url: '/api/data' })];
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### 2. Use Descriptive IDs
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
// ❌ Bad
|
|
515
|
+
const rule1 = defineRule({ id: 'r1', ... });
|
|
516
|
+
|
|
517
|
+
// ✅ Good
|
|
518
|
+
const processLogin = defineRule({ id: 'auth.processLogin', ... });
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### 3. Leverage TypeScript
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
// Define your context type
|
|
525
|
+
interface AppContext {
|
|
526
|
+
user: User | null;
|
|
527
|
+
items: Item[];
|
|
528
|
+
settings: Settings;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// Rules are typed
|
|
532
|
+
const typedRule = defineRule<AppContext>({
|
|
533
|
+
impl: (state, events) => {
|
|
534
|
+
// TypeScript knows the shape of state.context
|
|
535
|
+
const user = state.context.user;
|
|
536
|
+
return [];
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### 4. Test Your Logic
|
|
542
|
+
|
|
543
|
+
```typescript
|
|
544
|
+
import { describe, it, expect } from 'vitest';
|
|
545
|
+
|
|
546
|
+
describe('Login Rule', () => {
|
|
547
|
+
it('should emit UserLoggedIn on valid credentials', () => {
|
|
548
|
+
const engine = createPraxisEngine({
|
|
549
|
+
initialContext: { users: [{ username: 'alice', id: '1' }] },
|
|
550
|
+
registry,
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
const result = engine.step([
|
|
554
|
+
Login.create({ username: 'alice', password: 'valid' })
|
|
555
|
+
]);
|
|
556
|
+
|
|
557
|
+
expect(result.state.facts).toContainEqual(
|
|
558
|
+
expect.objectContaining({ tag: 'UserLoggedIn' })
|
|
559
|
+
);
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
**Next:** [UI Generation](./ui-generation.md)
|