@plures/praxis 1.0.3 → 1.1.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/FRAMEWORK.md +55 -5
- package/README.md +162 -375
- package/core/codegen/docs-generator.ts +5 -2
- package/core/codegen/index.ts +1 -1
- package/core/db-adapter/index.ts +2 -2
- package/core/db-adapter/sync-engine.ts +17 -6
- package/core/logic-engine/engine.ts +1 -1
- package/core/logic-engine/index.ts +2 -2
- package/core/logic-engine/protocol.ts +1 -1
- package/core/logic-engine/psf-adapter.ts +8 -4
- package/core/logic-engine/rules.ts +1 -1
- package/core/schema-engine/compiler.ts +53 -11
- package/core/schema-engine/generator.ts +17 -7
- package/core/schema-engine/index.ts +2 -2
- package/core/schema-engine/psf.ts +12 -3
- package/core/schema-engine/types.ts +3 -11
- package/core/schema-engine/validator.ts +112 -22
- package/dist/browser/engine-BjdqxeXG.d.ts +333 -0
- package/dist/browser/index.d.ts +3004 -0
- package/dist/browser/index.js +2892 -0
- package/dist/{src → browser}/integrations/svelte.d.ts +19 -17
- package/dist/browser/integrations/svelte.js +298 -0
- package/dist/node/auth-STARLY7I.js +207 -0
- package/dist/node/build-Y7OT5VBF.js +144 -0
- package/dist/node/canvas-UERZHJYW.js +362 -0
- package/dist/node/chunk-DSDC2JWZ.js +256 -0
- package/dist/node/chunk-FXQZXAWF.js +175 -0
- package/dist/node/chunk-N5Y37EUV.js +202 -0
- package/dist/node/chunk-QGM4M3NI.js +37 -0
- package/dist/node/chunk-RJMWCNHR.js +175 -0
- package/dist/node/chunk-SRM3OPPM.js +404 -0
- package/dist/node/chunk-UATVJBNV.js +175 -0
- package/dist/node/chunk-UY7YEBE2.js +159 -0
- package/dist/node/chunk-XCY2VIFX.js +143 -0
- package/dist/node/chunk-YXH4Y7ZZ.js +349 -0
- package/dist/node/cli/index.cjs +215139 -0
- package/dist/node/cli/index.d.cts +1 -0
- package/dist/node/cli/index.d.ts +1 -0
- package/dist/node/cli/index.js +690 -0
- package/dist/node/cloud/index.cjs +1043 -0
- package/dist/node/cloud/index.d.cts +864 -0
- package/dist/node/cloud/index.d.ts +864 -0
- package/dist/node/cloud/index.js +456 -0
- package/dist/node/cloud-AXOK4PSN.js +212 -0
- package/dist/node/component.cjs +374 -0
- package/dist/node/component.d.cts +125 -0
- package/dist/{src/core/component/generator.d.ts → node/component.d.ts} +11 -8
- package/dist/node/component.js +9 -0
- package/dist/node/components/index.cjs +216 -0
- package/dist/node/components/index.d.cts +43 -0
- package/dist/{src → node}/components/index.d.ts +8 -8
- package/dist/node/components/index.js +7 -0
- package/dist/node/create-TRLSVCNQ.js +584 -0
- package/dist/node/dev-PMJZUYGE.js +65 -0
- package/dist/node/engine-1iqLe6_P.d.ts +214 -0
- package/dist/node/engine-CVJobhHm.d.cts +214 -0
- package/dist/node/index.cjs +3247 -0
- package/dist/node/index.d.cts +2579 -0
- package/dist/node/index.d.ts +2579 -0
- package/dist/node/index.js +2098 -0
- package/dist/node/integrations/svelte.cjs +330 -0
- package/dist/node/integrations/svelte.d.cts +309 -0
- package/dist/node/integrations/svelte.d.ts +309 -0
- package/dist/node/integrations/svelte.js +300 -0
- package/dist/node/orchestrate-737TCL5H.js +127 -0
- package/dist/{src/core/protocol.d.ts → node/protocol-Qek7ebBl.d.cts} +11 -10
- package/dist/node/protocol-Qek7ebBl.d.ts +122 -0
- package/dist/node/schema.cjs +200 -0
- package/dist/{src/core/schema/types.d.ts → node/schema.d.cts} +30 -29
- package/dist/node/schema.d.ts +371 -0
- package/dist/node/schema.js +9 -0
- package/dist/{src/runtime/terminal-adapter.d.ts → node/terminal-adapter-07HGftGQ.d.ts} +86 -11
- package/dist/node/terminal-adapter-XLtCjjb_.d.cts +231 -0
- package/dist/node/verify-QRYKRIDU.js +210960 -0
- package/docs/MONETIZATION.md +21 -16
- package/docs/REACTIVE_REDESIGN.md +132 -0
- package/docs/README.md +47 -36
- package/docs/SVELTE_INTEGRATION_STRATEGY.md +68 -0
- package/docs/TERMINAL_NODE.md +27 -24
- package/docs/core/building-extensions.md +58 -61
- package/docs/core/cli-usage.md +59 -59
- package/docs/core/code-canvas-sync.md +28 -16
- package/docs/core/logic-engine.md +77 -82
- package/docs/core/pluresdb-integration.md +29 -39
- package/docs/core/schema-model.md +66 -52
- package/docs/core/ui-generation.md +57 -49
- package/docs/core/what-is-praxis.md +32 -15
- package/docs/guides/canvas.md +21 -5
- package/docs/guides/getting-started.md +13 -7
- package/docs/guides/history-state-pattern.md +65 -51
- package/docs/guides/orchestration.md +46 -32
- package/docs/guides/parallel-state-pattern.md +56 -72
- package/docs/guides/svelte-integration.md +45 -53
- package/docs/tutorials/README.md +16 -0
- package/docs/tutorials/ecommerce-cart.md +177 -95
- package/docs/tutorials/first-app.md +26 -41
- package/docs/tutorials/form-builder.md +191 -138
- package/docs/tutorials/todo-pluresdb.md +71 -69
- package/package.json +58 -23
- package/src/__tests__/actors.test.ts +68 -68
- package/src/__tests__/billing.test.ts +32 -32
- package/src/__tests__/canvas-components.test.ts +94 -73
- package/src/__tests__/cli-create.test.ts +28 -28
- package/src/__tests__/cloud.test.ts +36 -36
- package/src/__tests__/code-canvas-integration.test.ts +132 -141
- package/src/__tests__/docs-generator.test.ts +3 -9
- package/src/__tests__/dsl.test.ts +58 -64
- package/src/__tests__/edge-cases.test.ts +106 -108
- package/src/__tests__/engine.test.ts +51 -25
- package/src/__tests__/generators.test.ts +42 -44
- package/src/__tests__/introspection.test.ts +104 -114
- package/src/__tests__/pluresdb.test.ts +189 -187
- package/src/__tests__/protocol.test.ts +15 -15
- package/src/__tests__/provisioning.test.ts +61 -61
- package/src/__tests__/schema.test.ts +7 -11
- package/src/__tests__/state-docs-integration.test.ts +162 -145
- package/src/__tests__/svelte-integration.test.ts +16 -19
- package/src/__tests__/tauri-integration.test.ts +149 -147
- package/src/__tests__/terminal-node.test.ts +12 -7
- package/src/__tests__/unum-integration.test.ts +68 -68
- package/src/adapters/cli.ts +21 -15
- package/src/cli/commands/auth.ts +82 -78
- package/src/cli/commands/build.ts +29 -27
- package/src/cli/commands/canvas.ts +338 -127
- package/src/cli/commands/cloud.ts +47 -47
- package/src/cli/commands/create.ts +59 -47
- package/src/cli/commands/dev.ts +12 -12
- package/src/cli/commands/generate.ts +29 -40
- package/src/cli/commands/orchestrate.ts +24 -24
- package/src/cli/commands/verify.ts +7 -8
- package/src/cli/index.ts +14 -10
- package/src/cloud/README.md +28 -15
- package/src/cloud/auth.ts +55 -70
- package/src/cloud/billing.ts +59 -58
- package/src/cloud/client.ts +29 -35
- package/src/cloud/index.ts +19 -40
- package/src/cloud/marketplace.ts +69 -78
- package/src/cloud/provisioning.ts +42 -51
- package/src/cloud/relay/endpoints.ts +30 -34
- package/src/cloud/relay/health/index.ts +1 -1
- package/src/cloud/relay/stats/index.ts +1 -1
- package/src/cloud/relay/sync/index.ts +1 -1
- package/src/cloud/relay/usage/index.ts +1 -1
- package/src/cloud/sponsors.ts +31 -34
- package/src/cloud/types.ts +4 -4
- package/src/components/README.md +1 -0
- package/src/components/index.ts +3 -4
- package/src/core/actors.ts +7 -7
- package/src/core/component/generator.ts +10 -28
- package/src/core/engine.ts +51 -24
- package/src/core/introspection.ts +37 -35
- package/src/core/logic/generator.ts +62 -62
- package/src/core/pluresdb/adapter.ts +8 -8
- package/src/core/pluresdb/generator.ts +39 -35
- package/src/core/pluresdb/index.ts +9 -12
- package/src/core/pluresdb/schema-registry.ts +22 -25
- package/src/core/pluresdb/store.ts +57 -57
- package/src/core/protocol.ts +14 -14
- package/src/core/reactive-engine.svelte.ts +65 -0
- package/src/core/reactive-engine.ts +67 -0
- package/src/core/rules.ts +4 -4
- package/src/core/schema/loader.common.ts +150 -0
- package/src/core/schema/loader.ts +19 -149
- package/src/core/schema/normalize.ts +34 -51
- package/src/core/schema/types.ts +47 -11
- package/src/dsl/index.ts +8 -8
- package/src/dsl.ts +11 -17
- package/src/examples/advanced-todo/README.md +58 -40
- package/src/examples/advanced-todo/index.ts +3 -3
- package/src/examples/auth-basic/index.ts +30 -30
- package/src/examples/cart/index.ts +50 -50
- package/src/examples/hero-ecommerce/index.ts +130 -157
- package/src/examples/svelte-counter/index.ts +22 -26
- package/src/flows.ts +6 -17
- package/src/index.browser.ts +204 -0
- package/src/index.ts +37 -42
- package/src/integrations/code-canvas.ts +237 -193
- package/src/integrations/pluresdb.ts +55 -35
- package/src/integrations/state-docs.ts +104 -104
- package/src/integrations/svelte.ts +35 -35
- package/src/integrations/tauri.ts +75 -73
- package/src/integrations/unum.ts +68 -61
- package/src/registry.ts +7 -14
- package/src/runtime/terminal-adapter.ts +31 -26
- package/src/step.ts +10 -16
- package/src/types.ts +1 -1
- package/templates/basic-app/README.md +6 -9
- package/templates/fullstack-app/README.md +10 -0
- package/dist/core/codegen/docs-generator.d.ts +0 -123
- package/dist/core/codegen/docs-generator.d.ts.map +0 -1
- package/dist/core/codegen/docs-generator.js +0 -674
- package/dist/core/codegen/docs-generator.js.map +0 -1
- package/dist/core/codegen/index.d.ts +0 -11
- package/dist/core/codegen/index.d.ts.map +0 -1
- package/dist/core/codegen/index.js +0 -13
- package/dist/core/codegen/index.js.map +0 -1
- package/dist/core/codegen/ts-generator.d.ts +0 -8
- package/dist/core/codegen/ts-generator.d.ts.map +0 -1
- package/dist/core/codegen/ts-generator.js +0 -8
- package/dist/core/codegen/ts-generator.js.map +0 -1
- package/dist/core/db-adapter/index.d.ts +0 -18
- package/dist/core/db-adapter/index.d.ts.map +0 -1
- package/dist/core/db-adapter/index.js +0 -23
- package/dist/core/db-adapter/index.js.map +0 -1
- package/dist/core/db-adapter/sync-engine.d.ts +0 -180
- package/dist/core/db-adapter/sync-engine.d.ts.map +0 -1
- package/dist/core/db-adapter/sync-engine.js +0 -342
- package/dist/core/db-adapter/sync-engine.js.map +0 -1
- package/dist/core/logic-engine/engine.d.ts +0 -8
- package/dist/core/logic-engine/engine.d.ts.map +0 -1
- package/dist/core/logic-engine/engine.js +0 -8
- package/dist/core/logic-engine/engine.js.map +0 -1
- package/dist/core/logic-engine/index.d.ts +0 -16
- package/dist/core/logic-engine/index.d.ts.map +0 -1
- package/dist/core/logic-engine/index.js +0 -16
- package/dist/core/logic-engine/index.js.map +0 -1
- package/dist/core/logic-engine/protocol.d.ts +0 -7
- package/dist/core/logic-engine/protocol.d.ts.map +0 -1
- package/dist/core/logic-engine/protocol.js +0 -7
- package/dist/core/logic-engine/protocol.js.map +0 -1
- package/dist/core/logic-engine/psf-adapter.d.ts +0 -88
- package/dist/core/logic-engine/psf-adapter.d.ts.map +0 -1
- package/dist/core/logic-engine/psf-adapter.js +0 -207
- package/dist/core/logic-engine/psf-adapter.js.map +0 -1
- package/dist/core/logic-engine/rules.d.ts +0 -7
- package/dist/core/logic-engine/rules.d.ts.map +0 -1
- package/dist/core/logic-engine/rules.js +0 -7
- package/dist/core/logic-engine/rules.js.map +0 -1
- package/dist/core/schema-engine/compiler.d.ts +0 -198
- package/dist/core/schema-engine/compiler.d.ts.map +0 -1
- package/dist/core/schema-engine/compiler.js +0 -262
- package/dist/core/schema-engine/compiler.js.map +0 -1
- package/dist/core/schema-engine/generator.d.ts +0 -115
- package/dist/core/schema-engine/generator.d.ts.map +0 -1
- package/dist/core/schema-engine/generator.js +0 -506
- package/dist/core/schema-engine/generator.js.map +0 -1
- package/dist/core/schema-engine/index.d.ts +0 -18
- package/dist/core/schema-engine/index.d.ts.map +0 -1
- package/dist/core/schema-engine/index.js +0 -18
- package/dist/core/schema-engine/index.js.map +0 -1
- package/dist/core/schema-engine/psf.d.ts +0 -612
- package/dist/core/schema-engine/psf.d.ts.map +0 -1
- package/dist/core/schema-engine/psf.js +0 -45
- package/dist/core/schema-engine/psf.js.map +0 -1
- package/dist/core/schema-engine/types.d.ts +0 -10
- package/dist/core/schema-engine/types.d.ts.map +0 -1
- package/dist/core/schema-engine/types.js +0 -7
- package/dist/core/schema-engine/types.js.map +0 -1
- package/dist/core/schema-engine/validator.d.ts +0 -140
- package/dist/core/schema-engine/validator.d.ts.map +0 -1
- package/dist/core/schema-engine/validator.js +0 -407
- package/dist/core/schema-engine/validator.js.map +0 -1
- package/dist/src/adapters/cli.d.ts +0 -43
- package/dist/src/adapters/cli.d.ts.map +0 -1
- package/dist/src/adapters/cli.js +0 -126
- package/dist/src/adapters/cli.js.map +0 -1
- package/dist/src/cli/commands/auth.d.ts +0 -26
- package/dist/src/cli/commands/auth.d.ts.map +0 -1
- package/dist/src/cli/commands/auth.js +0 -233
- package/dist/src/cli/commands/auth.js.map +0 -1
- package/dist/src/cli/commands/build.d.ts +0 -23
- package/dist/src/cli/commands/build.d.ts.map +0 -1
- package/dist/src/cli/commands/build.js +0 -162
- package/dist/src/cli/commands/build.js.map +0 -1
- package/dist/src/cli/commands/canvas.d.ts +0 -23
- package/dist/src/cli/commands/canvas.d.ts.map +0 -1
- package/dist/src/cli/commands/canvas.js +0 -215
- package/dist/src/cli/commands/canvas.js.map +0 -1
- package/dist/src/cli/commands/cloud.d.ts +0 -27
- package/dist/src/cli/commands/cloud.d.ts.map +0 -1
- package/dist/src/cli/commands/cloud.js +0 -232
- package/dist/src/cli/commands/cloud.js.map +0 -1
- package/dist/src/cli/commands/create.d.ts +0 -21
- package/dist/src/cli/commands/create.d.ts.map +0 -1
- package/dist/src/cli/commands/create.js +0 -621
- package/dist/src/cli/commands/create.js.map +0 -1
- package/dist/src/cli/commands/dev.d.ts +0 -21
- package/dist/src/cli/commands/dev.d.ts.map +0 -1
- package/dist/src/cli/commands/dev.js +0 -71
- package/dist/src/cli/commands/dev.js.map +0 -1
- package/dist/src/cli/commands/generate.d.ts +0 -25
- package/dist/src/cli/commands/generate.d.ts.map +0 -1
- package/dist/src/cli/commands/generate.js +0 -168
- package/dist/src/cli/commands/generate.js.map +0 -1
- package/dist/src/cli/commands/orchestrate.d.ts +0 -44
- package/dist/src/cli/commands/orchestrate.d.ts.map +0 -1
- package/dist/src/cli/commands/orchestrate.js +0 -150
- package/dist/src/cli/commands/orchestrate.js.map +0 -1
- package/dist/src/cli/commands/verify.d.ts +0 -10
- package/dist/src/cli/commands/verify.d.ts.map +0 -1
- package/dist/src/cli/commands/verify.js +0 -39
- package/dist/src/cli/commands/verify.js.map +0 -1
- package/dist/src/cli/index.d.ts +0 -8
- package/dist/src/cli/index.d.ts.map +0 -1
- package/dist/src/cli/index.js +0 -226
- package/dist/src/cli/index.js.map +0 -1
- package/dist/src/cloud/auth.d.ts +0 -51
- package/dist/src/cloud/auth.d.ts.map +0 -1
- package/dist/src/cloud/auth.js +0 -194
- package/dist/src/cloud/auth.js.map +0 -1
- package/dist/src/cloud/billing.d.ts +0 -184
- package/dist/src/cloud/billing.d.ts.map +0 -1
- package/dist/src/cloud/billing.js +0 -179
- package/dist/src/cloud/billing.js.map +0 -1
- package/dist/src/cloud/client.d.ts +0 -39
- package/dist/src/cloud/client.d.ts.map +0 -1
- package/dist/src/cloud/client.js +0 -176
- package/dist/src/cloud/client.js.map +0 -1
- package/dist/src/cloud/index.d.ts +0 -44
- package/dist/src/cloud/index.d.ts.map +0 -1
- package/dist/src/cloud/index.js +0 -44
- package/dist/src/cloud/index.js.map +0 -1
- package/dist/src/cloud/marketplace.d.ts +0 -166
- package/dist/src/cloud/marketplace.d.ts.map +0 -1
- package/dist/src/cloud/marketplace.js +0 -159
- package/dist/src/cloud/marketplace.js.map +0 -1
- package/dist/src/cloud/provisioning.d.ts +0 -110
- package/dist/src/cloud/provisioning.d.ts.map +0 -1
- package/dist/src/cloud/provisioning.js +0 -148
- package/dist/src/cloud/provisioning.js.map +0 -1
- package/dist/src/cloud/relay/endpoints.d.ts +0 -62
- package/dist/src/cloud/relay/endpoints.d.ts.map +0 -1
- package/dist/src/cloud/relay/endpoints.js +0 -217
- package/dist/src/cloud/relay/endpoints.js.map +0 -1
- package/dist/src/cloud/relay/health/index.d.ts +0 -5
- package/dist/src/cloud/relay/health/index.d.ts.map +0 -1
- package/dist/src/cloud/relay/health/index.js +0 -9
- package/dist/src/cloud/relay/health/index.js.map +0 -1
- package/dist/src/cloud/relay/stats/index.d.ts +0 -5
- package/dist/src/cloud/relay/stats/index.d.ts.map +0 -1
- package/dist/src/cloud/relay/stats/index.js +0 -9
- package/dist/src/cloud/relay/stats/index.js.map +0 -1
- package/dist/src/cloud/relay/sync/index.d.ts +0 -5
- package/dist/src/cloud/relay/sync/index.d.ts.map +0 -1
- package/dist/src/cloud/relay/sync/index.js +0 -9
- package/dist/src/cloud/relay/sync/index.js.map +0 -1
- package/dist/src/cloud/relay/usage/index.d.ts +0 -5
- package/dist/src/cloud/relay/usage/index.d.ts.map +0 -1
- package/dist/src/cloud/relay/usage/index.js +0 -9
- package/dist/src/cloud/relay/usage/index.js.map +0 -1
- package/dist/src/cloud/sponsors.d.ts +0 -81
- package/dist/src/cloud/sponsors.d.ts.map +0 -1
- package/dist/src/cloud/sponsors.js +0 -130
- package/dist/src/cloud/sponsors.js.map +0 -1
- package/dist/src/cloud/types.d.ts +0 -169
- package/dist/src/cloud/types.d.ts.map +0 -1
- package/dist/src/cloud/types.js +0 -7
- package/dist/src/cloud/types.js.map +0 -1
- package/dist/src/components/index.d.ts.map +0 -1
- package/dist/src/components/index.js +0 -17
- package/dist/src/components/index.js.map +0 -1
- package/dist/src/core/actors.d.ts +0 -95
- package/dist/src/core/actors.d.ts.map +0 -1
- package/dist/src/core/actors.js +0 -158
- package/dist/src/core/actors.js.map +0 -1
- package/dist/src/core/component/generator.d.ts.map +0 -1
- package/dist/src/core/component/generator.js +0 -349
- package/dist/src/core/component/generator.js.map +0 -1
- package/dist/src/core/engine.d.ts +0 -92
- package/dist/src/core/engine.d.ts.map +0 -1
- package/dist/src/core/engine.js +0 -199
- package/dist/src/core/engine.js.map +0 -1
- package/dist/src/core/introspection.d.ts +0 -141
- package/dist/src/core/introspection.d.ts.map +0 -1
- package/dist/src/core/introspection.js +0 -208
- package/dist/src/core/introspection.js.map +0 -1
- package/dist/src/core/logic/generator.d.ts +0 -76
- package/dist/src/core/logic/generator.d.ts.map +0 -1
- package/dist/src/core/logic/generator.js +0 -370
- package/dist/src/core/logic/generator.js.map +0 -1
- package/dist/src/core/pluresdb/adapter.d.ts +0 -72
- package/dist/src/core/pluresdb/adapter.d.ts.map +0 -1
- package/dist/src/core/pluresdb/adapter.js +0 -73
- package/dist/src/core/pluresdb/adapter.js.map +0 -1
- package/dist/src/core/pluresdb/generator.d.ts +0 -58
- package/dist/src/core/pluresdb/generator.d.ts.map +0 -1
- package/dist/src/core/pluresdb/generator.js +0 -191
- package/dist/src/core/pluresdb/generator.js.map +0 -1
- package/dist/src/core/pluresdb/index.d.ts +0 -15
- package/dist/src/core/pluresdb/index.d.ts.map +0 -1
- package/dist/src/core/pluresdb/index.js +0 -11
- package/dist/src/core/pluresdb/index.js.map +0 -1
- package/dist/src/core/pluresdb/schema-registry.d.ts +0 -104
- package/dist/src/core/pluresdb/schema-registry.d.ts.map +0 -1
- package/dist/src/core/pluresdb/schema-registry.js +0 -130
- package/dist/src/core/pluresdb/schema-registry.js.map +0 -1
- package/dist/src/core/pluresdb/store.d.ts +0 -199
- package/dist/src/core/pluresdb/store.d.ts.map +0 -1
- package/dist/src/core/pluresdb/store.js +0 -344
- package/dist/src/core/pluresdb/store.js.map +0 -1
- package/dist/src/core/protocol.d.ts.map +0 -1
- package/dist/src/core/protocol.js +0 -46
- package/dist/src/core/protocol.js.map +0 -1
- package/dist/src/core/rules.d.ts +0 -120
- package/dist/src/core/rules.d.ts.map +0 -1
- package/dist/src/core/rules.js +0 -81
- package/dist/src/core/rules.js.map +0 -1
- package/dist/src/core/schema/loader.d.ts +0 -47
- package/dist/src/core/schema/loader.d.ts.map +0 -1
- package/dist/src/core/schema/loader.js +0 -189
- package/dist/src/core/schema/loader.js.map +0 -1
- package/dist/src/core/schema/normalize.d.ts +0 -72
- package/dist/src/core/schema/normalize.d.ts.map +0 -1
- package/dist/src/core/schema/normalize.js +0 -190
- package/dist/src/core/schema/normalize.js.map +0 -1
- package/dist/src/core/schema/types.d.ts.map +0 -1
- package/dist/src/core/schema/types.js +0 -161
- package/dist/src/core/schema/types.js.map +0 -1
- package/dist/src/dsl/index.d.ts +0 -152
- package/dist/src/dsl/index.d.ts.map +0 -1
- package/dist/src/dsl/index.js +0 -132
- package/dist/src/dsl/index.js.map +0 -1
- package/dist/src/dsl.d.ts +0 -124
- package/dist/src/dsl.d.ts.map +0 -1
- package/dist/src/dsl.js +0 -130
- package/dist/src/dsl.js.map +0 -1
- package/dist/src/examples/advanced-todo/index.d.ts +0 -55
- package/dist/src/examples/advanced-todo/index.d.ts.map +0 -1
- package/dist/src/examples/advanced-todo/index.js +0 -222
- package/dist/src/examples/advanced-todo/index.js.map +0 -1
- package/dist/src/examples/auth-basic/index.d.ts +0 -17
- package/dist/src/examples/auth-basic/index.d.ts.map +0 -1
- package/dist/src/examples/auth-basic/index.js +0 -122
- package/dist/src/examples/auth-basic/index.js.map +0 -1
- package/dist/src/examples/cart/index.d.ts +0 -19
- package/dist/src/examples/cart/index.d.ts.map +0 -1
- package/dist/src/examples/cart/index.js +0 -202
- package/dist/src/examples/cart/index.js.map +0 -1
- package/dist/src/examples/hero-ecommerce/index.d.ts +0 -39
- package/dist/src/examples/hero-ecommerce/index.d.ts.map +0 -1
- package/dist/src/examples/hero-ecommerce/index.js +0 -506
- package/dist/src/examples/hero-ecommerce/index.js.map +0 -1
- package/dist/src/examples/svelte-counter/index.d.ts +0 -31
- package/dist/src/examples/svelte-counter/index.d.ts.map +0 -1
- package/dist/src/examples/svelte-counter/index.js +0 -123
- package/dist/src/examples/svelte-counter/index.js.map +0 -1
- package/dist/src/flows.d.ts +0 -125
- package/dist/src/flows.d.ts.map +0 -1
- package/dist/src/flows.js +0 -160
- package/dist/src/flows.js.map +0 -1
- package/dist/src/index.d.ts +0 -77
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -64
- package/dist/src/index.js.map +0 -1
- package/dist/src/integrations/code-canvas.d.ts +0 -265
- package/dist/src/integrations/code-canvas.d.ts.map +0 -1
- package/dist/src/integrations/code-canvas.js +0 -451
- package/dist/src/integrations/code-canvas.js.map +0 -1
- package/dist/src/integrations/pluresdb.d.ts +0 -117
- package/dist/src/integrations/pluresdb.d.ts.map +0 -1
- package/dist/src/integrations/pluresdb.js +0 -117
- package/dist/src/integrations/pluresdb.js.map +0 -1
- package/dist/src/integrations/state-docs.d.ts +0 -191
- package/dist/src/integrations/state-docs.d.ts.map +0 -1
- package/dist/src/integrations/state-docs.js +0 -515
- package/dist/src/integrations/state-docs.js.map +0 -1
- package/dist/src/integrations/svelte.d.ts.map +0 -1
- package/dist/src/integrations/svelte.js +0 -447
- package/dist/src/integrations/svelte.js.map +0 -1
- package/dist/src/integrations/tauri.d.ts +0 -360
- package/dist/src/integrations/tauri.d.ts.map +0 -1
- package/dist/src/integrations/tauri.js +0 -278
- package/dist/src/integrations/tauri.js.map +0 -1
- package/dist/src/integrations/unum.d.ts +0 -159
- package/dist/src/integrations/unum.d.ts.map +0 -1
- package/dist/src/integrations/unum.js +0 -240
- package/dist/src/integrations/unum.js.map +0 -1
- package/dist/src/registry.d.ts +0 -94
- package/dist/src/registry.d.ts.map +0 -1
- package/dist/src/registry.js +0 -181
- package/dist/src/registry.js.map +0 -1
- package/dist/src/runtime/terminal-adapter.d.ts.map +0 -1
- package/dist/src/runtime/terminal-adapter.js +0 -239
- package/dist/src/runtime/terminal-adapter.js.map +0 -1
- package/dist/src/step.d.ts +0 -34
- package/dist/src/step.d.ts.map +0 -1
- package/dist/src/step.js +0 -111
- package/dist/src/step.js.map +0 -1
- package/dist/src/types.d.ts +0 -63
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -6
- package/dist/src/types.js.map +0 -1
- package/dist/tools/ast-analyzer/src/ast-analyzer.d.ts +0 -8
- package/dist/tools/ast-analyzer/src/ast-analyzer.d.ts.map +0 -1
- package/dist/tools/ast-analyzer/src/ast-analyzer.js +0 -119
- package/dist/tools/ast-analyzer/src/ast-analyzer.js.map +0 -1
- package/dist/tools/cli/commands/index.d.ts +0 -7
- package/dist/tools/cli/commands/index.d.ts.map +0 -1
- package/dist/tools/cli/commands/index.js +0 -7
- package/dist/tools/cli/commands/index.js.map +0 -1
- package/dist/tools/cli/index.d.ts +0 -8
- package/dist/tools/cli/index.d.ts.map +0 -1
- package/dist/tools/cli/index.js +0 -9
- package/dist/tools/cli/index.js.map +0 -1
- package/dist/tools/watcher/index.d.ts +0 -105
- package/dist/tools/watcher/index.d.ts.map +0 -1
- package/dist/tools/watcher/index.js +0 -213
- package/dist/tools/watcher/index.js.map +0 -1
- package/dist/ui/canvas/canvas-projection.d.ts +0 -78
- package/dist/ui/canvas/canvas-projection.d.ts.map +0 -1
- package/dist/ui/canvas/canvas-projection.js +0 -416
- package/dist/ui/canvas/canvas-projection.js.map +0 -1
- package/dist/ui/canvas/canvas-state.d.ts +0 -200
- package/dist/ui/canvas/canvas-state.d.ts.map +0 -1
- package/dist/ui/canvas/canvas-state.js +0 -464
- package/dist/ui/canvas/canvas-state.js.map +0 -1
- package/dist/ui/canvas/components/index.d.ts +0 -95
- package/dist/ui/canvas/components/index.d.ts.map +0 -1
- package/dist/ui/canvas/components/index.js +0 -19
- package/dist/ui/canvas/components/index.js.map +0 -1
- package/dist/ui/canvas/index.d.ts +0 -32
- package/dist/ui/canvas/index.d.ts.map +0 -1
- package/dist/ui/canvas/index.js +0 -32
- package/dist/ui/canvas/index.js.map +0 -1
- package/dist/ui/canvas-inspector/src/server.d.ts +0 -2
- package/dist/ui/canvas-inspector/src/server.d.ts.map +0 -1
- package/dist/ui/canvas-inspector/src/server.js +0 -248
- package/dist/ui/canvas-inspector/src/server.js.map +0 -1
- package/dist/ui/canvas-inspector/src/verify-fsm-implementation.d.ts +0 -5
- package/dist/ui/canvas-inspector/src/verify-fsm-implementation.d.ts.map +0 -1
- package/dist/ui/canvas-inspector/src/verify-fsm-implementation.js +0 -58
- package/dist/ui/canvas-inspector/src/verify-fsm-implementation.js.map +0 -1
- package/dist/ui/svelte-generator/index.d.ts +0 -9
- package/dist/ui/svelte-generator/index.d.ts.map +0 -1
- package/dist/ui/svelte-generator/index.js +0 -11
- package/dist/ui/svelte-generator/index.js.map +0 -1
- package/dist/ui/svelte-generator/psf-generator.d.ts +0 -128
- package/dist/ui/svelte-generator/psf-generator.d.ts.map +0 -1
- package/dist/ui/svelte-generator/psf-generator.js +0 -506
- package/dist/ui/svelte-generator/psf-generator.js.map +0 -1
|
@@ -0,0 +1,2892 @@
|
|
|
1
|
+
// src/core/protocol.ts
|
|
2
|
+
var PRAXIS_PROTOCOL_VERSION = "1.0.0";
|
|
3
|
+
|
|
4
|
+
// src/core/rules.ts
|
|
5
|
+
var PraxisRegistry = class {
|
|
6
|
+
rules = /* @__PURE__ */ new Map();
|
|
7
|
+
constraints = /* @__PURE__ */ new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Register a rule
|
|
10
|
+
*/
|
|
11
|
+
registerRule(descriptor) {
|
|
12
|
+
if (this.rules.has(descriptor.id)) {
|
|
13
|
+
throw new Error(`Rule with id "${descriptor.id}" already registered`);
|
|
14
|
+
}
|
|
15
|
+
this.rules.set(descriptor.id, descriptor);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Register a constraint
|
|
19
|
+
*/
|
|
20
|
+
registerConstraint(descriptor) {
|
|
21
|
+
if (this.constraints.has(descriptor.id)) {
|
|
22
|
+
throw new Error(`Constraint with id "${descriptor.id}" already registered`);
|
|
23
|
+
}
|
|
24
|
+
this.constraints.set(descriptor.id, descriptor);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Register a module (all its rules and constraints)
|
|
28
|
+
*/
|
|
29
|
+
registerModule(module) {
|
|
30
|
+
for (const rule of module.rules) {
|
|
31
|
+
this.registerRule(rule);
|
|
32
|
+
}
|
|
33
|
+
for (const constraint of module.constraints) {
|
|
34
|
+
this.registerConstraint(constraint);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get a rule by ID
|
|
39
|
+
*/
|
|
40
|
+
getRule(id) {
|
|
41
|
+
return this.rules.get(id);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get a constraint by ID
|
|
45
|
+
*/
|
|
46
|
+
getConstraint(id) {
|
|
47
|
+
return this.constraints.get(id);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get all registered rule IDs
|
|
51
|
+
*/
|
|
52
|
+
getRuleIds() {
|
|
53
|
+
return Array.from(this.rules.keys());
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get all registered constraint IDs
|
|
57
|
+
*/
|
|
58
|
+
getConstraintIds() {
|
|
59
|
+
return Array.from(this.constraints.keys());
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get all rules
|
|
63
|
+
*/
|
|
64
|
+
getAllRules() {
|
|
65
|
+
return Array.from(this.rules.values());
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get all constraints
|
|
69
|
+
*/
|
|
70
|
+
getAllConstraints() {
|
|
71
|
+
return Array.from(this.constraints.values());
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/core/engine.ts
|
|
76
|
+
function safeClone(value) {
|
|
77
|
+
if (value === null || typeof value !== "object") {
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
if (typeof globalThis.structuredClone === "function") {
|
|
81
|
+
try {
|
|
82
|
+
return globalThis.structuredClone(value);
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
return [...value];
|
|
88
|
+
}
|
|
89
|
+
return { ...value };
|
|
90
|
+
}
|
|
91
|
+
var LogicEngine = class {
|
|
92
|
+
state;
|
|
93
|
+
registry;
|
|
94
|
+
constructor(options) {
|
|
95
|
+
this.registry = options.registry;
|
|
96
|
+
this.state = {
|
|
97
|
+
context: options.initialContext,
|
|
98
|
+
facts: options.initialFacts ?? [],
|
|
99
|
+
meta: options.initialMeta ?? {},
|
|
100
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get the current state (immutable copy)
|
|
105
|
+
*/
|
|
106
|
+
getState() {
|
|
107
|
+
return {
|
|
108
|
+
context: safeClone(this.state.context),
|
|
109
|
+
facts: [...this.state.facts],
|
|
110
|
+
meta: this.state.meta ? safeClone(this.state.meta) : void 0,
|
|
111
|
+
protocolVersion: this.state.protocolVersion
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get the current context
|
|
116
|
+
*/
|
|
117
|
+
getContext() {
|
|
118
|
+
return safeClone(this.state.context);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get current facts
|
|
122
|
+
*/
|
|
123
|
+
getFacts() {
|
|
124
|
+
return [...this.state.facts];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Process events through the engine.
|
|
128
|
+
* Applies all registered rules and checks all registered constraints.
|
|
129
|
+
*
|
|
130
|
+
* @param events Events to process
|
|
131
|
+
* @returns Result with new state and diagnostics
|
|
132
|
+
*/
|
|
133
|
+
step(events) {
|
|
134
|
+
const config = {
|
|
135
|
+
ruleIds: this.registry.getRuleIds(),
|
|
136
|
+
constraintIds: this.registry.getConstraintIds()
|
|
137
|
+
};
|
|
138
|
+
return this.stepWithConfig(events, config);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Process events with specific rule and constraint configuration.
|
|
142
|
+
*
|
|
143
|
+
* @param events Events to process
|
|
144
|
+
* @param config Step configuration
|
|
145
|
+
* @returns Result with new state and diagnostics
|
|
146
|
+
*/
|
|
147
|
+
stepWithConfig(events, config) {
|
|
148
|
+
const diagnostics = [];
|
|
149
|
+
let newState = { ...this.state };
|
|
150
|
+
const newFacts = [];
|
|
151
|
+
for (const ruleId of config.ruleIds) {
|
|
152
|
+
const rule = this.registry.getRule(ruleId);
|
|
153
|
+
if (!rule) {
|
|
154
|
+
diagnostics.push({
|
|
155
|
+
kind: "rule-error",
|
|
156
|
+
message: `Rule "${ruleId}" not found in registry`,
|
|
157
|
+
data: { ruleId }
|
|
158
|
+
});
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const ruleFacts = rule.impl(newState, events);
|
|
163
|
+
newFacts.push(...ruleFacts);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
diagnostics.push({
|
|
166
|
+
kind: "rule-error",
|
|
167
|
+
message: `Error executing rule "${ruleId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
168
|
+
data: { ruleId, error }
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
newState = {
|
|
173
|
+
...newState,
|
|
174
|
+
facts: [...newState.facts, ...newFacts]
|
|
175
|
+
};
|
|
176
|
+
for (const constraintId of config.constraintIds) {
|
|
177
|
+
const constraint = this.registry.getConstraint(constraintId);
|
|
178
|
+
if (!constraint) {
|
|
179
|
+
diagnostics.push({
|
|
180
|
+
kind: "constraint-violation",
|
|
181
|
+
message: `Constraint "${constraintId}" not found in registry`,
|
|
182
|
+
data: { constraintId }
|
|
183
|
+
});
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const result = constraint.impl(newState);
|
|
188
|
+
if (result === false) {
|
|
189
|
+
diagnostics.push({
|
|
190
|
+
kind: "constraint-violation",
|
|
191
|
+
message: `Constraint "${constraintId}" violated`,
|
|
192
|
+
data: { constraintId, description: constraint.description }
|
|
193
|
+
});
|
|
194
|
+
} else if (typeof result === "string") {
|
|
195
|
+
diagnostics.push({
|
|
196
|
+
kind: "constraint-violation",
|
|
197
|
+
message: result,
|
|
198
|
+
data: { constraintId, description: constraint.description }
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
diagnostics.push({
|
|
203
|
+
kind: "constraint-violation",
|
|
204
|
+
message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
205
|
+
data: { constraintId, error }
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
this.state = newState;
|
|
210
|
+
return {
|
|
211
|
+
state: newState,
|
|
212
|
+
diagnostics
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Update the context directly (for exceptional cases).
|
|
217
|
+
* Generally, context should be updated through rules.
|
|
218
|
+
*
|
|
219
|
+
* @param updater Function that produces new context from old context
|
|
220
|
+
*/
|
|
221
|
+
updateContext(updater) {
|
|
222
|
+
this.state = {
|
|
223
|
+
...this.state,
|
|
224
|
+
context: updater(this.state.context)
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Add facts directly (for exceptional cases).
|
|
229
|
+
* Generally, facts should be added through rules.
|
|
230
|
+
*
|
|
231
|
+
* @param facts Facts to add
|
|
232
|
+
*/
|
|
233
|
+
addFacts(facts) {
|
|
234
|
+
this.state = {
|
|
235
|
+
...this.state,
|
|
236
|
+
facts: [...this.state.facts, ...facts]
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Clear all facts
|
|
241
|
+
*/
|
|
242
|
+
clearFacts() {
|
|
243
|
+
this.state = {
|
|
244
|
+
...this.state,
|
|
245
|
+
facts: []
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Reset the engine to initial state
|
|
250
|
+
*/
|
|
251
|
+
reset(options) {
|
|
252
|
+
this.state = {
|
|
253
|
+
context: options.initialContext,
|
|
254
|
+
facts: options.initialFacts ?? [],
|
|
255
|
+
meta: options.initialMeta ?? {},
|
|
256
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
function createPraxisEngine(options) {
|
|
261
|
+
return new LogicEngine(options);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/core/reactive-engine.svelte.ts
|
|
265
|
+
import * as $ from "svelte/internal/client";
|
|
266
|
+
var ReactiveLogicEngine = class {
|
|
267
|
+
#state = (
|
|
268
|
+
// The single source of truth, reactive by default
|
|
269
|
+
// We use $state.raw for things that shouldn't be deeply reactive if needed,
|
|
270
|
+
// but for context we usually want deep reactivity.
|
|
271
|
+
$.state($.proxy({ context: {}, facts: [], meta: {} }))
|
|
272
|
+
);
|
|
273
|
+
get state() {
|
|
274
|
+
return $.get(this.#state);
|
|
275
|
+
}
|
|
276
|
+
set state(value) {
|
|
277
|
+
$.set(this.#state, value, true);
|
|
278
|
+
}
|
|
279
|
+
constructor(options) {
|
|
280
|
+
this.state.context = options.initialContext;
|
|
281
|
+
this.state.facts = options.initialFacts ?? [];
|
|
282
|
+
this.state.meta = options.initialMeta ?? {};
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Access the reactive context directly.
|
|
286
|
+
* Consumers can use this in $derived() or $effect().
|
|
287
|
+
*/
|
|
288
|
+
get context() {
|
|
289
|
+
return this.state.context;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Access the reactive facts list.
|
|
293
|
+
*/
|
|
294
|
+
get facts() {
|
|
295
|
+
return this.state.facts;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Apply a mutation to the state.
|
|
299
|
+
* This is the "Action" or "Rule" equivalent.
|
|
300
|
+
*
|
|
301
|
+
* @param mutator A function that receives the state and modifies it.
|
|
302
|
+
*/
|
|
303
|
+
apply(mutator) {
|
|
304
|
+
mutator(this.state);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Access the reactive meta.
|
|
308
|
+
*/
|
|
309
|
+
get meta() {
|
|
310
|
+
return this.state.meta;
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// src/core/actors.ts
|
|
315
|
+
var ActorManager = class {
|
|
316
|
+
actors = /* @__PURE__ */ new Map();
|
|
317
|
+
activeActors = /* @__PURE__ */ new Set();
|
|
318
|
+
engine = null;
|
|
319
|
+
/**
|
|
320
|
+
* Register an actor
|
|
321
|
+
*/
|
|
322
|
+
register(actor) {
|
|
323
|
+
if (this.actors.has(actor.id)) {
|
|
324
|
+
throw new Error(`Actor with id "${actor.id}" already registered`);
|
|
325
|
+
}
|
|
326
|
+
this.actors.set(actor.id, actor);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Unregister an actor
|
|
330
|
+
*/
|
|
331
|
+
unregister(actorId) {
|
|
332
|
+
if (this.activeActors.has(actorId)) {
|
|
333
|
+
throw new Error(`Cannot unregister active actor "${actorId}". Stop it first.`);
|
|
334
|
+
}
|
|
335
|
+
this.actors.delete(actorId);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Attach the actor manager to an engine
|
|
339
|
+
*/
|
|
340
|
+
attachEngine(engine) {
|
|
341
|
+
this.engine = engine;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Start an actor
|
|
345
|
+
*/
|
|
346
|
+
async start(actorId) {
|
|
347
|
+
const actor = this.actors.get(actorId);
|
|
348
|
+
if (!actor) {
|
|
349
|
+
throw new Error(`Actor "${actorId}" not found`);
|
|
350
|
+
}
|
|
351
|
+
if (this.activeActors.has(actorId)) {
|
|
352
|
+
throw new Error(`Actor "${actorId}" is already started`);
|
|
353
|
+
}
|
|
354
|
+
if (!this.engine) {
|
|
355
|
+
throw new Error("Actor manager not attached to an engine");
|
|
356
|
+
}
|
|
357
|
+
this.activeActors.add(actorId);
|
|
358
|
+
if (actor.onStart) {
|
|
359
|
+
await actor.onStart(this.engine);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Stop an actor
|
|
364
|
+
*/
|
|
365
|
+
async stop(actorId) {
|
|
366
|
+
const actor = this.actors.get(actorId);
|
|
367
|
+
if (!actor) {
|
|
368
|
+
throw new Error(`Actor "${actorId}" not found`);
|
|
369
|
+
}
|
|
370
|
+
if (!this.activeActors.has(actorId)) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
this.activeActors.delete(actorId);
|
|
374
|
+
if (actor.onStop) {
|
|
375
|
+
await actor.onStop();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Start all registered actors
|
|
380
|
+
*/
|
|
381
|
+
async startAll() {
|
|
382
|
+
const actorIds = Array.from(this.actors.keys());
|
|
383
|
+
for (const actorId of actorIds) {
|
|
384
|
+
if (!this.activeActors.has(actorId)) {
|
|
385
|
+
await this.start(actorId);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Stop all active actors
|
|
391
|
+
*/
|
|
392
|
+
async stopAll() {
|
|
393
|
+
const activeIds = Array.from(this.activeActors);
|
|
394
|
+
for (const actorId of activeIds) {
|
|
395
|
+
await this.stop(actorId);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Notify active actors of a state change
|
|
400
|
+
*/
|
|
401
|
+
async notifyStateChange(state2) {
|
|
402
|
+
if (!this.engine) {
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const promises = [];
|
|
406
|
+
for (const actorId of this.activeActors) {
|
|
407
|
+
const actor = this.actors.get(actorId);
|
|
408
|
+
if (actor?.onStateChange) {
|
|
409
|
+
const result = actor.onStateChange(state2, this.engine);
|
|
410
|
+
if (result instanceof Promise) {
|
|
411
|
+
promises.push(result);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
await Promise.all(promises);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Get all registered actor IDs
|
|
419
|
+
*/
|
|
420
|
+
getActorIds() {
|
|
421
|
+
return Array.from(this.actors.keys());
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Get all active actor IDs
|
|
425
|
+
*/
|
|
426
|
+
getActiveActorIds() {
|
|
427
|
+
return Array.from(this.activeActors);
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Check if an actor is active
|
|
431
|
+
*/
|
|
432
|
+
isActive(actorId) {
|
|
433
|
+
return this.activeActors.has(actorId);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
function createTimerActor(id, intervalMs, createEvent) {
|
|
437
|
+
let timerId = null;
|
|
438
|
+
return {
|
|
439
|
+
id,
|
|
440
|
+
description: `Timer actor (${intervalMs}ms) - ${id}`,
|
|
441
|
+
onStart: (engine) => {
|
|
442
|
+
timerId = setInterval(() => {
|
|
443
|
+
engine.step([createEvent()]);
|
|
444
|
+
}, intervalMs);
|
|
445
|
+
},
|
|
446
|
+
onStop: () => {
|
|
447
|
+
if (timerId) {
|
|
448
|
+
clearInterval(timerId);
|
|
449
|
+
timerId = null;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// src/core/introspection.ts
|
|
456
|
+
var RegistryIntrospector = class {
|
|
457
|
+
constructor(registry) {
|
|
458
|
+
this.registry = registry;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Get basic statistics about the registry
|
|
462
|
+
*/
|
|
463
|
+
getStats() {
|
|
464
|
+
return {
|
|
465
|
+
ruleCount: this.registry.getRuleIds().length,
|
|
466
|
+
constraintCount: this.registry.getConstraintIds().length,
|
|
467
|
+
moduleCount: 0,
|
|
468
|
+
// Modules are flattened in registry
|
|
469
|
+
rulesById: this.registry.getRuleIds(),
|
|
470
|
+
constraintsById: this.registry.getConstraintIds()
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Generate a JSON schema representation of the registry
|
|
475
|
+
*/
|
|
476
|
+
generateSchema(protocolVersion) {
|
|
477
|
+
const rules = this.registry.getAllRules().map((rule) => ({
|
|
478
|
+
id: rule.id,
|
|
479
|
+
description: rule.description,
|
|
480
|
+
type: "rule",
|
|
481
|
+
meta: rule.meta
|
|
482
|
+
}));
|
|
483
|
+
const constraints = this.registry.getAllConstraints().map((constraint) => ({
|
|
484
|
+
id: constraint.id,
|
|
485
|
+
description: constraint.description,
|
|
486
|
+
type: "constraint",
|
|
487
|
+
meta: constraint.meta
|
|
488
|
+
}));
|
|
489
|
+
return {
|
|
490
|
+
protocolVersion,
|
|
491
|
+
rules,
|
|
492
|
+
constraints,
|
|
493
|
+
meta: {
|
|
494
|
+
ruleCount: rules.length,
|
|
495
|
+
constraintCount: constraints.length
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Generate a graph representation of the registry
|
|
501
|
+
*
|
|
502
|
+
* This creates nodes for rules and constraints.
|
|
503
|
+
* Edges can be inferred from metadata if rules/constraints
|
|
504
|
+
* document their dependencies.
|
|
505
|
+
*/
|
|
506
|
+
generateGraph() {
|
|
507
|
+
const nodes = [];
|
|
508
|
+
const edges = [];
|
|
509
|
+
for (const rule of this.registry.getAllRules()) {
|
|
510
|
+
nodes.push({
|
|
511
|
+
id: rule.id,
|
|
512
|
+
type: "rule",
|
|
513
|
+
description: rule.description,
|
|
514
|
+
meta: rule.meta
|
|
515
|
+
});
|
|
516
|
+
if (rule.meta?.dependsOn) {
|
|
517
|
+
const deps = Array.isArray(rule.meta.dependsOn) ? rule.meta.dependsOn : [rule.meta.dependsOn];
|
|
518
|
+
for (const dep of deps) {
|
|
519
|
+
edges.push({
|
|
520
|
+
from: String(dep),
|
|
521
|
+
to: rule.id,
|
|
522
|
+
type: "depends-on"
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
for (const constraint of this.registry.getAllConstraints()) {
|
|
528
|
+
nodes.push({
|
|
529
|
+
id: constraint.id,
|
|
530
|
+
type: "constraint",
|
|
531
|
+
description: constraint.description,
|
|
532
|
+
meta: constraint.meta
|
|
533
|
+
});
|
|
534
|
+
if (constraint.meta?.constrains) {
|
|
535
|
+
const targets = Array.isArray(constraint.meta.constrains) ? constraint.meta.constrains : [constraint.meta.constrains];
|
|
536
|
+
for (const target of targets) {
|
|
537
|
+
edges.push({
|
|
538
|
+
from: constraint.id,
|
|
539
|
+
to: String(target),
|
|
540
|
+
type: "constrains"
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return {
|
|
546
|
+
nodes,
|
|
547
|
+
edges,
|
|
548
|
+
meta: {
|
|
549
|
+
nodeCount: nodes.length,
|
|
550
|
+
ruleCount: nodes.filter((n) => n.type === "rule").length,
|
|
551
|
+
constraintCount: nodes.filter((n) => n.type === "constraint").length
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Export graph in DOT format (Graphviz)
|
|
557
|
+
*
|
|
558
|
+
* This can be rendered with Graphviz tools or online services.
|
|
559
|
+
*/
|
|
560
|
+
exportDOT() {
|
|
561
|
+
const graph = this.generateGraph();
|
|
562
|
+
const lines = [];
|
|
563
|
+
lines.push("digraph PraxisRegistry {");
|
|
564
|
+
lines.push(" rankdir=TB;");
|
|
565
|
+
lines.push(" node [shape=box, style=rounded];");
|
|
566
|
+
lines.push("");
|
|
567
|
+
for (const node of graph.nodes) {
|
|
568
|
+
const shape = node.type === "rule" ? "box" : "diamond";
|
|
569
|
+
const color = node.type === "rule" ? "lightblue" : "lightcoral";
|
|
570
|
+
const label = `${node.id}\\n${node.description}`;
|
|
571
|
+
lines.push(
|
|
572
|
+
` "${node.id}" [label="${label}", shape=${shape}, style=filled, fillcolor=${color}];`
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
lines.push("");
|
|
576
|
+
for (const edge of graph.edges) {
|
|
577
|
+
const style = edge.type === "constrains" ? "dashed" : "solid";
|
|
578
|
+
lines.push(` "${edge.from}" -> "${edge.to}" [label="${edge.type}", style=${style}];`);
|
|
579
|
+
}
|
|
580
|
+
lines.push("}");
|
|
581
|
+
return lines.join("\n");
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Export graph in Mermaid format
|
|
585
|
+
*
|
|
586
|
+
* Mermaid is a markdown-friendly diagramming language.
|
|
587
|
+
*/
|
|
588
|
+
exportMermaid() {
|
|
589
|
+
const graph = this.generateGraph();
|
|
590
|
+
const lines = [];
|
|
591
|
+
lines.push("graph TB");
|
|
592
|
+
for (const node of graph.nodes) {
|
|
593
|
+
const shape = node.type === "rule" ? "[" : "{";
|
|
594
|
+
const endShape = node.type === "rule" ? "]" : "}";
|
|
595
|
+
const label = `${node.id}<br/>${node.description}`;
|
|
596
|
+
lines.push(` ${node.id}${shape}"${label}"${endShape}`);
|
|
597
|
+
}
|
|
598
|
+
lines.push("");
|
|
599
|
+
for (const edge of graph.edges) {
|
|
600
|
+
const arrow = edge.type === "constrains" ? "-.->|constrains|" : "-->|" + edge.type + "|";
|
|
601
|
+
lines.push(` ${edge.from} ${arrow} ${edge.to}`);
|
|
602
|
+
}
|
|
603
|
+
return lines.join("\n");
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Get detailed information about a specific rule
|
|
607
|
+
*/
|
|
608
|
+
getRuleInfo(ruleId) {
|
|
609
|
+
return this.registry.getRule(ruleId);
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Get detailed information about a specific constraint
|
|
613
|
+
*/
|
|
614
|
+
getConstraintInfo(constraintId) {
|
|
615
|
+
return this.registry.getConstraint(constraintId);
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Search for rules by description text
|
|
619
|
+
*/
|
|
620
|
+
searchRules(query) {
|
|
621
|
+
const lowerQuery = query.toLowerCase();
|
|
622
|
+
return this.registry.getAllRules().filter(
|
|
623
|
+
(rule) => rule.id.toLowerCase().includes(lowerQuery) || rule.description.toLowerCase().includes(lowerQuery)
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Search for constraints by description text
|
|
628
|
+
*/
|
|
629
|
+
searchConstraints(query) {
|
|
630
|
+
const lowerQuery = query.toLowerCase();
|
|
631
|
+
return this.registry.getAllConstraints().filter(
|
|
632
|
+
(constraint) => constraint.id.toLowerCase().includes(lowerQuery) || constraint.description.toLowerCase().includes(lowerQuery)
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
function createIntrospector(registry) {
|
|
637
|
+
return new RegistryIntrospector(registry);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// src/dsl/index.ts
|
|
641
|
+
function defineFact(tag) {
|
|
642
|
+
return {
|
|
643
|
+
tag,
|
|
644
|
+
create(payload) {
|
|
645
|
+
return { tag, payload };
|
|
646
|
+
},
|
|
647
|
+
is(fact) {
|
|
648
|
+
return fact.tag === tag;
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
function defineEvent(tag) {
|
|
653
|
+
return {
|
|
654
|
+
tag,
|
|
655
|
+
create(payload) {
|
|
656
|
+
return { tag, payload };
|
|
657
|
+
},
|
|
658
|
+
is(event) {
|
|
659
|
+
return event.tag === tag;
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
function defineRule(options) {
|
|
664
|
+
return {
|
|
665
|
+
id: options.id,
|
|
666
|
+
description: options.description,
|
|
667
|
+
impl: options.impl,
|
|
668
|
+
meta: options.meta
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
function defineConstraint(options) {
|
|
672
|
+
return {
|
|
673
|
+
id: options.id,
|
|
674
|
+
description: options.description,
|
|
675
|
+
impl: options.impl,
|
|
676
|
+
meta: options.meta
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
function defineModule(options) {
|
|
680
|
+
return {
|
|
681
|
+
rules: options.rules ?? [],
|
|
682
|
+
constraints: options.constraints ?? [],
|
|
683
|
+
meta: options.meta
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function filterEvents(events, definition) {
|
|
687
|
+
return events.filter(definition.is);
|
|
688
|
+
}
|
|
689
|
+
function filterFacts(facts, definition) {
|
|
690
|
+
return facts.filter(definition.is);
|
|
691
|
+
}
|
|
692
|
+
function findEvent(events, definition) {
|
|
693
|
+
return events.find(definition.is);
|
|
694
|
+
}
|
|
695
|
+
function findFact(facts, definition) {
|
|
696
|
+
return facts.find(definition.is);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/core/schema/types.ts
|
|
700
|
+
function validateSchema(schema) {
|
|
701
|
+
const errors = [];
|
|
702
|
+
if (!schema.version) {
|
|
703
|
+
errors.push({ path: "version", message: "Schema version is required" });
|
|
704
|
+
}
|
|
705
|
+
if (!schema.name) {
|
|
706
|
+
errors.push({ path: "name", message: "Schema name is required" });
|
|
707
|
+
}
|
|
708
|
+
if (schema.models) {
|
|
709
|
+
schema.models.forEach((model, index) => {
|
|
710
|
+
if (!model.name) {
|
|
711
|
+
errors.push({
|
|
712
|
+
path: `models[${index}].name`,
|
|
713
|
+
message: "Model name is required"
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
if (!model.fields || model.fields.length === 0) {
|
|
717
|
+
errors.push({
|
|
718
|
+
path: `models[${index}].fields`,
|
|
719
|
+
message: "Model must have at least one field"
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
if (schema.components) {
|
|
725
|
+
schema.components.forEach((component, index) => {
|
|
726
|
+
if (!component.name) {
|
|
727
|
+
errors.push({
|
|
728
|
+
path: `components[${index}].name`,
|
|
729
|
+
message: "Component name is required"
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
if (!component.type) {
|
|
733
|
+
errors.push({
|
|
734
|
+
path: `components[${index}].type`,
|
|
735
|
+
message: "Component type is required"
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
if (schema.logic) {
|
|
741
|
+
schema.logic.forEach((logic, logicIndex) => {
|
|
742
|
+
if (logic.facts) {
|
|
743
|
+
logic.facts.forEach((fact, factIndex) => {
|
|
744
|
+
if (!fact.tag) {
|
|
745
|
+
errors.push({
|
|
746
|
+
path: `logic[${logicIndex}].facts[${factIndex}].tag`,
|
|
747
|
+
message: "Fact tag is required"
|
|
748
|
+
});
|
|
749
|
+
} else if (!isValidIdentifier(fact.tag)) {
|
|
750
|
+
errors.push({
|
|
751
|
+
path: `logic[${logicIndex}].facts[${factIndex}].tag`,
|
|
752
|
+
message: `Fact tag "${fact.tag}" is not a valid JavaScript identifier. Use only letters, numbers, underscores, and dollar signs, and do not start with a number.`
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
if (logic.events) {
|
|
758
|
+
logic.events.forEach((event, eventIndex) => {
|
|
759
|
+
if (!event.tag) {
|
|
760
|
+
errors.push({
|
|
761
|
+
path: `logic[${logicIndex}].events[${eventIndex}].tag`,
|
|
762
|
+
message: "Event tag is required"
|
|
763
|
+
});
|
|
764
|
+
} else if (!isValidIdentifier(event.tag)) {
|
|
765
|
+
errors.push({
|
|
766
|
+
path: `logic[${logicIndex}].events[${eventIndex}].tag`,
|
|
767
|
+
message: `Event tag "${event.tag}" is not a valid JavaScript identifier. Use only letters, numbers, underscores, and dollar signs, and do not start with a number.`
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
if (schema.orchestration?.nodes) {
|
|
775
|
+
schema.orchestration.nodes.forEach((node, index) => {
|
|
776
|
+
if (!node.id) {
|
|
777
|
+
errors.push({
|
|
778
|
+
path: `orchestration.nodes[${index}].id`,
|
|
779
|
+
message: "Node id is required"
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
if (!node.type) {
|
|
783
|
+
errors.push({
|
|
784
|
+
path: `orchestration.nodes[${index}].type`,
|
|
785
|
+
message: "Node type is required"
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
if (node.type === "terminal" && node.props) {
|
|
789
|
+
const props = node.props;
|
|
790
|
+
if (props.inputMode && !["text", "widget"].includes(props.inputMode)) {
|
|
791
|
+
errors.push({
|
|
792
|
+
path: `orchestration.nodes[${index}].props.inputMode`,
|
|
793
|
+
message: 'Terminal node inputMode must be "text" or "widget"'
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
if (props.history && !Array.isArray(props.history)) {
|
|
797
|
+
errors.push({
|
|
798
|
+
path: `orchestration.nodes[${index}].props.history`,
|
|
799
|
+
message: "Terminal node history must be an array"
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
return {
|
|
806
|
+
valid: errors.length === 0,
|
|
807
|
+
errors
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
function isValidIdentifier(str) {
|
|
811
|
+
const identifierRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
812
|
+
const reservedKeywords = [
|
|
813
|
+
"break",
|
|
814
|
+
"case",
|
|
815
|
+
"catch",
|
|
816
|
+
"class",
|
|
817
|
+
"const",
|
|
818
|
+
"continue",
|
|
819
|
+
"debugger",
|
|
820
|
+
"default",
|
|
821
|
+
"delete",
|
|
822
|
+
"do",
|
|
823
|
+
"else",
|
|
824
|
+
"export",
|
|
825
|
+
"extends",
|
|
826
|
+
"finally",
|
|
827
|
+
"for",
|
|
828
|
+
"function",
|
|
829
|
+
"if",
|
|
830
|
+
"import",
|
|
831
|
+
"in",
|
|
832
|
+
"instanceof",
|
|
833
|
+
"new",
|
|
834
|
+
"return",
|
|
835
|
+
"super",
|
|
836
|
+
"switch",
|
|
837
|
+
"this",
|
|
838
|
+
"throw",
|
|
839
|
+
"try",
|
|
840
|
+
"typeof",
|
|
841
|
+
"var",
|
|
842
|
+
"void",
|
|
843
|
+
"while",
|
|
844
|
+
"with",
|
|
845
|
+
"yield",
|
|
846
|
+
"let",
|
|
847
|
+
"static",
|
|
848
|
+
"enum",
|
|
849
|
+
"await",
|
|
850
|
+
"implements",
|
|
851
|
+
"interface",
|
|
852
|
+
"package",
|
|
853
|
+
"private",
|
|
854
|
+
"protected",
|
|
855
|
+
"public"
|
|
856
|
+
];
|
|
857
|
+
return identifierRegex.test(str) && !reservedKeywords.includes(str);
|
|
858
|
+
}
|
|
859
|
+
function createSchemaTemplate(name) {
|
|
860
|
+
return {
|
|
861
|
+
version: "1.0.0",
|
|
862
|
+
name,
|
|
863
|
+
description: `Schema for ${name}`,
|
|
864
|
+
models: [],
|
|
865
|
+
components: [],
|
|
866
|
+
logic: []
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// src/core/schema/loader.common.ts
|
|
871
|
+
import { load as yamlLoad } from "js-yaml";
|
|
872
|
+
function createSchema(name) {
|
|
873
|
+
return {
|
|
874
|
+
version: "1.0.0",
|
|
875
|
+
name,
|
|
876
|
+
description: `Schema for ${name}`,
|
|
877
|
+
models: [],
|
|
878
|
+
components: [],
|
|
879
|
+
logic: []
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
function loadSchemaFromJson(json, options = {}) {
|
|
883
|
+
const errors = [];
|
|
884
|
+
try {
|
|
885
|
+
const schema = JSON.parse(json);
|
|
886
|
+
let validation;
|
|
887
|
+
if (options.validate !== false) {
|
|
888
|
+
validation = validateSchema(schema);
|
|
889
|
+
if (!validation.valid) {
|
|
890
|
+
errors.push("Schema validation failed:");
|
|
891
|
+
validation.errors.forEach((error) => {
|
|
892
|
+
errors.push(` ${error.path}: ${error.message}`);
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
return {
|
|
897
|
+
schema,
|
|
898
|
+
validation,
|
|
899
|
+
errors
|
|
900
|
+
};
|
|
901
|
+
} catch (error) {
|
|
902
|
+
if (error instanceof Error) {
|
|
903
|
+
errors.push(`Failed to parse JSON: ${error.message}`);
|
|
904
|
+
} else {
|
|
905
|
+
errors.push("Failed to parse JSON: Unknown error");
|
|
906
|
+
}
|
|
907
|
+
return { errors };
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
function loadSchemaFromYaml(yaml, options = {}) {
|
|
911
|
+
const errors = [];
|
|
912
|
+
try {
|
|
913
|
+
const schema = yamlLoad(yaml);
|
|
914
|
+
let validation;
|
|
915
|
+
if (options.validate !== false) {
|
|
916
|
+
validation = validateSchema(schema);
|
|
917
|
+
if (!validation.valid) {
|
|
918
|
+
errors.push("Schema validation failed:");
|
|
919
|
+
validation.errors.forEach((error) => {
|
|
920
|
+
errors.push(` ${error.path}: ${error.message}`);
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return {
|
|
925
|
+
schema,
|
|
926
|
+
validation,
|
|
927
|
+
errors
|
|
928
|
+
};
|
|
929
|
+
} catch (error) {
|
|
930
|
+
if (error instanceof Error) {
|
|
931
|
+
errors.push(`Failed to parse YAML: ${error.message}`);
|
|
932
|
+
} else {
|
|
933
|
+
errors.push("Failed to parse YAML: Unknown error");
|
|
934
|
+
}
|
|
935
|
+
return { errors };
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
function validateForGeneration(schema) {
|
|
939
|
+
const errors = [];
|
|
940
|
+
if (!schema.models || schema.models.length === 0) {
|
|
941
|
+
errors.push("Schema must define at least one model for generation");
|
|
942
|
+
}
|
|
943
|
+
schema.models?.forEach((model, index) => {
|
|
944
|
+
if (!model.fields || model.fields.length === 0) {
|
|
945
|
+
errors.push(`Model "${model.name}" at index ${index} must have at least one field`);
|
|
946
|
+
}
|
|
947
|
+
model.fields?.forEach((field, fieldIndex) => {
|
|
948
|
+
if (!field.name) {
|
|
949
|
+
errors.push(`Field at index ${fieldIndex} in model "${model.name}" must have a name`);
|
|
950
|
+
}
|
|
951
|
+
if (!field.type) {
|
|
952
|
+
errors.push(`Field "${field.name}" in model "${model.name}" must have a type`);
|
|
953
|
+
}
|
|
954
|
+
});
|
|
955
|
+
});
|
|
956
|
+
return {
|
|
957
|
+
valid: errors.length === 0,
|
|
958
|
+
errors: errors.map((message) => ({ path: "schema", message }))
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// src/core/pluresdb/store.ts
|
|
963
|
+
var PRAXIS_PATHS = {
|
|
964
|
+
/** Base path for all Praxis data */
|
|
965
|
+
BASE: "/_praxis",
|
|
966
|
+
/** Path for facts storage */
|
|
967
|
+
FACTS: "/_praxis/facts",
|
|
968
|
+
/** Path for events storage */
|
|
969
|
+
EVENTS: "/_praxis/events",
|
|
970
|
+
/** Path for schema registry */
|
|
971
|
+
SCHEMAS: "/_praxis/schemas"
|
|
972
|
+
};
|
|
973
|
+
function getFactPath(factTag, id) {
|
|
974
|
+
if (id) {
|
|
975
|
+
return `${PRAXIS_PATHS.FACTS}/${factTag}/${id}`;
|
|
976
|
+
}
|
|
977
|
+
return `${PRAXIS_PATHS.FACTS}/${factTag}`;
|
|
978
|
+
}
|
|
979
|
+
function getEventPath(eventTag) {
|
|
980
|
+
return `${PRAXIS_PATHS.EVENTS}/${eventTag}`;
|
|
981
|
+
}
|
|
982
|
+
function generateId() {
|
|
983
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
984
|
+
}
|
|
985
|
+
var defaultErrorHandler = (ruleId, error) => {
|
|
986
|
+
if (typeof process !== "undefined" && true) {
|
|
987
|
+
console.error(`Error executing rule "${ruleId}":`, error);
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
var PraxisDBStore = class {
|
|
991
|
+
db;
|
|
992
|
+
registry;
|
|
993
|
+
context;
|
|
994
|
+
subscriptions = [];
|
|
995
|
+
factWatchers = /* @__PURE__ */ new Map();
|
|
996
|
+
onRuleError;
|
|
997
|
+
constructor(options) {
|
|
998
|
+
this.db = options.db;
|
|
999
|
+
this.registry = options.registry;
|
|
1000
|
+
this.context = options.initialContext ?? {};
|
|
1001
|
+
this.onRuleError = options.onRuleError ?? defaultErrorHandler;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Store a fact in PluresDB
|
|
1005
|
+
*
|
|
1006
|
+
* Facts are stored under `/_praxis/facts/<factTag>/<id>`
|
|
1007
|
+
* If no id is provided in the payload, a timestamp-based id is used.
|
|
1008
|
+
*
|
|
1009
|
+
* @param fact The fact to store
|
|
1010
|
+
* @returns Promise that resolves when the fact is stored
|
|
1011
|
+
*/
|
|
1012
|
+
async storeFact(fact) {
|
|
1013
|
+
const constraintResult = await this.checkConstraints([fact]);
|
|
1014
|
+
if (!constraintResult.valid) {
|
|
1015
|
+
throw new Error(`Constraint violation: ${constraintResult.errors.join(", ")}`);
|
|
1016
|
+
}
|
|
1017
|
+
await this.persistFact(fact);
|
|
1018
|
+
await this.triggerRules([fact]);
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Store multiple facts in PluresDB
|
|
1022
|
+
*
|
|
1023
|
+
* @param facts The facts to store
|
|
1024
|
+
*/
|
|
1025
|
+
async storeFacts(facts) {
|
|
1026
|
+
const constraintResult = await this.checkConstraints(facts);
|
|
1027
|
+
if (!constraintResult.valid) {
|
|
1028
|
+
throw new Error(`Constraint violation: ${constraintResult.errors.join(", ")}`);
|
|
1029
|
+
}
|
|
1030
|
+
for (const fact of facts) {
|
|
1031
|
+
await this.persistFact(fact);
|
|
1032
|
+
}
|
|
1033
|
+
await this.triggerRules(facts);
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Internal method to persist a fact without constraint checking
|
|
1037
|
+
* Used by both storeFact and derived fact storage
|
|
1038
|
+
*/
|
|
1039
|
+
async persistFact(fact) {
|
|
1040
|
+
const payload = fact.payload;
|
|
1041
|
+
const id = payload?.id ?? generateId();
|
|
1042
|
+
const path = getFactPath(fact.tag, id);
|
|
1043
|
+
await this.db.set(path, fact);
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* Get a fact by tag and id
|
|
1047
|
+
*
|
|
1048
|
+
* @param factTag The fact type tag
|
|
1049
|
+
* @param id The fact id
|
|
1050
|
+
* @returns The fact or undefined if not found
|
|
1051
|
+
*/
|
|
1052
|
+
async getFact(factTag, id) {
|
|
1053
|
+
const path = getFactPath(factTag, id);
|
|
1054
|
+
return this.db.get(path);
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Append an event to the event stream
|
|
1058
|
+
*
|
|
1059
|
+
* Events are stored as append-only streams under `/_praxis/events/<eventTag>`
|
|
1060
|
+
*
|
|
1061
|
+
* @param event The event to append
|
|
1062
|
+
*/
|
|
1063
|
+
async appendEvent(event) {
|
|
1064
|
+
const path = getEventPath(event.tag);
|
|
1065
|
+
const existingEvents = await this.db.get(path) ?? [];
|
|
1066
|
+
const entry = {
|
|
1067
|
+
event,
|
|
1068
|
+
timestamp: Date.now(),
|
|
1069
|
+
sequence: existingEvents.length
|
|
1070
|
+
};
|
|
1071
|
+
const newEvents = [...existingEvents, entry];
|
|
1072
|
+
await this.db.set(path, newEvents);
|
|
1073
|
+
await this.triggerRulesForEvents([event]);
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Append multiple events to their respective streams
|
|
1077
|
+
*
|
|
1078
|
+
* @param events The events to append
|
|
1079
|
+
*/
|
|
1080
|
+
async appendEvents(events) {
|
|
1081
|
+
const eventsByTag = /* @__PURE__ */ new Map();
|
|
1082
|
+
for (const event of events) {
|
|
1083
|
+
const existing = eventsByTag.get(event.tag) ?? [];
|
|
1084
|
+
eventsByTag.set(event.tag, [...existing, event]);
|
|
1085
|
+
}
|
|
1086
|
+
for (const [tag, tagEvents] of eventsByTag) {
|
|
1087
|
+
const path = getEventPath(tag);
|
|
1088
|
+
const existingEvents = await this.db.get(path) ?? [];
|
|
1089
|
+
let sequence = existingEvents.length;
|
|
1090
|
+
const newEntries = tagEvents.map((event) => ({
|
|
1091
|
+
event,
|
|
1092
|
+
timestamp: Date.now(),
|
|
1093
|
+
sequence: sequence++
|
|
1094
|
+
}));
|
|
1095
|
+
await this.db.set(path, [...existingEvents, ...newEntries]);
|
|
1096
|
+
}
|
|
1097
|
+
await this.triggerRulesForEvents(events);
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Get events from a stream
|
|
1101
|
+
*
|
|
1102
|
+
* @param eventTag The event type tag
|
|
1103
|
+
* @param options Query options
|
|
1104
|
+
* @returns Array of event stream entries
|
|
1105
|
+
*/
|
|
1106
|
+
async getEvents(eventTag, options) {
|
|
1107
|
+
const path = getEventPath(eventTag);
|
|
1108
|
+
const events = await this.db.get(path) ?? [];
|
|
1109
|
+
let result = events;
|
|
1110
|
+
if (options?.since !== void 0) {
|
|
1111
|
+
const sinceTimestamp = options.since;
|
|
1112
|
+
result = result.filter((e) => e.timestamp > sinceTimestamp);
|
|
1113
|
+
}
|
|
1114
|
+
if (options?.limit !== void 0) {
|
|
1115
|
+
result = result.slice(-options.limit);
|
|
1116
|
+
}
|
|
1117
|
+
return result;
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* Watch a fact path for changes
|
|
1121
|
+
*
|
|
1122
|
+
* @param factTag The fact type tag to watch
|
|
1123
|
+
* @param callback Called when facts of this type change
|
|
1124
|
+
* @returns Unsubscribe function
|
|
1125
|
+
*/
|
|
1126
|
+
watchFacts(factTag, callback) {
|
|
1127
|
+
const path = getFactPath(factTag);
|
|
1128
|
+
if (!this.factWatchers.has(factTag)) {
|
|
1129
|
+
this.factWatchers.set(factTag, /* @__PURE__ */ new Set());
|
|
1130
|
+
}
|
|
1131
|
+
const watchers = this.factWatchers.get(factTag);
|
|
1132
|
+
if (watchers) {
|
|
1133
|
+
watchers.add(callback);
|
|
1134
|
+
}
|
|
1135
|
+
const unsubscribe = this.db.watch(path, (fact) => {
|
|
1136
|
+
callback([fact]);
|
|
1137
|
+
});
|
|
1138
|
+
this.subscriptions.push(unsubscribe);
|
|
1139
|
+
return () => {
|
|
1140
|
+
unsubscribe();
|
|
1141
|
+
this.factWatchers.get(factTag)?.delete(callback);
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Check constraints against the current state with new facts
|
|
1146
|
+
*/
|
|
1147
|
+
async checkConstraints(newFacts) {
|
|
1148
|
+
const constraints = this.registry.getAllConstraints();
|
|
1149
|
+
const errors = [];
|
|
1150
|
+
const state2 = {
|
|
1151
|
+
context: this.context,
|
|
1152
|
+
facts: newFacts,
|
|
1153
|
+
meta: {}
|
|
1154
|
+
};
|
|
1155
|
+
for (const constraint of constraints) {
|
|
1156
|
+
try {
|
|
1157
|
+
const result = constraint.impl(state2);
|
|
1158
|
+
if (result === false) {
|
|
1159
|
+
errors.push(`Constraint "${constraint.id}" violated`);
|
|
1160
|
+
} else if (typeof result === "string") {
|
|
1161
|
+
errors.push(result);
|
|
1162
|
+
}
|
|
1163
|
+
} catch (error) {
|
|
1164
|
+
errors.push(
|
|
1165
|
+
`Error checking constraint "${constraint.id}": ${error instanceof Error ? error.message : String(error)}`
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
return {
|
|
1170
|
+
valid: errors.length === 0,
|
|
1171
|
+
errors
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Trigger rules when new facts are added
|
|
1176
|
+
*
|
|
1177
|
+
* This method is called after facts are stored. It can be extended
|
|
1178
|
+
* for derived fact computation where rules generate new facts based
|
|
1179
|
+
* on existing facts. Currently implemented as a hook point for future
|
|
1180
|
+
* enhancements.
|
|
1181
|
+
*
|
|
1182
|
+
* @param _newFacts The newly stored facts (unused in current implementation)
|
|
1183
|
+
*/
|
|
1184
|
+
async triggerRules(_newFacts) {
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Trigger rules when events are appended
|
|
1188
|
+
*/
|
|
1189
|
+
async triggerRulesForEvents(events) {
|
|
1190
|
+
const rules = this.registry.getAllRules();
|
|
1191
|
+
const state2 = {
|
|
1192
|
+
context: this.context,
|
|
1193
|
+
facts: [],
|
|
1194
|
+
meta: {}
|
|
1195
|
+
};
|
|
1196
|
+
const derivedFacts = [];
|
|
1197
|
+
for (const rule of rules) {
|
|
1198
|
+
try {
|
|
1199
|
+
const facts = rule.impl(state2, events);
|
|
1200
|
+
derivedFacts.push(...facts);
|
|
1201
|
+
} catch (error) {
|
|
1202
|
+
this.onRuleError(rule.id, error);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
if (derivedFacts.length > 0) {
|
|
1206
|
+
const constraintResult = await this.checkConstraints(derivedFacts);
|
|
1207
|
+
if (constraintResult.valid) {
|
|
1208
|
+
for (const fact of derivedFacts) {
|
|
1209
|
+
await this.persistFact(fact);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Update the context
|
|
1216
|
+
*/
|
|
1217
|
+
updateContext(context) {
|
|
1218
|
+
this.context = context;
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Get the current context
|
|
1222
|
+
*/
|
|
1223
|
+
getContext() {
|
|
1224
|
+
return this.context;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Dispose of all subscriptions
|
|
1228
|
+
*/
|
|
1229
|
+
dispose() {
|
|
1230
|
+
for (const unsubscribe of this.subscriptions) {
|
|
1231
|
+
unsubscribe();
|
|
1232
|
+
}
|
|
1233
|
+
this.subscriptions = [];
|
|
1234
|
+
this.factWatchers.clear();
|
|
1235
|
+
}
|
|
1236
|
+
};
|
|
1237
|
+
function createPraxisDBStore(db, registry, initialContext, onRuleError) {
|
|
1238
|
+
return new PraxisDBStore({ db, registry, initialContext, onRuleError });
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
// src/core/pluresdb/adapter.ts
|
|
1242
|
+
var InMemoryPraxisDB = class {
|
|
1243
|
+
store = /* @__PURE__ */ new Map();
|
|
1244
|
+
watchers = /* @__PURE__ */ new Map();
|
|
1245
|
+
async get(key) {
|
|
1246
|
+
return this.store.get(key);
|
|
1247
|
+
}
|
|
1248
|
+
async set(key, value) {
|
|
1249
|
+
this.store.set(key, value);
|
|
1250
|
+
const keyWatchers = this.watchers.get(key);
|
|
1251
|
+
if (keyWatchers) {
|
|
1252
|
+
for (const callback of keyWatchers) {
|
|
1253
|
+
callback(value);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
watch(key, callback) {
|
|
1258
|
+
if (!this.watchers.has(key)) {
|
|
1259
|
+
this.watchers.set(key, /* @__PURE__ */ new Set());
|
|
1260
|
+
}
|
|
1261
|
+
const watchers = this.watchers.get(key);
|
|
1262
|
+
const wrappedCallback = (val) => callback(val);
|
|
1263
|
+
watchers.add(wrappedCallback);
|
|
1264
|
+
return () => {
|
|
1265
|
+
watchers.delete(wrappedCallback);
|
|
1266
|
+
if (watchers.size === 0) {
|
|
1267
|
+
this.watchers.delete(key);
|
|
1268
|
+
}
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Get all keys (for testing/debugging)
|
|
1273
|
+
*/
|
|
1274
|
+
keys() {
|
|
1275
|
+
return Array.from(this.store.keys());
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Clear all data (for testing)
|
|
1279
|
+
*/
|
|
1280
|
+
clear() {
|
|
1281
|
+
this.store.clear();
|
|
1282
|
+
this.watchers.clear();
|
|
1283
|
+
}
|
|
1284
|
+
};
|
|
1285
|
+
function createInMemoryDB() {
|
|
1286
|
+
return new InMemoryPraxisDB();
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
// src/core/pluresdb/schema-registry.ts
|
|
1290
|
+
function getSchemaPath(schemaName) {
|
|
1291
|
+
return `${PRAXIS_PATHS.SCHEMAS}/${schemaName}`;
|
|
1292
|
+
}
|
|
1293
|
+
var PraxisSchemaRegistry = class {
|
|
1294
|
+
db;
|
|
1295
|
+
constructor(db) {
|
|
1296
|
+
this.db = db;
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Register a schema in PluresDB
|
|
1300
|
+
*
|
|
1301
|
+
* @param schema The schema to register
|
|
1302
|
+
*/
|
|
1303
|
+
async register(schema) {
|
|
1304
|
+
const path = getSchemaPath(schema.name);
|
|
1305
|
+
const storedSchema = {
|
|
1306
|
+
schema,
|
|
1307
|
+
registeredAt: Date.now(),
|
|
1308
|
+
version: schema.version
|
|
1309
|
+
};
|
|
1310
|
+
await this.db.set(path, storedSchema);
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Get a schema by name
|
|
1314
|
+
*
|
|
1315
|
+
* @param schemaName The schema name
|
|
1316
|
+
* @returns The stored schema or undefined if not found
|
|
1317
|
+
*/
|
|
1318
|
+
async get(schemaName) {
|
|
1319
|
+
const path = getSchemaPath(schemaName);
|
|
1320
|
+
return this.db.get(path);
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Check if a schema is registered
|
|
1324
|
+
*
|
|
1325
|
+
* @param schemaName The schema name
|
|
1326
|
+
* @returns True if the schema exists
|
|
1327
|
+
*/
|
|
1328
|
+
async exists(schemaName) {
|
|
1329
|
+
const stored = await this.get(schemaName);
|
|
1330
|
+
return stored !== void 0;
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* Update a schema (replaces existing)
|
|
1334
|
+
*
|
|
1335
|
+
* @param schema The updated schema
|
|
1336
|
+
*/
|
|
1337
|
+
async update(schema) {
|
|
1338
|
+
await this.register(schema);
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* List all registered schema names
|
|
1342
|
+
*
|
|
1343
|
+
* Implementation note: This method uses an index stored at `/_praxis/schemas/_index`.
|
|
1344
|
+
* When using InMemoryPraxisDB, schemas must be registered using `registerWithIndex()`
|
|
1345
|
+
* for them to appear in this listing. When using a full PluresDB implementation,
|
|
1346
|
+
* native listing capabilities should be used instead.
|
|
1347
|
+
*
|
|
1348
|
+
* @returns Array of registered schema names
|
|
1349
|
+
*/
|
|
1350
|
+
async list() {
|
|
1351
|
+
const indexPath = `${PRAXIS_PATHS.SCHEMAS}/_index`;
|
|
1352
|
+
const index = await this.db.get(indexPath);
|
|
1353
|
+
return index ?? [];
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* Register a schema and update the index
|
|
1357
|
+
*
|
|
1358
|
+
* @param schema The schema to register
|
|
1359
|
+
*/
|
|
1360
|
+
async registerWithIndex(schema) {
|
|
1361
|
+
await this.register(schema);
|
|
1362
|
+
const indexPath = `${PRAXIS_PATHS.SCHEMAS}/_index`;
|
|
1363
|
+
const existingIndex = await this.db.get(indexPath) ?? [];
|
|
1364
|
+
if (!existingIndex.includes(schema.name)) {
|
|
1365
|
+
await this.db.set(indexPath, [...existingIndex, schema.name]);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
};
|
|
1369
|
+
async function registerSchema(db, schema) {
|
|
1370
|
+
const registry = new PraxisSchemaRegistry(db);
|
|
1371
|
+
await registry.registerWithIndex(schema);
|
|
1372
|
+
}
|
|
1373
|
+
function createSchemaRegistry(db) {
|
|
1374
|
+
return new PraxisSchemaRegistry(db);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
// src/core/pluresdb/generator.ts
|
|
1378
|
+
var PluresDBGenerator = class {
|
|
1379
|
+
options;
|
|
1380
|
+
constructor(options) {
|
|
1381
|
+
this.options = {
|
|
1382
|
+
dbVersion: 1,
|
|
1383
|
+
enableSync: false,
|
|
1384
|
+
autoIndex: "all",
|
|
1385
|
+
// Default to indexing all fields for backward compatibility
|
|
1386
|
+
...options
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
/**
|
|
1390
|
+
* Generate PluresDB configuration from schema
|
|
1391
|
+
*/
|
|
1392
|
+
generateConfig(schema) {
|
|
1393
|
+
const files = [];
|
|
1394
|
+
files.push(this.generateConfigFile(schema));
|
|
1395
|
+
return files;
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* Generate pluresdb-config.ts file
|
|
1399
|
+
*/
|
|
1400
|
+
generateConfigFile(schema) {
|
|
1401
|
+
const lines = [];
|
|
1402
|
+
const dbName = this.options.dbName || schema.name.toLowerCase();
|
|
1403
|
+
lines.push("/**");
|
|
1404
|
+
lines.push(` * PluresDB Configuration for ${schema.name}`);
|
|
1405
|
+
lines.push(" * Generated from Praxis schema");
|
|
1406
|
+
lines.push(" */");
|
|
1407
|
+
lines.push("");
|
|
1408
|
+
lines.push("// import { createPluresDB } from '@plures/pluresdb';");
|
|
1409
|
+
lines.push("");
|
|
1410
|
+
lines.push("/**");
|
|
1411
|
+
lines.push(" * Database store configuration");
|
|
1412
|
+
lines.push(" * ");
|
|
1413
|
+
const autoIndexStrategy = this.options.autoIndex || "all";
|
|
1414
|
+
if (autoIndexStrategy === "all") {
|
|
1415
|
+
lines.push(" * Indexing: All string, number, and date fields are auto-indexed by default.");
|
|
1416
|
+
lines.push(' * For large datasets, consider using autoIndex: "explicit" to only index');
|
|
1417
|
+
lines.push(" * fields explicitly defined in the schema.");
|
|
1418
|
+
} else if (autoIndexStrategy === "explicit") {
|
|
1419
|
+
lines.push(" * Indexing: Only fields explicitly defined in schema indexes are indexed.");
|
|
1420
|
+
} else if (autoIndexStrategy === "none") {
|
|
1421
|
+
lines.push(" * Indexing: Auto-indexing disabled. Only explicit schema indexes are used.");
|
|
1422
|
+
}
|
|
1423
|
+
lines.push(" */");
|
|
1424
|
+
lines.push("export const stores = {");
|
|
1425
|
+
if (schema.models && schema.models.length > 0) {
|
|
1426
|
+
for (const model of schema.models) {
|
|
1427
|
+
const storeName = model.name.toLowerCase() + "s";
|
|
1428
|
+
const storeConfig = this.generateStoreConfig(model);
|
|
1429
|
+
lines.push(` ${storeName}: {`);
|
|
1430
|
+
lines.push(` keyPath: '${storeConfig.keyPath}',`);
|
|
1431
|
+
if (storeConfig.indexes.length > 0) {
|
|
1432
|
+
lines.push(` indexes: [${storeConfig.indexes.map((idx) => `'${idx}'`).join(", ")}],`);
|
|
1433
|
+
}
|
|
1434
|
+
lines.push(" },");
|
|
1435
|
+
}
|
|
1436
|
+
} else {
|
|
1437
|
+
lines.push(" // No models defined in schema");
|
|
1438
|
+
}
|
|
1439
|
+
lines.push("};");
|
|
1440
|
+
lines.push("");
|
|
1441
|
+
lines.push("/**");
|
|
1442
|
+
lines.push(" * Database configuration");
|
|
1443
|
+
lines.push(" */");
|
|
1444
|
+
lines.push("export const dbConfig = {");
|
|
1445
|
+
lines.push(` name: '${dbName}',`);
|
|
1446
|
+
lines.push(` version: ${this.options.dbVersion},`);
|
|
1447
|
+
lines.push(" stores,");
|
|
1448
|
+
if (this.options.enableSync) {
|
|
1449
|
+
lines.push(" sync: {");
|
|
1450
|
+
lines.push(" enabled: true,");
|
|
1451
|
+
if (this.options.syncEndpoint) {
|
|
1452
|
+
lines.push(` endpoint: '${this.options.syncEndpoint}',`);
|
|
1453
|
+
} else {
|
|
1454
|
+
lines.push(" endpoint: 'ws://localhost:8080/sync',");
|
|
1455
|
+
}
|
|
1456
|
+
lines.push(" conflictResolution: 'last-write-wins',");
|
|
1457
|
+
lines.push(" },");
|
|
1458
|
+
}
|
|
1459
|
+
lines.push("};");
|
|
1460
|
+
lines.push("");
|
|
1461
|
+
lines.push("/**");
|
|
1462
|
+
lines.push(" * Initialize PluresDB");
|
|
1463
|
+
lines.push(" * @returns Configured PluresDB instance");
|
|
1464
|
+
lines.push(" */");
|
|
1465
|
+
lines.push("export function initDB() {");
|
|
1466
|
+
lines.push(" // Create and configure PluresDB instance");
|
|
1467
|
+
lines.push(" const db = createInMemoryDB();");
|
|
1468
|
+
lines.push(" ");
|
|
1469
|
+
lines.push(" // Initialize stores based on configuration");
|
|
1470
|
+
lines.push(" for (const storeDef of dbConfig.stores) {");
|
|
1471
|
+
lines.push(" // Pre-create store paths");
|
|
1472
|
+
lines.push(" db.set(`stores/${storeDef.name}/_meta`, {");
|
|
1473
|
+
lines.push(" keyPath: storeDef.keyPath,");
|
|
1474
|
+
lines.push(" indexes: storeDef.indexes,");
|
|
1475
|
+
lines.push(" createdAt: Date.now(),");
|
|
1476
|
+
lines.push(" });");
|
|
1477
|
+
lines.push(" }");
|
|
1478
|
+
lines.push(" ");
|
|
1479
|
+
lines.push(" console.log(`PluresDB initialized: ${dbConfig.name}`);");
|
|
1480
|
+
lines.push(" return db;");
|
|
1481
|
+
lines.push("}");
|
|
1482
|
+
lines.push("");
|
|
1483
|
+
lines.push("/**");
|
|
1484
|
+
lines.push(" * Get store by name");
|
|
1485
|
+
lines.push(" */");
|
|
1486
|
+
lines.push(
|
|
1487
|
+
"export function getStore(db: ReturnType<typeof createInMemoryDB>, storeName: string) {"
|
|
1488
|
+
);
|
|
1489
|
+
lines.push(" const storeDef = dbConfig.stores.find(s => s.name === storeName);");
|
|
1490
|
+
lines.push(" if (!storeDef) {");
|
|
1491
|
+
lines.push(' throw new Error(`Store "${storeName}" not found in configuration`);');
|
|
1492
|
+
lines.push(" }");
|
|
1493
|
+
lines.push(" return {");
|
|
1494
|
+
lines.push(" get: (key: string) => db.get(`stores/${storeName}/${key}`),");
|
|
1495
|
+
lines.push(
|
|
1496
|
+
" set: (key: string, value: unknown) => db.set(`stores/${storeName}/${key}`, value),"
|
|
1497
|
+
);
|
|
1498
|
+
lines.push(" delete: (key: string) => db.delete(`stores/${storeName}/${key}`),");
|
|
1499
|
+
lines.push(" watch: (key: string, callback: (data: unknown) => void) => ");
|
|
1500
|
+
lines.push(" db.watch(`stores/${storeName}/${key}`, callback),");
|
|
1501
|
+
lines.push(" };");
|
|
1502
|
+
lines.push("}");
|
|
1503
|
+
return {
|
|
1504
|
+
path: `${this.options.outputDir}/pluresdb-config.ts`,
|
|
1505
|
+
content: lines.join("\n"),
|
|
1506
|
+
type: "config"
|
|
1507
|
+
};
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Generate store configuration for a model
|
|
1511
|
+
*/
|
|
1512
|
+
generateStoreConfig(model) {
|
|
1513
|
+
const idField = model.fields.find((f) => f.name === "id" || f.name === "_id");
|
|
1514
|
+
const keyPath = idField ? idField.name : "id";
|
|
1515
|
+
const indexes = [];
|
|
1516
|
+
const autoIndexStrategy = this.options.autoIndex || "all";
|
|
1517
|
+
if (autoIndexStrategy === "all") {
|
|
1518
|
+
for (const field of model.fields) {
|
|
1519
|
+
if (field.name !== keyPath) {
|
|
1520
|
+
if (field.type === "string" || field.type === "number" || field.type === "date") {
|
|
1521
|
+
indexes.push(field.name);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
if (model.indexes) {
|
|
1527
|
+
for (const indexDef of model.indexes) {
|
|
1528
|
+
for (const fieldName of indexDef.fields) {
|
|
1529
|
+
if (!indexes.includes(fieldName) && fieldName !== keyPath) {
|
|
1530
|
+
indexes.push(fieldName);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
return {
|
|
1536
|
+
keyPath,
|
|
1537
|
+
indexes
|
|
1538
|
+
};
|
|
1539
|
+
}
|
|
1540
|
+
};
|
|
1541
|
+
function createPluresDBGenerator(outputDir, options) {
|
|
1542
|
+
return new PluresDBGenerator({
|
|
1543
|
+
outputDir,
|
|
1544
|
+
...options
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
// src/integrations/pluresdb.ts
|
|
1549
|
+
function createPluresDBAdapter(options) {
|
|
1550
|
+
const store = createPraxisDBStore(options.db, options.registry, options.initialContext);
|
|
1551
|
+
const subscriptions = [];
|
|
1552
|
+
return {
|
|
1553
|
+
async persistEvents(events) {
|
|
1554
|
+
await store.appendEvents(events);
|
|
1555
|
+
},
|
|
1556
|
+
async persistFacts(facts) {
|
|
1557
|
+
await store.storeFacts(facts);
|
|
1558
|
+
},
|
|
1559
|
+
async loadEvents(query) {
|
|
1560
|
+
if (!query?.tag) {
|
|
1561
|
+
return [];
|
|
1562
|
+
}
|
|
1563
|
+
const entries = await store.getEvents(query.tag, {
|
|
1564
|
+
since: query.since,
|
|
1565
|
+
limit: query.limit
|
|
1566
|
+
});
|
|
1567
|
+
return entries.map((e) => e.event);
|
|
1568
|
+
},
|
|
1569
|
+
subscribeToEvents(callback, query) {
|
|
1570
|
+
if (!query?.tag) {
|
|
1571
|
+
return () => {
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
const unsubscribe = store.watchFacts(query.tag, (facts) => {
|
|
1575
|
+
const events = facts.map((f) => ({
|
|
1576
|
+
tag: f.tag,
|
|
1577
|
+
payload: f.payload
|
|
1578
|
+
}));
|
|
1579
|
+
callback(events);
|
|
1580
|
+
});
|
|
1581
|
+
subscriptions.push(unsubscribe);
|
|
1582
|
+
return unsubscribe;
|
|
1583
|
+
},
|
|
1584
|
+
attachEngine(engine) {
|
|
1585
|
+
store.updateContext(engine.getContext());
|
|
1586
|
+
},
|
|
1587
|
+
dispose() {
|
|
1588
|
+
for (const unsub of subscriptions) {
|
|
1589
|
+
unsub();
|
|
1590
|
+
}
|
|
1591
|
+
subscriptions.length = 0;
|
|
1592
|
+
store.dispose();
|
|
1593
|
+
}
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
function attachToEngine(store, engine) {
|
|
1597
|
+
store.updateContext(engine.getContext());
|
|
1598
|
+
return () => {
|
|
1599
|
+
store.dispose();
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
// src/integrations/unum.ts
|
|
1604
|
+
async function createUnumAdapter(config) {
|
|
1605
|
+
const { db, realtime = true } = config;
|
|
1606
|
+
let currentIdentity = null;
|
|
1607
|
+
const channels = /* @__PURE__ */ new Map();
|
|
1608
|
+
const subscriptions = /* @__PURE__ */ new Set();
|
|
1609
|
+
if (config.identity) {
|
|
1610
|
+
currentIdentity = {
|
|
1611
|
+
...config.identity,
|
|
1612
|
+
id: config.identity.id || generateId2(),
|
|
1613
|
+
createdAt: Date.now()
|
|
1614
|
+
};
|
|
1615
|
+
await db.set(`unum/identities/${currentIdentity.id}`, currentIdentity);
|
|
1616
|
+
}
|
|
1617
|
+
async function setIdentity(identity) {
|
|
1618
|
+
currentIdentity = {
|
|
1619
|
+
...identity,
|
|
1620
|
+
id: generateId2(),
|
|
1621
|
+
createdAt: Date.now()
|
|
1622
|
+
};
|
|
1623
|
+
await db.set(`unum/identities/${currentIdentity.id}`, currentIdentity);
|
|
1624
|
+
return currentIdentity;
|
|
1625
|
+
}
|
|
1626
|
+
async function getIdentity(id) {
|
|
1627
|
+
return await db.get(`unum/identities/${id}`);
|
|
1628
|
+
}
|
|
1629
|
+
async function createChannel(name, members) {
|
|
1630
|
+
const channelId = generateId2();
|
|
1631
|
+
const channelData = {
|
|
1632
|
+
id: channelId,
|
|
1633
|
+
name,
|
|
1634
|
+
members: members || [],
|
|
1635
|
+
createdAt: Date.now(),
|
|
1636
|
+
createdBy: currentIdentity?.id
|
|
1637
|
+
};
|
|
1638
|
+
await db.set(`unum/channels/${channelId}`, channelData);
|
|
1639
|
+
const channel = createChannelInstance(channelId, name);
|
|
1640
|
+
channels.set(channelId, channel);
|
|
1641
|
+
return channel;
|
|
1642
|
+
}
|
|
1643
|
+
async function joinChannel(channelId) {
|
|
1644
|
+
const existing = channels.get(channelId);
|
|
1645
|
+
if (existing) return existing;
|
|
1646
|
+
const channelData = await db.get(`unum/channels/${channelId}`);
|
|
1647
|
+
if (!channelData) {
|
|
1648
|
+
throw new Error(`Channel ${channelId} not found`);
|
|
1649
|
+
}
|
|
1650
|
+
const channel = createChannelInstance(channelData.id, channelData.name);
|
|
1651
|
+
channels.set(channelId, channel);
|
|
1652
|
+
return channel;
|
|
1653
|
+
}
|
|
1654
|
+
async function listChannels() {
|
|
1655
|
+
return Array.from(channels.values());
|
|
1656
|
+
}
|
|
1657
|
+
function createChannelInstance(id, name) {
|
|
1658
|
+
const handlers = /* @__PURE__ */ new Set();
|
|
1659
|
+
return {
|
|
1660
|
+
id,
|
|
1661
|
+
name,
|
|
1662
|
+
subscribe(handler) {
|
|
1663
|
+
handlers.add(handler);
|
|
1664
|
+
if (realtime) {
|
|
1665
|
+
const unsub = db.watch(`unum/channels/${id}/messages`, (data) => {
|
|
1666
|
+
if (data) {
|
|
1667
|
+
handler(data);
|
|
1668
|
+
}
|
|
1669
|
+
});
|
|
1670
|
+
subscriptions.add(unsub);
|
|
1671
|
+
}
|
|
1672
|
+
return () => {
|
|
1673
|
+
handlers.delete(handler);
|
|
1674
|
+
};
|
|
1675
|
+
},
|
|
1676
|
+
async publish(message) {
|
|
1677
|
+
const fullMessage = {
|
|
1678
|
+
...message,
|
|
1679
|
+
id: message.id || generateId2(),
|
|
1680
|
+
channelId: id,
|
|
1681
|
+
timestamp: Date.now()
|
|
1682
|
+
};
|
|
1683
|
+
await db.set(`unum/channels/${id}/messages/${fullMessage.id}`, fullMessage);
|
|
1684
|
+
handlers.forEach((h) => h(fullMessage));
|
|
1685
|
+
},
|
|
1686
|
+
async getMembers() {
|
|
1687
|
+
const channelData = await db.get(`unum/channels/${id}`);
|
|
1688
|
+
if (!channelData?.members) return [];
|
|
1689
|
+
const members = [];
|
|
1690
|
+
for (const memberId of channelData.members) {
|
|
1691
|
+
const identity = await getIdentity(memberId);
|
|
1692
|
+
if (identity) members.push(identity);
|
|
1693
|
+
}
|
|
1694
|
+
return members;
|
|
1695
|
+
},
|
|
1696
|
+
async leave() {
|
|
1697
|
+
channels.delete(id);
|
|
1698
|
+
}
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
async function broadcastEvent(channelId, event) {
|
|
1702
|
+
const channel = channels.get(channelId);
|
|
1703
|
+
if (!channel) {
|
|
1704
|
+
throw new Error(`Not joined to channel ${channelId}`);
|
|
1705
|
+
}
|
|
1706
|
+
await channel.publish({
|
|
1707
|
+
id: generateId2(),
|
|
1708
|
+
sender: currentIdentity || { id: "anonymous", createdAt: Date.now() },
|
|
1709
|
+
content: event,
|
|
1710
|
+
type: "event"
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
async function broadcastFact(channelId, fact) {
|
|
1714
|
+
const channel = channels.get(channelId);
|
|
1715
|
+
if (!channel) {
|
|
1716
|
+
throw new Error(`Not joined to channel ${channelId}`);
|
|
1717
|
+
}
|
|
1718
|
+
await channel.publish({
|
|
1719
|
+
id: generateId2(),
|
|
1720
|
+
sender: currentIdentity || { id: "anonymous", createdAt: Date.now() },
|
|
1721
|
+
content: fact,
|
|
1722
|
+
type: "fact"
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
function subscribeToEvents(channelId, handler) {
|
|
1726
|
+
const channel = channels.get(channelId);
|
|
1727
|
+
if (!channel) {
|
|
1728
|
+
throw new Error(`Not joined to channel ${channelId}`);
|
|
1729
|
+
}
|
|
1730
|
+
return channel.subscribe((message) => {
|
|
1731
|
+
if (message.type === "event") {
|
|
1732
|
+
handler(message.content);
|
|
1733
|
+
}
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
function subscribeToFacts(channelId, handler) {
|
|
1737
|
+
const channel = channels.get(channelId);
|
|
1738
|
+
if (!channel) {
|
|
1739
|
+
throw new Error(`Not joined to channel ${channelId}`);
|
|
1740
|
+
}
|
|
1741
|
+
return channel.subscribe((message) => {
|
|
1742
|
+
if (message.type === "fact") {
|
|
1743
|
+
handler(message.content);
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
async function disconnect() {
|
|
1748
|
+
subscriptions.forEach((unsub) => unsub());
|
|
1749
|
+
subscriptions.clear();
|
|
1750
|
+
for (const channel of channels.values()) {
|
|
1751
|
+
await channel.leave();
|
|
1752
|
+
}
|
|
1753
|
+
channels.clear();
|
|
1754
|
+
currentIdentity = null;
|
|
1755
|
+
}
|
|
1756
|
+
return {
|
|
1757
|
+
get identity() {
|
|
1758
|
+
return currentIdentity;
|
|
1759
|
+
},
|
|
1760
|
+
setIdentity,
|
|
1761
|
+
getIdentity,
|
|
1762
|
+
createChannel,
|
|
1763
|
+
joinChannel,
|
|
1764
|
+
listChannels,
|
|
1765
|
+
broadcastEvent,
|
|
1766
|
+
broadcastFact,
|
|
1767
|
+
subscribeToEvents,
|
|
1768
|
+
subscribeToFacts,
|
|
1769
|
+
disconnect
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1772
|
+
function generateId2() {
|
|
1773
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).substr(2, 9)}`;
|
|
1774
|
+
}
|
|
1775
|
+
function attachUnumToEngine(_engine, _adapter, _channelId) {
|
|
1776
|
+
return () => {
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
// src/integrations/code-canvas.ts
|
|
1781
|
+
function schemaToCanvas(schema, _options = {}) {
|
|
1782
|
+
const nodes = [];
|
|
1783
|
+
const edges = [];
|
|
1784
|
+
let nodeId = 0;
|
|
1785
|
+
let yOffset = 0;
|
|
1786
|
+
const xSpacing = 200;
|
|
1787
|
+
const ySpacing = 100;
|
|
1788
|
+
if (schema.models) {
|
|
1789
|
+
schema.models.forEach((model, index) => {
|
|
1790
|
+
const pos = model.position && (model.position.x !== 0 || model.position.y !== 0) ? model.position : { x: 50, y: yOffset + index * ySpacing };
|
|
1791
|
+
const node = {
|
|
1792
|
+
id: model.id || `model-${nodeId++}`,
|
|
1793
|
+
type: "model",
|
|
1794
|
+
label: model.name,
|
|
1795
|
+
x: pos.x,
|
|
1796
|
+
y: pos.y,
|
|
1797
|
+
width: 150,
|
|
1798
|
+
height: 60,
|
|
1799
|
+
data: model,
|
|
1800
|
+
style: {
|
|
1801
|
+
backgroundColor: "#e3f2fd",
|
|
1802
|
+
borderColor: "#1976d2"
|
|
1803
|
+
}
|
|
1804
|
+
};
|
|
1805
|
+
nodes.push(node);
|
|
1806
|
+
});
|
|
1807
|
+
yOffset += schema.models.length * ySpacing + 50;
|
|
1808
|
+
}
|
|
1809
|
+
if (schema.components) {
|
|
1810
|
+
schema.components.forEach((component, index) => {
|
|
1811
|
+
const pos = component.position && (component.position.x !== 0 || component.position.y !== 0) ? component.position : { x: 50 + xSpacing, y: yOffset + index * ySpacing };
|
|
1812
|
+
const node = {
|
|
1813
|
+
id: component.id || `component-${nodeId++}`,
|
|
1814
|
+
type: "component",
|
|
1815
|
+
label: component.name,
|
|
1816
|
+
x: pos.x,
|
|
1817
|
+
y: pos.y,
|
|
1818
|
+
width: 150,
|
|
1819
|
+
height: 60,
|
|
1820
|
+
data: component,
|
|
1821
|
+
style: {
|
|
1822
|
+
backgroundColor: "#e8f5e9",
|
|
1823
|
+
borderColor: "#388e3c"
|
|
1824
|
+
}
|
|
1825
|
+
};
|
|
1826
|
+
nodes.push(node);
|
|
1827
|
+
if (component.model) {
|
|
1828
|
+
const modelNode = nodes.find((n) => n.type === "model" && n.label === component.model);
|
|
1829
|
+
if (modelNode) {
|
|
1830
|
+
edges.push({
|
|
1831
|
+
id: `edge-${edges.length}`,
|
|
1832
|
+
source: node.id,
|
|
1833
|
+
target: modelNode.id,
|
|
1834
|
+
type: "reference",
|
|
1835
|
+
label: "uses"
|
|
1836
|
+
});
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
});
|
|
1840
|
+
yOffset += schema.components.length * ySpacing + 50;
|
|
1841
|
+
}
|
|
1842
|
+
if (schema.events) {
|
|
1843
|
+
schema.events.forEach((event, index) => {
|
|
1844
|
+
const pos = event.position && (event.position.x !== 0 || event.position.y !== 0) ? event.position : { x: 50 + xSpacing * 2, y: yOffset + index * ySpacing };
|
|
1845
|
+
const node = {
|
|
1846
|
+
id: event.id || `event-${nodeId++}`,
|
|
1847
|
+
type: "event",
|
|
1848
|
+
label: event.tag,
|
|
1849
|
+
x: pos.x,
|
|
1850
|
+
y: pos.y,
|
|
1851
|
+
width: 150,
|
|
1852
|
+
height: 50,
|
|
1853
|
+
data: event,
|
|
1854
|
+
style: {
|
|
1855
|
+
backgroundColor: "#fff3e0",
|
|
1856
|
+
borderColor: "#f57c00"
|
|
1857
|
+
}
|
|
1858
|
+
};
|
|
1859
|
+
nodes.push(node);
|
|
1860
|
+
});
|
|
1861
|
+
yOffset += schema.events.length * ySpacing + 30;
|
|
1862
|
+
}
|
|
1863
|
+
if (schema.facts) {
|
|
1864
|
+
schema.facts.forEach((fact, index) => {
|
|
1865
|
+
const pos = fact.position && (fact.position.x !== 0 || fact.position.y !== 0) ? fact.position : { x: 50 + xSpacing * 3, y: yOffset + index * ySpacing };
|
|
1866
|
+
const node = {
|
|
1867
|
+
id: fact.id || `fact-${nodeId++}`,
|
|
1868
|
+
type: "fact",
|
|
1869
|
+
label: fact.tag,
|
|
1870
|
+
x: pos.x,
|
|
1871
|
+
y: pos.y,
|
|
1872
|
+
width: 150,
|
|
1873
|
+
height: 50,
|
|
1874
|
+
data: fact,
|
|
1875
|
+
style: {
|
|
1876
|
+
backgroundColor: "#fce4ec",
|
|
1877
|
+
borderColor: "#c2185b"
|
|
1878
|
+
}
|
|
1879
|
+
};
|
|
1880
|
+
nodes.push(node);
|
|
1881
|
+
});
|
|
1882
|
+
yOffset += schema.facts.length * ySpacing + 30;
|
|
1883
|
+
}
|
|
1884
|
+
if (schema.rules) {
|
|
1885
|
+
schema.rules.forEach((rule, index) => {
|
|
1886
|
+
const pos = rule.position && (rule.position.x !== 0 || rule.position.y !== 0) ? rule.position : { x: 50 + xSpacing * 4, y: yOffset + index * ySpacing };
|
|
1887
|
+
const node = {
|
|
1888
|
+
id: rule.id || `rule-${nodeId++}`,
|
|
1889
|
+
type: "rule",
|
|
1890
|
+
label: rule.id,
|
|
1891
|
+
x: pos.x,
|
|
1892
|
+
y: pos.y,
|
|
1893
|
+
width: 150,
|
|
1894
|
+
height: 50,
|
|
1895
|
+
data: rule,
|
|
1896
|
+
style: {
|
|
1897
|
+
backgroundColor: "#e1f5fe",
|
|
1898
|
+
borderColor: "#0288d1"
|
|
1899
|
+
}
|
|
1900
|
+
};
|
|
1901
|
+
nodes.push(node);
|
|
1902
|
+
if (rule.triggers) {
|
|
1903
|
+
rule.triggers.forEach((trigger) => {
|
|
1904
|
+
const eventNode = nodes.find((n) => n.type === "event" && n.label === trigger);
|
|
1905
|
+
if (eventNode) {
|
|
1906
|
+
edges.push({
|
|
1907
|
+
id: `edge-${edges.length}`,
|
|
1908
|
+
source: eventNode.id,
|
|
1909
|
+
target: node.id,
|
|
1910
|
+
type: "event",
|
|
1911
|
+
label: "triggers"
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
});
|
|
1917
|
+
yOffset += schema.rules.length * ySpacing + 30;
|
|
1918
|
+
}
|
|
1919
|
+
if (schema.constraints) {
|
|
1920
|
+
schema.constraints.forEach((constraint, index) => {
|
|
1921
|
+
const pos = constraint.position && (constraint.position.x !== 0 || constraint.position.y !== 0) ? constraint.position : { x: 50 + xSpacing * 5, y: yOffset + index * ySpacing };
|
|
1922
|
+
const node = {
|
|
1923
|
+
id: constraint.id || `constraint-${nodeId++}`,
|
|
1924
|
+
type: "constraint",
|
|
1925
|
+
label: constraint.id,
|
|
1926
|
+
x: pos.x,
|
|
1927
|
+
y: pos.y,
|
|
1928
|
+
width: 150,
|
|
1929
|
+
height: 50,
|
|
1930
|
+
data: constraint,
|
|
1931
|
+
style: {
|
|
1932
|
+
backgroundColor: "#ffebee",
|
|
1933
|
+
borderColor: "#c62828"
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
nodes.push(node);
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
return {
|
|
1940
|
+
id: `canvas-${Date.now()}`,
|
|
1941
|
+
name: schema.name || "Praxis Schema",
|
|
1942
|
+
version: schema.$version || "1.0.0",
|
|
1943
|
+
nodes,
|
|
1944
|
+
edges,
|
|
1945
|
+
flows: schema.flows || [],
|
|
1946
|
+
metadata: {
|
|
1947
|
+
created: Date.now(),
|
|
1948
|
+
modified: Date.now(),
|
|
1949
|
+
description: schema.description
|
|
1950
|
+
},
|
|
1951
|
+
viewport: { x: 0, y: 0, zoom: 1 }
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
function canvasToSchema(canvas) {
|
|
1955
|
+
const models = [];
|
|
1956
|
+
const components = [];
|
|
1957
|
+
const events = [];
|
|
1958
|
+
const facts = [];
|
|
1959
|
+
const rules = [];
|
|
1960
|
+
const constraints = [];
|
|
1961
|
+
for (const node of canvas.nodes) {
|
|
1962
|
+
const position = { x: node.x, y: node.y };
|
|
1963
|
+
switch (node.type) {
|
|
1964
|
+
case "model":
|
|
1965
|
+
if (node.data) {
|
|
1966
|
+
models.push({ ...node.data, position });
|
|
1967
|
+
}
|
|
1968
|
+
break;
|
|
1969
|
+
case "component":
|
|
1970
|
+
if (node.data) {
|
|
1971
|
+
components.push({ ...node.data, position });
|
|
1972
|
+
}
|
|
1973
|
+
break;
|
|
1974
|
+
case "event":
|
|
1975
|
+
if (node.data) {
|
|
1976
|
+
events.push({ ...node.data, position });
|
|
1977
|
+
}
|
|
1978
|
+
break;
|
|
1979
|
+
case "fact":
|
|
1980
|
+
if (node.data) {
|
|
1981
|
+
facts.push({ ...node.data, position });
|
|
1982
|
+
}
|
|
1983
|
+
break;
|
|
1984
|
+
case "rule":
|
|
1985
|
+
if (node.data) {
|
|
1986
|
+
rules.push({ ...node.data, position });
|
|
1987
|
+
}
|
|
1988
|
+
break;
|
|
1989
|
+
case "constraint":
|
|
1990
|
+
if (node.data) {
|
|
1991
|
+
constraints.push({ ...node.data, position });
|
|
1992
|
+
}
|
|
1993
|
+
break;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
return {
|
|
1997
|
+
$version: "1.0.0",
|
|
1998
|
+
id: canvas.id,
|
|
1999
|
+
name: canvas.name,
|
|
2000
|
+
description: canvas.metadata?.description,
|
|
2001
|
+
models,
|
|
2002
|
+
components,
|
|
2003
|
+
events,
|
|
2004
|
+
facts,
|
|
2005
|
+
rules,
|
|
2006
|
+
constraints,
|
|
2007
|
+
flows: canvas.flows || [],
|
|
2008
|
+
metadata: canvas.metadata
|
|
2009
|
+
};
|
|
2010
|
+
}
|
|
2011
|
+
function canvasToYaml(canvas) {
|
|
2012
|
+
const lines = [
|
|
2013
|
+
`# ${canvas.name}`,
|
|
2014
|
+
`# Generated by Praxis CodeCanvas Integration`,
|
|
2015
|
+
`# Version: ${canvas.version}`,
|
|
2016
|
+
"",
|
|
2017
|
+
"nodes:"
|
|
2018
|
+
];
|
|
2019
|
+
for (const node of canvas.nodes) {
|
|
2020
|
+
lines.push(` - id: "${node.id}"`);
|
|
2021
|
+
lines.push(` type: "${node.type}"`);
|
|
2022
|
+
lines.push(` label: "${node.label}"`);
|
|
2023
|
+
lines.push(` x: ${node.x}`);
|
|
2024
|
+
lines.push(` y: ${node.y}`);
|
|
2025
|
+
lines.push(` width: ${node.width}`);
|
|
2026
|
+
lines.push(` height: ${node.height}`);
|
|
2027
|
+
if (node.fsmState) {
|
|
2028
|
+
lines.push(` fsmState: "${node.fsmState}"`);
|
|
2029
|
+
}
|
|
2030
|
+
lines.push("");
|
|
2031
|
+
}
|
|
2032
|
+
lines.push("edges:");
|
|
2033
|
+
for (const edge of canvas.edges) {
|
|
2034
|
+
lines.push(` - id: "${edge.id}"`);
|
|
2035
|
+
lines.push(` source: "${edge.source}"`);
|
|
2036
|
+
lines.push(` target: "${edge.target}"`);
|
|
2037
|
+
if (edge.label) {
|
|
2038
|
+
lines.push(` label: "${edge.label}"`);
|
|
2039
|
+
}
|
|
2040
|
+
if (edge.type) {
|
|
2041
|
+
lines.push(` type: "${edge.type}"`);
|
|
2042
|
+
}
|
|
2043
|
+
lines.push("");
|
|
2044
|
+
}
|
|
2045
|
+
return lines.join("\n");
|
|
2046
|
+
}
|
|
2047
|
+
function canvasToMermaid(canvas) {
|
|
2048
|
+
const lines = ["graph TD"];
|
|
2049
|
+
for (const node of canvas.nodes) {
|
|
2050
|
+
let shape;
|
|
2051
|
+
switch (node.type) {
|
|
2052
|
+
case "model":
|
|
2053
|
+
shape = `[${node.label}]`;
|
|
2054
|
+
break;
|
|
2055
|
+
case "component":
|
|
2056
|
+
shape = `(${node.label})`;
|
|
2057
|
+
break;
|
|
2058
|
+
case "event":
|
|
2059
|
+
shape = `{{${node.label}}}`;
|
|
2060
|
+
break;
|
|
2061
|
+
case "fact":
|
|
2062
|
+
shape = `((${node.label}))`;
|
|
2063
|
+
break;
|
|
2064
|
+
case "rule":
|
|
2065
|
+
shape = `[/${node.label}/]`;
|
|
2066
|
+
break;
|
|
2067
|
+
case "constraint":
|
|
2068
|
+
shape = `[\\${node.label}\\]`;
|
|
2069
|
+
break;
|
|
2070
|
+
default:
|
|
2071
|
+
shape = `[${node.label}]`;
|
|
2072
|
+
}
|
|
2073
|
+
lines.push(` ${node.id}${shape}`);
|
|
2074
|
+
}
|
|
2075
|
+
lines.push("");
|
|
2076
|
+
for (const edge of canvas.edges) {
|
|
2077
|
+
const label = edge.label ? `|${edge.label}|` : "";
|
|
2078
|
+
lines.push(` ${edge.source} -->${label} ${edge.target}`);
|
|
2079
|
+
}
|
|
2080
|
+
return lines.join("\n");
|
|
2081
|
+
}
|
|
2082
|
+
function validateWithGuardian(files, activity, lifecycle) {
|
|
2083
|
+
const errors = [];
|
|
2084
|
+
const warnings = [];
|
|
2085
|
+
const currentState = lifecycle.find((s) => s.id === activity.activity);
|
|
2086
|
+
if (!currentState) {
|
|
2087
|
+
errors.push({
|
|
2088
|
+
code: "INVALID_ACTIVITY",
|
|
2089
|
+
message: `Activity "${activity.activity}" is not a valid lifecycle state`,
|
|
2090
|
+
rule: "lifecycle-state"
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
if (activity.allowedPaths) {
|
|
2094
|
+
for (const file of files) {
|
|
2095
|
+
const allowed = activity.allowedPaths.some((pattern) => {
|
|
2096
|
+
const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$");
|
|
2097
|
+
return regex.test(file);
|
|
2098
|
+
});
|
|
2099
|
+
if (!allowed) {
|
|
2100
|
+
errors.push({
|
|
2101
|
+
code: "PATH_NOT_ALLOWED",
|
|
2102
|
+
message: `File "${file}" is not allowed during "${activity.activity}" activity`,
|
|
2103
|
+
file,
|
|
2104
|
+
rule: "allowed-paths"
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
return {
|
|
2110
|
+
valid: errors.length === 0,
|
|
2111
|
+
errors,
|
|
2112
|
+
warnings,
|
|
2113
|
+
filesChecked: files,
|
|
2114
|
+
activity
|
|
2115
|
+
};
|
|
2116
|
+
}
|
|
2117
|
+
function createCanvasEditor(config) {
|
|
2118
|
+
const document = config.document || (config.schema ? schemaToCanvas(config.schema, { layout: config.layout }) : {
|
|
2119
|
+
id: `canvas-${Date.now()}`,
|
|
2120
|
+
name: "New Canvas",
|
|
2121
|
+
version: "1.0.0",
|
|
2122
|
+
nodes: [],
|
|
2123
|
+
edges: [],
|
|
2124
|
+
metadata: { created: Date.now(), modified: Date.now() },
|
|
2125
|
+
viewport: { x: 0, y: 0, zoom: 1 }
|
|
2126
|
+
});
|
|
2127
|
+
let nodeIdCounter = document.nodes.length;
|
|
2128
|
+
let edgeIdCounter = document.edges.length;
|
|
2129
|
+
return {
|
|
2130
|
+
document,
|
|
2131
|
+
addNode(node) {
|
|
2132
|
+
const fullNode = {
|
|
2133
|
+
...node,
|
|
2134
|
+
id: `node-${nodeIdCounter++}`
|
|
2135
|
+
};
|
|
2136
|
+
document.nodes.push(fullNode);
|
|
2137
|
+
document.metadata.modified = Date.now();
|
|
2138
|
+
return fullNode;
|
|
2139
|
+
},
|
|
2140
|
+
removeNode(id) {
|
|
2141
|
+
const index = document.nodes.findIndex((n) => n.id === id);
|
|
2142
|
+
if (index !== -1) {
|
|
2143
|
+
document.nodes.splice(index, 1);
|
|
2144
|
+
document.edges = document.edges.filter((e) => e.source !== id && e.target !== id);
|
|
2145
|
+
document.metadata.modified = Date.now();
|
|
2146
|
+
}
|
|
2147
|
+
},
|
|
2148
|
+
addEdge(edge) {
|
|
2149
|
+
const fullEdge = {
|
|
2150
|
+
...edge,
|
|
2151
|
+
id: `edge-${edgeIdCounter++}`
|
|
2152
|
+
};
|
|
2153
|
+
document.edges.push(fullEdge);
|
|
2154
|
+
document.metadata.modified = Date.now();
|
|
2155
|
+
return fullEdge;
|
|
2156
|
+
},
|
|
2157
|
+
removeEdge(id) {
|
|
2158
|
+
const index = document.edges.findIndex((e) => e.id === id);
|
|
2159
|
+
if (index !== -1) {
|
|
2160
|
+
document.edges.splice(index, 1);
|
|
2161
|
+
document.metadata.modified = Date.now();
|
|
2162
|
+
}
|
|
2163
|
+
},
|
|
2164
|
+
toSchema() {
|
|
2165
|
+
return canvasToSchema(document);
|
|
2166
|
+
},
|
|
2167
|
+
toYaml() {
|
|
2168
|
+
return canvasToYaml(document);
|
|
2169
|
+
},
|
|
2170
|
+
toMermaid() {
|
|
2171
|
+
return canvasToMermaid(document);
|
|
2172
|
+
}
|
|
2173
|
+
};
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
// src/integrations/state-docs.ts
|
|
2177
|
+
var StateDocsGenerator = class {
|
|
2178
|
+
config;
|
|
2179
|
+
constructor(config) {
|
|
2180
|
+
this.config = {
|
|
2181
|
+
target: "./docs",
|
|
2182
|
+
globs: ["**/*.ts", "**/*.js"],
|
|
2183
|
+
visualization: {
|
|
2184
|
+
format: "mermaid",
|
|
2185
|
+
exportPng: false,
|
|
2186
|
+
theme: "default"
|
|
2187
|
+
},
|
|
2188
|
+
template: {
|
|
2189
|
+
toc: true,
|
|
2190
|
+
timestamp: true
|
|
2191
|
+
},
|
|
2192
|
+
...config
|
|
2193
|
+
};
|
|
2194
|
+
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Generate documentation from a Praxis schema
|
|
2197
|
+
*/
|
|
2198
|
+
generateFromSchema(schema) {
|
|
2199
|
+
const docs = [];
|
|
2200
|
+
docs.push(this.generateSchemaReadme(schema));
|
|
2201
|
+
if (schema.models && schema.models.length > 0) {
|
|
2202
|
+
docs.push(this.generateModelsDoc(schema));
|
|
2203
|
+
}
|
|
2204
|
+
if (schema.components && schema.components.length > 0) {
|
|
2205
|
+
docs.push(this.generateComponentsDoc(schema));
|
|
2206
|
+
}
|
|
2207
|
+
if (schema.logic && schema.logic.length > 0) {
|
|
2208
|
+
for (const logic of schema.logic) {
|
|
2209
|
+
docs.push(this.generateLogicDoc(logic));
|
|
2210
|
+
docs.push(this.generateLogicDiagram(logic));
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
return docs;
|
|
2214
|
+
}
|
|
2215
|
+
/**
|
|
2216
|
+
* Generate documentation from a Praxis registry
|
|
2217
|
+
*/
|
|
2218
|
+
generateFromModule(module) {
|
|
2219
|
+
const docs = [];
|
|
2220
|
+
const rules = module.rules;
|
|
2221
|
+
const constraints = module.constraints;
|
|
2222
|
+
docs.push(this.generateRulesDoc(rules));
|
|
2223
|
+
docs.push(this.generateConstraintsDoc(constraints));
|
|
2224
|
+
docs.push(this.generateRegistryDiagram(rules, constraints));
|
|
2225
|
+
return docs;
|
|
2226
|
+
}
|
|
2227
|
+
/**
|
|
2228
|
+
* Generate the main schema README
|
|
2229
|
+
*/
|
|
2230
|
+
generateSchemaReadme(schema) {
|
|
2231
|
+
const lines = [];
|
|
2232
|
+
if (this.config.template?.header) {
|
|
2233
|
+
lines.push(this.config.template.header);
|
|
2234
|
+
lines.push("");
|
|
2235
|
+
}
|
|
2236
|
+
lines.push(`# ${schema.name || this.config.projectTitle}`);
|
|
2237
|
+
lines.push("");
|
|
2238
|
+
if (schema.description) {
|
|
2239
|
+
lines.push(schema.description);
|
|
2240
|
+
lines.push("");
|
|
2241
|
+
}
|
|
2242
|
+
if (this.config.template?.toc) {
|
|
2243
|
+
lines.push("## Table of Contents");
|
|
2244
|
+
lines.push("");
|
|
2245
|
+
lines.push("- [Overview](#overview)");
|
|
2246
|
+
if (schema.models && schema.models.length > 0) {
|
|
2247
|
+
lines.push("- [Models](#models)");
|
|
2248
|
+
}
|
|
2249
|
+
if (schema.components && schema.components.length > 0) {
|
|
2250
|
+
lines.push("- [Components](#components)");
|
|
2251
|
+
}
|
|
2252
|
+
if (schema.logic && schema.logic.length > 0) {
|
|
2253
|
+
lines.push("- [Logic](#logic)");
|
|
2254
|
+
}
|
|
2255
|
+
lines.push("");
|
|
2256
|
+
}
|
|
2257
|
+
lines.push("## Overview");
|
|
2258
|
+
lines.push("");
|
|
2259
|
+
lines.push(`**Version:** ${schema.version}`);
|
|
2260
|
+
lines.push("");
|
|
2261
|
+
lines.push("### Statistics");
|
|
2262
|
+
lines.push("");
|
|
2263
|
+
lines.push("| Category | Count |");
|
|
2264
|
+
lines.push("|----------|-------|");
|
|
2265
|
+
lines.push(`| Models | ${schema.models?.length || 0} |`);
|
|
2266
|
+
lines.push(`| Components | ${schema.components?.length || 0} |`);
|
|
2267
|
+
lines.push(`| Logic Modules | ${schema.logic?.length || 0} |`);
|
|
2268
|
+
lines.push("");
|
|
2269
|
+
if (schema.models && schema.models.length > 0) {
|
|
2270
|
+
lines.push("## Models");
|
|
2271
|
+
lines.push("");
|
|
2272
|
+
for (const model of schema.models) {
|
|
2273
|
+
lines.push(`### ${model.name}`);
|
|
2274
|
+
lines.push("");
|
|
2275
|
+
if (model.description) {
|
|
2276
|
+
lines.push(model.description);
|
|
2277
|
+
lines.push("");
|
|
2278
|
+
}
|
|
2279
|
+
lines.push("**Fields:**");
|
|
2280
|
+
lines.push("");
|
|
2281
|
+
lines.push("| Name | Type | Required |");
|
|
2282
|
+
lines.push("|------|------|----------|");
|
|
2283
|
+
for (const field of model.fields) {
|
|
2284
|
+
const required = field.optional ? "No" : "Yes";
|
|
2285
|
+
lines.push(`| ${field.name} | ${field.type} | ${required} |`);
|
|
2286
|
+
}
|
|
2287
|
+
lines.push("");
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
if (schema.components && schema.components.length > 0) {
|
|
2291
|
+
lines.push("## Components");
|
|
2292
|
+
lines.push("");
|
|
2293
|
+
for (const component of schema.components) {
|
|
2294
|
+
lines.push(`### ${component.name}`);
|
|
2295
|
+
lines.push("");
|
|
2296
|
+
lines.push(`**Type:** ${component.type}`);
|
|
2297
|
+
lines.push("");
|
|
2298
|
+
if (component.description) {
|
|
2299
|
+
lines.push(component.description);
|
|
2300
|
+
lines.push("");
|
|
2301
|
+
}
|
|
2302
|
+
if (component.model) {
|
|
2303
|
+
lines.push(`**Model:** ${component.model}`);
|
|
2304
|
+
lines.push("");
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
if (schema.logic && schema.logic.length > 0) {
|
|
2309
|
+
lines.push("## Logic");
|
|
2310
|
+
lines.push("");
|
|
2311
|
+
for (const logic of schema.logic) {
|
|
2312
|
+
lines.push(`### ${logic.id}`);
|
|
2313
|
+
lines.push("");
|
|
2314
|
+
if (logic.description) {
|
|
2315
|
+
lines.push(logic.description);
|
|
2316
|
+
lines.push("");
|
|
2317
|
+
}
|
|
2318
|
+
if (logic.events && logic.events.length > 0) {
|
|
2319
|
+
lines.push("**Events:**");
|
|
2320
|
+
lines.push("");
|
|
2321
|
+
for (const event of logic.events) {
|
|
2322
|
+
lines.push(`- \`${event.tag}\`: ${event.description || ""}`);
|
|
2323
|
+
}
|
|
2324
|
+
lines.push("");
|
|
2325
|
+
}
|
|
2326
|
+
if (logic.facts && logic.facts.length > 0) {
|
|
2327
|
+
lines.push("**Facts:**");
|
|
2328
|
+
lines.push("");
|
|
2329
|
+
for (const fact of logic.facts) {
|
|
2330
|
+
lines.push(`- \`${fact.tag}\`: ${fact.description || ""}`);
|
|
2331
|
+
}
|
|
2332
|
+
lines.push("");
|
|
2333
|
+
}
|
|
2334
|
+
if (logic.rules && logic.rules.length > 0) {
|
|
2335
|
+
lines.push("**Rules:**");
|
|
2336
|
+
lines.push("");
|
|
2337
|
+
for (const rule of logic.rules) {
|
|
2338
|
+
lines.push(`- \`${rule.id}\`: ${rule.description || ""}`);
|
|
2339
|
+
}
|
|
2340
|
+
lines.push("");
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
if (this.config.template?.timestamp) {
|
|
2345
|
+
lines.push("---");
|
|
2346
|
+
lines.push("");
|
|
2347
|
+
lines.push(`*Generated on ${(/* @__PURE__ */ new Date()).toISOString()} by State-Docs*`);
|
|
2348
|
+
}
|
|
2349
|
+
if (this.config.template?.footer) {
|
|
2350
|
+
lines.push("");
|
|
2351
|
+
lines.push(this.config.template.footer);
|
|
2352
|
+
}
|
|
2353
|
+
return {
|
|
2354
|
+
path: `${this.config.target}/README.md`,
|
|
2355
|
+
content: lines.join("\n"),
|
|
2356
|
+
type: "markdown"
|
|
2357
|
+
};
|
|
2358
|
+
}
|
|
2359
|
+
/**
|
|
2360
|
+
* Generate models documentation
|
|
2361
|
+
*/
|
|
2362
|
+
generateModelsDoc(schema) {
|
|
2363
|
+
const lines = [
|
|
2364
|
+
"# Models",
|
|
2365
|
+
"",
|
|
2366
|
+
"This document describes all data models defined in the schema.",
|
|
2367
|
+
""
|
|
2368
|
+
];
|
|
2369
|
+
if (schema.models) {
|
|
2370
|
+
for (const model of schema.models) {
|
|
2371
|
+
lines.push(`## ${model.name}`);
|
|
2372
|
+
lines.push("");
|
|
2373
|
+
if (model.description) {
|
|
2374
|
+
lines.push(model.description);
|
|
2375
|
+
lines.push("");
|
|
2376
|
+
}
|
|
2377
|
+
lines.push("### Fields");
|
|
2378
|
+
lines.push("");
|
|
2379
|
+
lines.push("| Name | Type | Required | Description |");
|
|
2380
|
+
lines.push("|------|------|----------|-------------|");
|
|
2381
|
+
for (const field of model.fields) {
|
|
2382
|
+
const required = field.optional ? "No" : "Yes";
|
|
2383
|
+
const description = field.description || "-";
|
|
2384
|
+
lines.push(`| ${field.name} | \`${field.type}\` | ${required} | ${description} |`);
|
|
2385
|
+
}
|
|
2386
|
+
lines.push("");
|
|
2387
|
+
if (model.indexes && model.indexes.length > 0) {
|
|
2388
|
+
lines.push("### Indexes");
|
|
2389
|
+
lines.push("");
|
|
2390
|
+
for (const index of model.indexes) {
|
|
2391
|
+
lines.push(`- **${index.name}**: \`${index.fields.join(", ")}\``);
|
|
2392
|
+
}
|
|
2393
|
+
lines.push("");
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
return {
|
|
2398
|
+
path: `${this.config.target}/models.md`,
|
|
2399
|
+
content: lines.join("\n"),
|
|
2400
|
+
type: "markdown"
|
|
2401
|
+
};
|
|
2402
|
+
}
|
|
2403
|
+
/**
|
|
2404
|
+
* Generate components documentation
|
|
2405
|
+
*/
|
|
2406
|
+
generateComponentsDoc(schema) {
|
|
2407
|
+
const lines = [
|
|
2408
|
+
"# Components",
|
|
2409
|
+
"",
|
|
2410
|
+
"This document describes all UI components defined in the schema.",
|
|
2411
|
+
""
|
|
2412
|
+
];
|
|
2413
|
+
if (schema.components) {
|
|
2414
|
+
for (const component of schema.components) {
|
|
2415
|
+
lines.push(`## ${component.name}`);
|
|
2416
|
+
lines.push("");
|
|
2417
|
+
lines.push(`**Type:** ${component.type}`);
|
|
2418
|
+
lines.push("");
|
|
2419
|
+
if (component.description) {
|
|
2420
|
+
lines.push(component.description);
|
|
2421
|
+
lines.push("");
|
|
2422
|
+
}
|
|
2423
|
+
if (component.model) {
|
|
2424
|
+
lines.push(
|
|
2425
|
+
`**Associated Model:** [${component.model}](./models.md#${component.model.toLowerCase()})`
|
|
2426
|
+
);
|
|
2427
|
+
lines.push("");
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
return {
|
|
2432
|
+
path: `${this.config.target}/components.md`,
|
|
2433
|
+
content: lines.join("\n"),
|
|
2434
|
+
type: "markdown"
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* Generate logic documentation
|
|
2439
|
+
*/
|
|
2440
|
+
generateLogicDoc(logic) {
|
|
2441
|
+
const lines = [`# ${logic.id}`, ""];
|
|
2442
|
+
if (logic.description) {
|
|
2443
|
+
lines.push(logic.description);
|
|
2444
|
+
lines.push("");
|
|
2445
|
+
}
|
|
2446
|
+
if (logic.events && logic.events.length > 0) {
|
|
2447
|
+
lines.push("## Events");
|
|
2448
|
+
lines.push("");
|
|
2449
|
+
lines.push("| Event | Description | Payload |");
|
|
2450
|
+
lines.push("|-------|-------------|---------|");
|
|
2451
|
+
for (const event of logic.events) {
|
|
2452
|
+
const payload = event.payload ? Object.entries(event.payload).map(([k, v]) => `${k}: ${v}`).join(", ") : "-";
|
|
2453
|
+
lines.push(`| \`${event.tag}\` | ${event.description || "-"} | ${payload} |`);
|
|
2454
|
+
}
|
|
2455
|
+
lines.push("");
|
|
2456
|
+
}
|
|
2457
|
+
if (logic.facts && logic.facts.length > 0) {
|
|
2458
|
+
lines.push("## Facts");
|
|
2459
|
+
lines.push("");
|
|
2460
|
+
lines.push("| Fact | Description | Payload |");
|
|
2461
|
+
lines.push("|------|-------------|---------|");
|
|
2462
|
+
for (const fact of logic.facts) {
|
|
2463
|
+
const payload = fact.payload ? Object.entries(fact.payload).map(([k, v]) => `${k}: ${v}`).join(", ") : "-";
|
|
2464
|
+
lines.push(`| \`${fact.tag}\` | ${fact.description || "-"} | ${payload} |`);
|
|
2465
|
+
}
|
|
2466
|
+
lines.push("");
|
|
2467
|
+
}
|
|
2468
|
+
if (logic.rules && logic.rules.length > 0) {
|
|
2469
|
+
lines.push("## Rules");
|
|
2470
|
+
lines.push("");
|
|
2471
|
+
for (const rule of logic.rules) {
|
|
2472
|
+
lines.push(`### ${rule.id}`);
|
|
2473
|
+
lines.push("");
|
|
2474
|
+
if (rule.description) {
|
|
2475
|
+
lines.push(rule.description);
|
|
2476
|
+
lines.push("");
|
|
2477
|
+
}
|
|
2478
|
+
if (rule.priority !== void 0) {
|
|
2479
|
+
lines.push(`**Priority:** ${rule.priority}`);
|
|
2480
|
+
lines.push("");
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
if (logic.constraints && logic.constraints.length > 0) {
|
|
2485
|
+
lines.push("## Constraints");
|
|
2486
|
+
lines.push("");
|
|
2487
|
+
for (const constraint of logic.constraints) {
|
|
2488
|
+
lines.push(`### ${constraint.id}`);
|
|
2489
|
+
lines.push("");
|
|
2490
|
+
if (constraint.description) {
|
|
2491
|
+
lines.push(constraint.description);
|
|
2492
|
+
lines.push("");
|
|
2493
|
+
}
|
|
2494
|
+
if (constraint.message) {
|
|
2495
|
+
lines.push(`**Error Message:** ${constraint.message}`);
|
|
2496
|
+
lines.push("");
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
return {
|
|
2501
|
+
path: `${this.config.target}/logic/${logic.id}.md`,
|
|
2502
|
+
content: lines.join("\n"),
|
|
2503
|
+
type: "markdown"
|
|
2504
|
+
};
|
|
2505
|
+
}
|
|
2506
|
+
/**
|
|
2507
|
+
* Generate Mermaid diagram for logic
|
|
2508
|
+
*/
|
|
2509
|
+
generateLogicDiagram(logic) {
|
|
2510
|
+
const lines = ["stateDiagram-v2"];
|
|
2511
|
+
if (logic.events && logic.facts) {
|
|
2512
|
+
lines.push(" [*] --> Processing");
|
|
2513
|
+
for (const event of logic.events) {
|
|
2514
|
+
lines.push(` Processing --> ${event.tag.replace(/[^a-zA-Z0-9]/g, "")}: ${event.tag}`);
|
|
2515
|
+
}
|
|
2516
|
+
for (const fact of logic.facts) {
|
|
2517
|
+
lines.push(` ${fact.tag.replace(/[^a-zA-Z0-9]/g, "")} --> [*]`);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
return {
|
|
2521
|
+
path: `${this.config.target}/logic/${logic.id}.mmd`,
|
|
2522
|
+
content: lines.join("\n"),
|
|
2523
|
+
type: "mermaid"
|
|
2524
|
+
};
|
|
2525
|
+
}
|
|
2526
|
+
/**
|
|
2527
|
+
* Generate rules documentation
|
|
2528
|
+
*/
|
|
2529
|
+
generateRulesDoc(rules) {
|
|
2530
|
+
const lines = [
|
|
2531
|
+
"# Rules",
|
|
2532
|
+
"",
|
|
2533
|
+
"This document describes all rules registered in the Praxis engine.",
|
|
2534
|
+
""
|
|
2535
|
+
];
|
|
2536
|
+
for (const rule of rules) {
|
|
2537
|
+
lines.push(`## ${rule.id}`);
|
|
2538
|
+
lines.push("");
|
|
2539
|
+
if (rule.description) {
|
|
2540
|
+
lines.push(rule.description);
|
|
2541
|
+
lines.push("");
|
|
2542
|
+
}
|
|
2543
|
+
if (rule.meta?.eventType) {
|
|
2544
|
+
lines.push(`**Triggers on:** \`${rule.meta.eventType}\``);
|
|
2545
|
+
lines.push("");
|
|
2546
|
+
}
|
|
2547
|
+
if (rule.meta?.priority !== void 0) {
|
|
2548
|
+
lines.push(`**Priority:** ${rule.meta.priority}`);
|
|
2549
|
+
lines.push("");
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
return {
|
|
2553
|
+
path: `${this.config.target}/rules.md`,
|
|
2554
|
+
content: lines.join("\n"),
|
|
2555
|
+
type: "markdown"
|
|
2556
|
+
};
|
|
2557
|
+
}
|
|
2558
|
+
/**
|
|
2559
|
+
* Generate constraints documentation
|
|
2560
|
+
*/
|
|
2561
|
+
generateConstraintsDoc(constraints) {
|
|
2562
|
+
const lines = [
|
|
2563
|
+
"# Constraints",
|
|
2564
|
+
"",
|
|
2565
|
+
"This document describes all constraints (invariants) registered in the Praxis engine.",
|
|
2566
|
+
""
|
|
2567
|
+
];
|
|
2568
|
+
for (const constraint of constraints) {
|
|
2569
|
+
lines.push(`## ${constraint.id}`);
|
|
2570
|
+
lines.push("");
|
|
2571
|
+
if (constraint.description) {
|
|
2572
|
+
lines.push(constraint.description);
|
|
2573
|
+
lines.push("");
|
|
2574
|
+
}
|
|
2575
|
+
if (constraint.meta?.errorMessage) {
|
|
2576
|
+
lines.push(`**Error Message:** ${constraint.meta.errorMessage}`);
|
|
2577
|
+
lines.push("");
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
return {
|
|
2581
|
+
path: `${this.config.target}/constraints.md`,
|
|
2582
|
+
content: lines.join("\n"),
|
|
2583
|
+
type: "markdown"
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
/**
|
|
2587
|
+
* Generate state diagram from registry
|
|
2588
|
+
*/
|
|
2589
|
+
generateRegistryDiagram(rules, constraints) {
|
|
2590
|
+
const lines = ["graph TD", " subgraph Rules"];
|
|
2591
|
+
for (const rule of rules) {
|
|
2592
|
+
const id = rule.id.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2593
|
+
lines.push(` ${id}["${rule.id}"]`);
|
|
2594
|
+
}
|
|
2595
|
+
lines.push(" end");
|
|
2596
|
+
lines.push(" subgraph Constraints");
|
|
2597
|
+
for (const constraint of constraints) {
|
|
2598
|
+
const id = constraint.id.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2599
|
+
lines.push(` ${id}["${constraint.id}"]`);
|
|
2600
|
+
}
|
|
2601
|
+
lines.push(" end");
|
|
2602
|
+
return {
|
|
2603
|
+
path: `${this.config.target}/state-diagram.mmd`,
|
|
2604
|
+
content: lines.join("\n"),
|
|
2605
|
+
type: "mermaid"
|
|
2606
|
+
};
|
|
2607
|
+
}
|
|
2608
|
+
};
|
|
2609
|
+
function createStateDocsGenerator(config) {
|
|
2610
|
+
return new StateDocsGenerator(config);
|
|
2611
|
+
}
|
|
2612
|
+
function generateDocs(schema, config) {
|
|
2613
|
+
const generator = createStateDocsGenerator(config);
|
|
2614
|
+
return generator.generateFromSchema(schema);
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
// src/integrations/tauri.ts
|
|
2618
|
+
function createMockTauriBridge() {
|
|
2619
|
+
const eventHandlers = /* @__PURE__ */ new Map();
|
|
2620
|
+
const storage = /* @__PURE__ */ new Map();
|
|
2621
|
+
return {
|
|
2622
|
+
app: {
|
|
2623
|
+
name: "Mock App",
|
|
2624
|
+
version: "0.0.0",
|
|
2625
|
+
tauriVersion: "mock"
|
|
2626
|
+
},
|
|
2627
|
+
fs: {
|
|
2628
|
+
async readFile(path) {
|
|
2629
|
+
const data = storage.get(path);
|
|
2630
|
+
if (data instanceof Uint8Array) return data;
|
|
2631
|
+
throw new Error(`File not found: ${path}`);
|
|
2632
|
+
},
|
|
2633
|
+
async readTextFile(path) {
|
|
2634
|
+
const data = storage.get(path);
|
|
2635
|
+
if (typeof data === "string") return data;
|
|
2636
|
+
throw new Error(`File not found: ${path}`);
|
|
2637
|
+
},
|
|
2638
|
+
async writeFile(path, data) {
|
|
2639
|
+
storage.set(path, data);
|
|
2640
|
+
},
|
|
2641
|
+
async writeTextFile(path, data) {
|
|
2642
|
+
storage.set(path, data);
|
|
2643
|
+
},
|
|
2644
|
+
async exists(path) {
|
|
2645
|
+
return storage.has(path);
|
|
2646
|
+
},
|
|
2647
|
+
async mkdir(_path, _options) {
|
|
2648
|
+
},
|
|
2649
|
+
async remove(path, _options) {
|
|
2650
|
+
storage.delete(path);
|
|
2651
|
+
},
|
|
2652
|
+
async rename(oldPath, newPath) {
|
|
2653
|
+
const data = storage.get(oldPath);
|
|
2654
|
+
if (data !== void 0) {
|
|
2655
|
+
storage.set(newPath, data);
|
|
2656
|
+
storage.delete(oldPath);
|
|
2657
|
+
}
|
|
2658
|
+
},
|
|
2659
|
+
async readDir(_path) {
|
|
2660
|
+
return [];
|
|
2661
|
+
}
|
|
2662
|
+
},
|
|
2663
|
+
tray: {
|
|
2664
|
+
async setIcon(_icon) {
|
|
2665
|
+
},
|
|
2666
|
+
async setTooltip(_tooltip) {
|
|
2667
|
+
},
|
|
2668
|
+
async setMenu(_menu) {
|
|
2669
|
+
},
|
|
2670
|
+
async show() {
|
|
2671
|
+
},
|
|
2672
|
+
async hide() {
|
|
2673
|
+
}
|
|
2674
|
+
},
|
|
2675
|
+
notification: {
|
|
2676
|
+
async send(options) {
|
|
2677
|
+
console.log("Mock notification:", options.title, options.body);
|
|
2678
|
+
},
|
|
2679
|
+
async requestPermission() {
|
|
2680
|
+
return "granted";
|
|
2681
|
+
},
|
|
2682
|
+
async checkPermission() {
|
|
2683
|
+
return "granted";
|
|
2684
|
+
}
|
|
2685
|
+
},
|
|
2686
|
+
async invoke(cmd, payload) {
|
|
2687
|
+
console.log("Mock invoke:", cmd, payload);
|
|
2688
|
+
return null;
|
|
2689
|
+
},
|
|
2690
|
+
async listen(event, handler) {
|
|
2691
|
+
if (!eventHandlers.has(event)) {
|
|
2692
|
+
eventHandlers.set(event, /* @__PURE__ */ new Set());
|
|
2693
|
+
}
|
|
2694
|
+
eventHandlers.get(event).add(handler);
|
|
2695
|
+
return () => {
|
|
2696
|
+
eventHandlers.get(event)?.delete(handler);
|
|
2697
|
+
};
|
|
2698
|
+
},
|
|
2699
|
+
async emit(event, payload) {
|
|
2700
|
+
const handlers = eventHandlers.get(event);
|
|
2701
|
+
if (handlers) {
|
|
2702
|
+
const tauriEvent = { event, payload };
|
|
2703
|
+
handlers.forEach((h) => h(tauriEvent));
|
|
2704
|
+
}
|
|
2705
|
+
},
|
|
2706
|
+
window: {
|
|
2707
|
+
async minimize() {
|
|
2708
|
+
},
|
|
2709
|
+
async maximize() {
|
|
2710
|
+
},
|
|
2711
|
+
async unmaximize() {
|
|
2712
|
+
},
|
|
2713
|
+
async close() {
|
|
2714
|
+
},
|
|
2715
|
+
async toggleFullscreen() {
|
|
2716
|
+
},
|
|
2717
|
+
async setTitle(_title) {
|
|
2718
|
+
},
|
|
2719
|
+
async show() {
|
|
2720
|
+
},
|
|
2721
|
+
async hide() {
|
|
2722
|
+
},
|
|
2723
|
+
async focus() {
|
|
2724
|
+
}
|
|
2725
|
+
},
|
|
2726
|
+
async checkForUpdates() {
|
|
2727
|
+
return null;
|
|
2728
|
+
},
|
|
2729
|
+
async installUpdate() {
|
|
2730
|
+
}
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2733
|
+
function createTauriPraxisAdapter(options) {
|
|
2734
|
+
const { bridge, statePath = "praxis-state.json", eventsPath = "praxis-events.json" } = options;
|
|
2735
|
+
return {
|
|
2736
|
+
async saveState(state2) {
|
|
2737
|
+
const json = JSON.stringify(state2, null, 2);
|
|
2738
|
+
await bridge.fs.writeTextFile(statePath, json);
|
|
2739
|
+
},
|
|
2740
|
+
async loadState() {
|
|
2741
|
+
try {
|
|
2742
|
+
const exists = await bridge.fs.exists(statePath);
|
|
2743
|
+
if (!exists) return null;
|
|
2744
|
+
const json = await bridge.fs.readTextFile(statePath);
|
|
2745
|
+
return JSON.parse(json);
|
|
2746
|
+
} catch {
|
|
2747
|
+
return null;
|
|
2748
|
+
}
|
|
2749
|
+
},
|
|
2750
|
+
async saveEvents(events) {
|
|
2751
|
+
const json = JSON.stringify(events, null, 2);
|
|
2752
|
+
await bridge.fs.writeTextFile(eventsPath, json);
|
|
2753
|
+
},
|
|
2754
|
+
async loadEvents() {
|
|
2755
|
+
try {
|
|
2756
|
+
const exists = await bridge.fs.exists(eventsPath);
|
|
2757
|
+
if (!exists) return [];
|
|
2758
|
+
const json = await bridge.fs.readTextFile(eventsPath);
|
|
2759
|
+
return JSON.parse(json);
|
|
2760
|
+
} catch {
|
|
2761
|
+
return [];
|
|
2762
|
+
}
|
|
2763
|
+
},
|
|
2764
|
+
async watchStateFile(_handler) {
|
|
2765
|
+
console.log("File watching not implemented in mock");
|
|
2766
|
+
return () => {
|
|
2767
|
+
};
|
|
2768
|
+
},
|
|
2769
|
+
getStatePath() {
|
|
2770
|
+
return statePath;
|
|
2771
|
+
},
|
|
2772
|
+
getEventsPath() {
|
|
2773
|
+
return eventsPath;
|
|
2774
|
+
}
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
function attachTauriToEngine(engine, adapter, options = {}) {
|
|
2778
|
+
const { autoSave = true, saveInterval = 5e3 } = options;
|
|
2779
|
+
const cleanupFns = [];
|
|
2780
|
+
if (autoSave) {
|
|
2781
|
+
let saveTimer = null;
|
|
2782
|
+
let pendingSave = false;
|
|
2783
|
+
const debouncedSave = async () => {
|
|
2784
|
+
pendingSave = true;
|
|
2785
|
+
if (saveTimer) clearTimeout(saveTimer);
|
|
2786
|
+
saveTimer = setTimeout(async () => {
|
|
2787
|
+
if (pendingSave) {
|
|
2788
|
+
await adapter.saveState(engine.getContext());
|
|
2789
|
+
pendingSave = false;
|
|
2790
|
+
}
|
|
2791
|
+
}, saveInterval);
|
|
2792
|
+
};
|
|
2793
|
+
cleanupFns.push(() => {
|
|
2794
|
+
if (saveTimer) clearTimeout(saveTimer);
|
|
2795
|
+
});
|
|
2796
|
+
void debouncedSave;
|
|
2797
|
+
}
|
|
2798
|
+
return () => {
|
|
2799
|
+
cleanupFns.forEach((fn) => fn());
|
|
2800
|
+
};
|
|
2801
|
+
}
|
|
2802
|
+
function generateTauriConfig(config) {
|
|
2803
|
+
return {
|
|
2804
|
+
$schema: "https://raw.githubusercontent.com/tauri-apps/tauri/tauri-v2.0.0/core/tauri-config-schema/schema.json",
|
|
2805
|
+
productName: config.name,
|
|
2806
|
+
version: config.version,
|
|
2807
|
+
identifier: config.identifier,
|
|
2808
|
+
app: {
|
|
2809
|
+
windows: [
|
|
2810
|
+
{
|
|
2811
|
+
title: config.window?.title || config.name,
|
|
2812
|
+
width: config.window?.width || 800,
|
|
2813
|
+
height: config.window?.height || 600,
|
|
2814
|
+
minWidth: config.window?.minWidth,
|
|
2815
|
+
minHeight: config.window?.minHeight,
|
|
2816
|
+
resizable: config.window?.resizable ?? true,
|
|
2817
|
+
fullscreen: config.window?.fullscreen ?? false,
|
|
2818
|
+
decorations: config.window?.decorations ?? true,
|
|
2819
|
+
transparent: config.window?.transparent ?? false,
|
|
2820
|
+
alwaysOnTop: config.window?.alwaysOnTop ?? false,
|
|
2821
|
+
center: config.window?.center ?? true
|
|
2822
|
+
}
|
|
2823
|
+
],
|
|
2824
|
+
security: {
|
|
2825
|
+
csp: config.security?.csp || "default-src 'self'",
|
|
2826
|
+
devtools: config.security?.devTools ?? false
|
|
2827
|
+
}
|
|
2828
|
+
},
|
|
2829
|
+
build: {
|
|
2830
|
+
devUrl: "http://localhost:5173",
|
|
2831
|
+
frontendDist: "../dist"
|
|
2832
|
+
},
|
|
2833
|
+
plugins: Object.fromEntries((config.plugins || []).map((p) => [p.name, p.config || {}]))
|
|
2834
|
+
};
|
|
2835
|
+
}
|
|
2836
|
+
export {
|
|
2837
|
+
ActorManager,
|
|
2838
|
+
InMemoryPraxisDB,
|
|
2839
|
+
LogicEngine,
|
|
2840
|
+
PRAXIS_PATHS,
|
|
2841
|
+
PRAXIS_PROTOCOL_VERSION,
|
|
2842
|
+
PluresDBGenerator,
|
|
2843
|
+
PraxisDBStore,
|
|
2844
|
+
PraxisRegistry,
|
|
2845
|
+
PraxisSchemaRegistry,
|
|
2846
|
+
ReactiveLogicEngine,
|
|
2847
|
+
RegistryIntrospector,
|
|
2848
|
+
StateDocsGenerator,
|
|
2849
|
+
attachTauriToEngine,
|
|
2850
|
+
attachToEngine,
|
|
2851
|
+
attachUnumToEngine,
|
|
2852
|
+
canvasToMermaid,
|
|
2853
|
+
canvasToSchema,
|
|
2854
|
+
canvasToYaml,
|
|
2855
|
+
createCanvasEditor,
|
|
2856
|
+
createInMemoryDB,
|
|
2857
|
+
createIntrospector,
|
|
2858
|
+
createMockTauriBridge,
|
|
2859
|
+
createPluresDBAdapter,
|
|
2860
|
+
createPluresDBGenerator,
|
|
2861
|
+
createPraxisDBStore,
|
|
2862
|
+
createPraxisEngine,
|
|
2863
|
+
createSchema,
|
|
2864
|
+
createSchemaRegistry,
|
|
2865
|
+
createSchemaTemplate,
|
|
2866
|
+
createStateDocsGenerator,
|
|
2867
|
+
createTauriPraxisAdapter,
|
|
2868
|
+
createTimerActor,
|
|
2869
|
+
createUnumAdapter,
|
|
2870
|
+
defineConstraint,
|
|
2871
|
+
defineEvent,
|
|
2872
|
+
defineFact,
|
|
2873
|
+
defineModule,
|
|
2874
|
+
defineRule,
|
|
2875
|
+
filterEvents,
|
|
2876
|
+
filterFacts,
|
|
2877
|
+
findEvent,
|
|
2878
|
+
findFact,
|
|
2879
|
+
generateDocs,
|
|
2880
|
+
generateId,
|
|
2881
|
+
generateTauriConfig,
|
|
2882
|
+
getEventPath,
|
|
2883
|
+
getFactPath,
|
|
2884
|
+
getSchemaPath,
|
|
2885
|
+
loadSchemaFromJson,
|
|
2886
|
+
loadSchemaFromYaml,
|
|
2887
|
+
registerSchema,
|
|
2888
|
+
schemaToCanvas,
|
|
2889
|
+
validateForGeneration,
|
|
2890
|
+
validateSchema,
|
|
2891
|
+
validateWithGuardian
|
|
2892
|
+
};
|