@plures/praxis 0.2.1 → 1.0.1

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