@plures/praxis 1.1.2 → 1.2.0

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 (49) hide show
  1. package/FRAMEWORK.md +106 -15
  2. package/README.md +275 -53
  3. package/dist/browser/adapter-TM4IS5KT.js +12 -0
  4. package/dist/browser/chunk-JQ64KMLN.js +141 -0
  5. package/dist/browser/chunk-LE2ZJYFC.js +154 -0
  6. package/dist/browser/chunk-VOMLVI6V.js +197 -0
  7. package/dist/browser/engine-YJZV4SLD.js +8 -0
  8. package/dist/browser/index.d.ts +300 -11
  9. package/dist/browser/index.js +334 -325
  10. package/dist/browser/integrations/svelte.d.ts +3 -1
  11. package/dist/browser/integrations/svelte.js +8 -0
  12. package/dist/browser/{engine-BjdqxeXG.d.ts → reactive-engine.svelte-C9OpcTHf.d.ts} +87 -1
  13. package/dist/node/adapter-K6DOX6XS.js +13 -0
  14. package/dist/node/chunk-JQ64KMLN.js +141 -0
  15. package/dist/node/chunk-LE2ZJYFC.js +154 -0
  16. package/dist/node/chunk-S54337I5.js +446 -0
  17. package/dist/node/chunk-VOMLVI6V.js +197 -0
  18. package/dist/node/cli/index.cjs +1444 -889
  19. package/dist/node/cli/index.js +9 -0
  20. package/dist/node/components/index.d.cts +2 -2
  21. package/dist/node/components/index.d.ts +2 -2
  22. package/dist/node/docs-JFNYTOJA.js +102 -0
  23. package/dist/node/engine-2DQBKBJC.js +9 -0
  24. package/dist/node/index.cjs +747 -234
  25. package/dist/node/index.d.cts +237 -15
  26. package/dist/node/index.d.ts +237 -15
  27. package/dist/node/index.js +339 -767
  28. package/dist/node/integrations/svelte.cjs +357 -2
  29. package/dist/node/integrations/svelte.d.cts +3 -1
  30. package/dist/node/integrations/svelte.d.ts +3 -1
  31. package/dist/node/integrations/svelte.js +7 -0
  32. package/dist/node/{engine-CVJobhHm.d.cts → reactive-engine.svelte-1M4m_C_v.d.cts} +87 -1
  33. package/dist/node/{engine-1iqLe6_P.d.ts → reactive-engine.svelte-ChNFn4Hj.d.ts} +87 -1
  34. package/dist/node/{terminal-adapter-XLtCjjb_.d.cts → terminal-adapter-CDzxoLKR.d.cts} +68 -1
  35. package/dist/node/{terminal-adapter-07HGftGQ.d.ts → terminal-adapter-CWka-yL8.d.ts} +68 -1
  36. package/package.json +3 -2
  37. package/src/__tests__/reactive-engine.test.ts +516 -0
  38. package/src/cli/commands/docs.ts +147 -0
  39. package/src/cli/index.ts +21 -0
  40. package/src/core/pluresdb/README.md +156 -0
  41. package/src/core/pluresdb/adapter.ts +165 -0
  42. package/src/core/pluresdb/index.ts +3 -3
  43. package/src/core/reactive-engine.svelte.ts +93 -19
  44. package/src/core/reactive-engine.ts +284 -22
  45. package/src/index.browser.ts +16 -0
  46. package/src/index.ts +16 -0
  47. package/src/integrations/pluresdb.ts +2 -2
  48. package/src/integrations/svelte.ts +8 -0
  49. package/src/integrations/unified.ts +350 -0
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Unified Integration Helpers
3
+ *
4
+ * Convenience functions for setting up Praxis with all ecosystem integrations
5
+ * (PluresDB, Unum, State-Docs, CodeCanvas) in a single call.
6
+ */
7
+
8
+ import type { LogicEngine } from '../core/engine.js';
9
+ import type { PraxisRegistry, PraxisModule } from '../core/rules.js';
10
+ import type { PraxisSchema } from '../core/schema/types.js';
11
+ import type { PraxisDB, UnsubscribeFn } from '../core/pluresdb/adapter.js';
12
+ import type { UnumIdentity } from './unum.js';
13
+ import {
14
+ createPluresDBAdapter,
15
+ generateId,
16
+ type PluresDBAdapter,
17
+ } from './pluresdb.js';
18
+ import {
19
+ createUnumAdapter,
20
+ attachUnumToEngine,
21
+ type UnumAdapter,
22
+ type UnumChannel,
23
+ } from './unum.js';
24
+ import {
25
+ createStateDocsGenerator,
26
+ type StateDocsGenerator,
27
+ type GeneratedDoc,
28
+ } from './state-docs.js';
29
+ import {
30
+ schemaToCanvas,
31
+ type CanvasDocument,
32
+ } from './code-canvas.js';
33
+
34
+ /**
35
+ * Configuration for unified Praxis application
36
+ */
37
+ export interface UnifiedAppConfig<TContext = unknown> {
38
+ /** Praxis registry with rules and constraints */
39
+ registry: PraxisRegistry<TContext>;
40
+
41
+ /** Initial context for the engine */
42
+ initialContext: TContext;
43
+
44
+ /** PluresDB instance (if not provided, creates in-memory DB) */
45
+ db?: PraxisDB;
46
+
47
+ /** Enable Unum for distributed communication */
48
+ enableUnum?: boolean;
49
+
50
+ /** Unum identity configuration (without id and createdAt which are auto-generated) */
51
+ unumIdentity?: Omit<UnumIdentity, 'id' | 'createdAt'>;
52
+
53
+ /** Enable State-Docs documentation generation */
54
+ enableDocs?: boolean;
55
+
56
+ /** State-Docs configuration */
57
+ docsConfig?: {
58
+ projectTitle: string;
59
+ target?: string;
60
+ };
61
+
62
+ /** Praxis schema for CodeCanvas integration */
63
+ schema?: PraxisSchema;
64
+ }
65
+
66
+ /**
67
+ * Unified application instance with all integrations
68
+ */
69
+ export interface UnifiedApp<TContext = unknown> {
70
+ /** Praxis logic engine */
71
+ engine: LogicEngine<TContext>;
72
+
73
+ /** PluresDB adapter for persistence */
74
+ pluresdb: PluresDBAdapter<TContext>;
75
+
76
+ /** Unum adapter for distributed communication (if enabled) */
77
+ unum?: UnumAdapter;
78
+
79
+ /** Default Unum channel (if Unum enabled) */
80
+ channel?: UnumChannel;
81
+
82
+ /** State-Docs generator (if enabled) */
83
+ docs?: StateDocsGenerator;
84
+
85
+ /** CodeCanvas document (if schema provided) */
86
+ canvas?: CanvasDocument;
87
+
88
+ /** Generate documentation from current state */
89
+ generateDocs?: () => GeneratedDoc[];
90
+
91
+ /** Cleanup function to dispose all integrations */
92
+ dispose: () => void;
93
+ }
94
+
95
+ /**
96
+ * Create a unified Praxis application with all integrations
97
+ *
98
+ * This is a convenience function that sets up:
99
+ * - Praxis logic engine
100
+ * - PluresDB for persistence (auto-attaches to engine)
101
+ * - Unum for distributed communication (optional)
102
+ * - State-Docs for documentation generation (optional)
103
+ * - CodeCanvas for visual schema editing (optional)
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * import { createUnifiedApp } from '@plures/praxis';
108
+ *
109
+ * const app = await createUnifiedApp({
110
+ * registry: myRegistry,
111
+ * initialContext: { count: 0 },
112
+ * enableUnum: true,
113
+ * unumIdentity: { name: 'node-1' },
114
+ * enableDocs: true,
115
+ * docsConfig: { projectTitle: 'My App' },
116
+ * schema: mySchema,
117
+ * });
118
+ *
119
+ * // Use the engine
120
+ * app.engine.step([myEvent]);
121
+ *
122
+ * // Broadcast to other nodes
123
+ * if (app.channel) {
124
+ * await app.unum?.broadcastEvent(app.channel.id, myEvent);
125
+ * }
126
+ *
127
+ * // Generate documentation
128
+ * const docs = app.generateDocs?.();
129
+ *
130
+ * // Cleanup
131
+ * app.dispose();
132
+ * ```
133
+ */
134
+ export async function createUnifiedApp<TContext = unknown>(
135
+ config: UnifiedAppConfig<TContext>
136
+ ): Promise<UnifiedApp<TContext>> {
137
+ const { createPraxisEngine } = await import('../core/engine.js');
138
+ const { createInMemoryDB } = await import('../core/pluresdb/adapter.js');
139
+
140
+ // Create database if not provided
141
+ const db = config.db || createInMemoryDB();
142
+
143
+ // Create PluresDB adapter
144
+ const pluresdb = createPluresDBAdapter({
145
+ db,
146
+ registry: config.registry,
147
+ initialContext: config.initialContext,
148
+ });
149
+
150
+ // Create Praxis engine
151
+ const engine = createPraxisEngine({
152
+ initialContext: config.initialContext,
153
+ registry: config.registry,
154
+ });
155
+
156
+ // Attach PluresDB to engine
157
+ pluresdb.attachEngine(engine);
158
+
159
+ const disposers: UnsubscribeFn[] = [];
160
+
161
+ // Setup Unum if enabled
162
+ let unum: UnumAdapter | undefined;
163
+ let channel: UnumChannel | undefined;
164
+ if (config.enableUnum) {
165
+ // Convert partial identity to full identity if provided
166
+ const fullIdentity: UnumIdentity | undefined = config.unumIdentity
167
+ ? {
168
+ ...config.unumIdentity,
169
+ id: generateId(),
170
+ createdAt: Date.now(),
171
+ }
172
+ : undefined;
173
+
174
+ unum = await createUnumAdapter({
175
+ db,
176
+ identity: fullIdentity,
177
+ realtime: true,
178
+ });
179
+
180
+ // Create default channel
181
+ channel = await unum.createChannel(
182
+ config.unumIdentity?.name || 'praxis-app',
183
+ []
184
+ );
185
+
186
+ // Attach Unum to engine
187
+ const unumDisposer = attachUnumToEngine(engine, unum, channel.id);
188
+ disposers.push(unumDisposer);
189
+ }
190
+
191
+ // Setup State-Docs if enabled
192
+ let docs: StateDocsGenerator | undefined;
193
+ let generateDocs: (() => GeneratedDoc[]) | undefined;
194
+ if (config.enableDocs && config.docsConfig) {
195
+ docs = createStateDocsGenerator({
196
+ projectTitle: config.docsConfig.projectTitle,
197
+ target: config.docsConfig.target || './docs',
198
+ });
199
+
200
+ generateDocs = () => {
201
+ // Get rules and constraints from registry
202
+ const module: PraxisModule<TContext> = {
203
+ rules: config.registry.getAllRules(),
204
+ constraints: config.registry.getAllConstraints(),
205
+ };
206
+ return docs!.generateFromModule(module);
207
+ };
208
+ }
209
+
210
+ // Setup CodeCanvas if schema provided
211
+ let canvas: CanvasDocument | undefined;
212
+ if (config.schema) {
213
+ // Convert PraxisSchema to PSFSchema format expected by schemaToCanvas
214
+ // Both types are structurally compatible, so we can safely cast
215
+ canvas = schemaToCanvas(config.schema as unknown as import('../../core/schema-engine/psf.js').PSFSchema, { layout: 'hierarchical' });
216
+ }
217
+
218
+ return {
219
+ engine,
220
+ pluresdb,
221
+ unum,
222
+ channel,
223
+ docs,
224
+ canvas,
225
+ generateDocs,
226
+ dispose: () => {
227
+ pluresdb.dispose();
228
+ if (unum) {
229
+ // Disconnect from Unum, log errors during cleanup
230
+ unum.disconnect().catch((err) => {
231
+ console.warn('Warning: Error during Unum disconnect:', err);
232
+ });
233
+ }
234
+ for (const disposer of disposers) {
235
+ disposer();
236
+ }
237
+ },
238
+ };
239
+ }
240
+
241
+ /**
242
+ * Attach all available integrations to an existing Praxis engine
243
+ *
244
+ * This is useful when you already have an engine and want to add integrations.
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * import { createPraxisEngine, attachAllIntegrations } from '@plures/praxis';
249
+ *
250
+ * const engine = createPraxisEngine({ initialContext: {}, registry });
251
+ *
252
+ * const integrations = await attachAllIntegrations(engine, registry, {
253
+ * enableUnum: true,
254
+ * enableDocs: true,
255
+ * });
256
+ *
257
+ * // Later cleanup
258
+ * integrations.dispose();
259
+ * ```
260
+ */
261
+ export async function attachAllIntegrations<TContext = unknown>(
262
+ engine: LogicEngine<TContext>,
263
+ registry: PraxisRegistry<TContext>,
264
+ options: {
265
+ db?: PraxisDB;
266
+ enableUnum?: boolean;
267
+ unumIdentity?: Omit<UnumIdentity, 'id' | 'createdAt'>;
268
+ enableDocs?: boolean;
269
+ docsConfig?: { projectTitle: string; target?: string };
270
+ } = {}
271
+ ): Promise<{
272
+ pluresdb: PluresDBAdapter<TContext>;
273
+ unum?: UnumAdapter;
274
+ channel?: UnumChannel;
275
+ docs?: StateDocsGenerator;
276
+ dispose: () => void;
277
+ }> {
278
+ const { createInMemoryDB } = await import('../core/pluresdb/adapter.js');
279
+
280
+ // Create database if not provided
281
+ const db = options.db || createInMemoryDB();
282
+
283
+ // Create PluresDB adapter
284
+ const pluresdb = createPluresDBAdapter({
285
+ db,
286
+ registry,
287
+ initialContext: engine.getContext(),
288
+ });
289
+
290
+ // Attach PluresDB to engine
291
+ pluresdb.attachEngine(engine);
292
+
293
+ const disposers: UnsubscribeFn[] = [];
294
+
295
+ // Setup Unum if enabled
296
+ let unum: UnumAdapter | undefined;
297
+ let channel: UnumChannel | undefined;
298
+ if (options.enableUnum) {
299
+ // Convert partial identity to full identity if provided
300
+ const fullIdentity: UnumIdentity | undefined = options.unumIdentity
301
+ ? {
302
+ ...options.unumIdentity,
303
+ id: generateId(),
304
+ createdAt: Date.now(),
305
+ }
306
+ : undefined;
307
+
308
+ unum = await createUnumAdapter({
309
+ db,
310
+ identity: fullIdentity,
311
+ realtime: true,
312
+ });
313
+
314
+ channel = await unum.createChannel(
315
+ options.unumIdentity?.name || 'praxis-app',
316
+ []
317
+ );
318
+
319
+ const unumDisposer = attachUnumToEngine(engine, unum, channel.id);
320
+ disposers.push(unumDisposer);
321
+ }
322
+
323
+ // Setup State-Docs if enabled
324
+ let docs: StateDocsGenerator | undefined;
325
+ if (options.enableDocs && options.docsConfig) {
326
+ docs = createStateDocsGenerator({
327
+ projectTitle: options.docsConfig.projectTitle,
328
+ target: options.docsConfig.target || './docs',
329
+ });
330
+ }
331
+
332
+ return {
333
+ pluresdb,
334
+ unum,
335
+ channel,
336
+ docs,
337
+ dispose: () => {
338
+ pluresdb.dispose();
339
+ if (unum) {
340
+ // Disconnect from Unum, log errors during cleanup
341
+ unum.disconnect().catch((err) => {
342
+ console.warn('Warning: Error during Unum disconnect:', err);
343
+ });
344
+ }
345
+ for (const disposer of disposers) {
346
+ disposer();
347
+ }
348
+ },
349
+ };
350
+ }