@plures/praxis 1.4.4 → 2.0.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.
- package/dist/browser/chunk-6MVRT7CK.js +363 -0
- package/dist/browser/factory/index.d.ts +2 -1
- package/dist/browser/index.d.ts +7 -4
- package/dist/browser/index.js +18 -6
- package/dist/browser/integrations/svelte.d.ts +4 -3
- package/dist/browser/project/index.d.ts +2 -1
- package/dist/browser/{reactive-engine.svelte-DgVTqHLc.d.ts → reactive-engine.svelte-BwWadvAW.d.ts} +2 -1
- package/dist/browser/rule-result-DcXWe9tn.d.ts +206 -0
- package/dist/browser/{rules-i1LHpnGd.d.ts → rules-BaWMqxuG.d.ts} +2 -205
- package/dist/browser/unified/index.d.ts +239 -0
- package/dist/browser/unified/index.js +20 -0
- package/dist/node/chunk-6MVRT7CK.js +363 -0
- package/dist/node/cli/index.js +1 -1
- package/dist/node/index.cjs +367 -0
- package/dist/node/index.d.cts +4 -2
- package/dist/node/index.d.ts +4 -2
- package/dist/node/index.js +19 -7
- package/dist/node/integrations/svelte.d.cts +3 -2
- package/dist/node/integrations/svelte.d.ts +3 -2
- package/dist/node/integrations/svelte.js +2 -2
- package/dist/node/{reactive-engine.svelte-DekxqFu0.d.ts → reactive-engine.svelte-BBZLMzus.d.ts} +3 -79
- package/dist/node/{reactive-engine.svelte-Cg0Yc2Hs.d.cts → reactive-engine.svelte-Cbq_V20o.d.cts} +3 -79
- package/dist/node/rule-result-B9GMivAn.d.cts +80 -0
- package/dist/node/rule-result-Bo3sFMmN.d.ts +80 -0
- package/dist/node/unified/index.cjs +484 -0
- package/dist/node/unified/index.d.cts +240 -0
- package/dist/node/unified/index.d.ts +240 -0
- package/dist/node/unified/index.js +21 -0
- package/package.json +7 -1
- package/src/index.browser.ts +20 -0
- package/src/index.ts +21 -0
- package/src/unified/__tests__/unified.test.ts +396 -0
- package/src/unified/core.ts +517 -0
- package/src/unified/index.ts +32 -0
- package/src/unified/rules.ts +66 -0
- package/src/unified/types.ts +148 -0
- package/dist/node/{chunk-ZO2LU4G4.js → chunk-WFRHXZBP.js} +3 -3
- package/dist/node/{validate-5PSWJTIC.js → validate-BY7JNY7H.js} +1 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { R as RuleResult } from '../rule-result-B9GMivAn.cjs';
|
|
2
|
+
export { f as fact } from '../rule-result-B9GMivAn.cjs';
|
|
3
|
+
import { e as PraxisDiagnostics, b as PraxisFact } from '../protocol-DcyGMmWY.cjs';
|
|
4
|
+
|
|
5
|
+
/** Minimal store contract — anything with subscribe() */
|
|
6
|
+
interface Subscribable<T> {
|
|
7
|
+
subscribe(cb: (value: T) => void): (() => void) | {
|
|
8
|
+
unsubscribe(): void;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/** Schema definition for a graph path */
|
|
12
|
+
interface PathSchema<T = unknown> {
|
|
13
|
+
/** The graph path (e.g., 'sprint/current') */
|
|
14
|
+
path: string;
|
|
15
|
+
/** Default/initial value */
|
|
16
|
+
initial: T;
|
|
17
|
+
/** Optional TTL for staleness detection (ms) */
|
|
18
|
+
staleTtl?: number;
|
|
19
|
+
/** Whether this path is a collection (maps over children) */
|
|
20
|
+
collection?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Define a typed graph path.
|
|
24
|
+
* This is the primary API for declaring what data exists in your app.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* const Sprint = definePath<SprintInfo | null>('sprint/current', null);
|
|
28
|
+
* const Items = definePath<WorkItem[]>('sprint/items', [], { collection: true });
|
|
29
|
+
* const Loading = definePath<boolean>('sprint/loading', false);
|
|
30
|
+
*/
|
|
31
|
+
declare function definePath<T>(path: string, initial: T, opts?: Omit<PathSchema<T>, 'path' | 'initial'>): PathSchema<T>;
|
|
32
|
+
interface QueryOptions<T> {
|
|
33
|
+
/** Filter function for collections */
|
|
34
|
+
where?: (item: T extends (infer U)[] ? U : T) => boolean;
|
|
35
|
+
/** Select/map function */
|
|
36
|
+
select?: (item: T) => unknown;
|
|
37
|
+
/** Sort comparator */
|
|
38
|
+
sort?: (a: any, b: any) => number;
|
|
39
|
+
/** Limit results */
|
|
40
|
+
limit?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A reactive reference returned by query().
|
|
44
|
+
* Has a Svelte-compatible subscribe() and a .current getter.
|
|
45
|
+
*/
|
|
46
|
+
interface ReactiveRef<T> extends Subscribable<T> {
|
|
47
|
+
/** Current value (synchronous read) */
|
|
48
|
+
readonly current: T;
|
|
49
|
+
/** Svelte store contract — subscribe returns unsubscribe fn */
|
|
50
|
+
subscribe(cb: (value: T) => void): () => void;
|
|
51
|
+
}
|
|
52
|
+
interface MutationResult {
|
|
53
|
+
/** Whether the mutation was accepted */
|
|
54
|
+
accepted: boolean;
|
|
55
|
+
/** Constraint violations that blocked the mutation (if any) */
|
|
56
|
+
violations: PraxisDiagnostics[];
|
|
57
|
+
/** Facts emitted by rules triggered by this mutation */
|
|
58
|
+
facts: PraxisFact[];
|
|
59
|
+
}
|
|
60
|
+
interface UnifiedRule {
|
|
61
|
+
/** Unique rule ID */
|
|
62
|
+
id: string;
|
|
63
|
+
/** Human-readable description */
|
|
64
|
+
description?: string;
|
|
65
|
+
/** Graph paths this rule watches — auto-subscribed */
|
|
66
|
+
watch: string[];
|
|
67
|
+
/** Rule evaluation function — receives watched values by path */
|
|
68
|
+
evaluate: (values: Record<string, any>, facts: PraxisFact[]) => RuleResult;
|
|
69
|
+
}
|
|
70
|
+
interface UnifiedConstraint {
|
|
71
|
+
/** Unique constraint ID */
|
|
72
|
+
id: string;
|
|
73
|
+
/** Human-readable description */
|
|
74
|
+
description?: string;
|
|
75
|
+
/** Graph paths this constraint reads */
|
|
76
|
+
watch: string[];
|
|
77
|
+
/** Validation function — return true if valid, string if violated */
|
|
78
|
+
validate: (values: Record<string, any>) => true | string;
|
|
79
|
+
}
|
|
80
|
+
interface LivenessConfig {
|
|
81
|
+
/** Paths that must update within `timeoutMs` after init */
|
|
82
|
+
expect: string[];
|
|
83
|
+
/** Milliseconds to wait before flagging staleness (default: 5000) */
|
|
84
|
+
timeoutMs?: number;
|
|
85
|
+
/** Callback when a path is stale */
|
|
86
|
+
onStale?: (path: string, elapsed: number) => void;
|
|
87
|
+
}
|
|
88
|
+
interface PraxisAppConfig {
|
|
89
|
+
/** App name (used in Chronos context) */
|
|
90
|
+
name: string;
|
|
91
|
+
/** Graph schema — all paths the app uses */
|
|
92
|
+
schema: PathSchema[];
|
|
93
|
+
/** Business rules */
|
|
94
|
+
rules?: UnifiedRule[];
|
|
95
|
+
/** Constraints */
|
|
96
|
+
constraints?: UnifiedConstraint[];
|
|
97
|
+
/** Liveness monitoring */
|
|
98
|
+
liveness?: LivenessConfig;
|
|
99
|
+
/** Chronos options */
|
|
100
|
+
chronos?: {
|
|
101
|
+
batchMs?: number;
|
|
102
|
+
maxBatch?: number;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Praxis Unified Reactive Layer — Core
|
|
108
|
+
*
|
|
109
|
+
* createApp() → query() / mutate()
|
|
110
|
+
*
|
|
111
|
+
* The developer defines a schema + rules. Praxis handles:
|
|
112
|
+
* - Reactive state (backed by Unum graph DB)
|
|
113
|
+
* - Automatic rule evaluation on state changes
|
|
114
|
+
* - Constraint enforcement on mutations
|
|
115
|
+
* - Chronos logging for every state change
|
|
116
|
+
* - Liveness monitoring (detect broken plumbing)
|
|
117
|
+
* - Svelte-compatible store contract
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
interface TimelineEntry {
|
|
121
|
+
id: string;
|
|
122
|
+
timestamp: number;
|
|
123
|
+
path: string;
|
|
124
|
+
kind: 'mutation' | 'rule-eval' | 'constraint-check' | 'liveness';
|
|
125
|
+
data: Record<string, unknown>;
|
|
126
|
+
}
|
|
127
|
+
interface PraxisApp {
|
|
128
|
+
/** Reactive query — returns a Svelte-compatible store */
|
|
129
|
+
query: <T>(path: string, opts?: QueryOptions<T>) => ReactiveRef<T>;
|
|
130
|
+
/** Write to the graph — validates through constraints first */
|
|
131
|
+
mutate: (path: string, value: unknown) => MutationResult;
|
|
132
|
+
/** Batch multiple mutations atomically */
|
|
133
|
+
batch: (fn: (mutate: (path: string, value: unknown) => void) => void) => MutationResult;
|
|
134
|
+
/** Current facts */
|
|
135
|
+
facts: () => PraxisFact[];
|
|
136
|
+
/** Current constraint violations */
|
|
137
|
+
violations: () => PraxisDiagnostics[];
|
|
138
|
+
/** Timeline (Chronos entries) */
|
|
139
|
+
timeline: () => TimelineEntry[];
|
|
140
|
+
/** Force re-evaluate all rules */
|
|
141
|
+
evaluate: () => void;
|
|
142
|
+
/** Cleanup */
|
|
143
|
+
destroy: () => void;
|
|
144
|
+
/** Liveness status — which paths are stale */
|
|
145
|
+
liveness: () => Record<string, {
|
|
146
|
+
stale: boolean;
|
|
147
|
+
lastUpdated: number;
|
|
148
|
+
elapsed: number;
|
|
149
|
+
}>;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Create a Praxis application.
|
|
153
|
+
*
|
|
154
|
+
* This is the single entry point. It creates the reactive graph,
|
|
155
|
+
* wires rules and constraints, starts Chronos logging, and returns
|
|
156
|
+
* query() and mutate() — the only two functions a developer needs.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { createApp, definePath, defineRule } from '@plures/praxis';
|
|
161
|
+
*
|
|
162
|
+
* const Sprint = definePath<SprintInfo | null>('sprint/current', null);
|
|
163
|
+
* const Loading = definePath<boolean>('sprint/loading', false);
|
|
164
|
+
*
|
|
165
|
+
* const app = createApp({
|
|
166
|
+
* name: 'sprint-log',
|
|
167
|
+
* schema: [Sprint, Loading],
|
|
168
|
+
* rules: [sprintBehindRule, capacityRule],
|
|
169
|
+
* constraints: [noCloseWithoutHoursConstraint],
|
|
170
|
+
* });
|
|
171
|
+
*
|
|
172
|
+
* // In a Svelte component:
|
|
173
|
+
* const sprint = app.query<SprintInfo | null>('sprint/current');
|
|
174
|
+
* // $sprint is reactive — updates automatically
|
|
175
|
+
*
|
|
176
|
+
* // To write:
|
|
177
|
+
* app.mutate('sprint/current', sprintData);
|
|
178
|
+
* // Constraints validated, rules re-evaluated, Chronos logged — all automatic
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
declare function createApp(config: PraxisAppConfig): PraxisApp;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Praxis Unified — Rule DSL helpers
|
|
185
|
+
*
|
|
186
|
+
* Developers define rules as plain objects with watch paths.
|
|
187
|
+
* No manual subscriptions, no wirePraxis(), no context mapping.
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Define a rule that watches graph paths and auto-evaluates.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* const sprintBehind = defineRule({
|
|
195
|
+
* id: 'sprint.behind',
|
|
196
|
+
* watch: ['sprint/current'],
|
|
197
|
+
* evaluate: (values) => {
|
|
198
|
+
* const sprint = values['sprint/current'];
|
|
199
|
+
* if (!sprint) return RuleResult.skip('No sprint');
|
|
200
|
+
* const pace = sprint.currentDay / sprint.totalDays;
|
|
201
|
+
* const work = sprint.completedHours / sprint.totalHours;
|
|
202
|
+
* if (work >= pace) return RuleResult.retract(['sprint.behind']);
|
|
203
|
+
* return RuleResult.emit([fact('sprint.behind', { pace, work })]);
|
|
204
|
+
* }
|
|
205
|
+
* });
|
|
206
|
+
*/
|
|
207
|
+
declare function defineRule(rule: UnifiedRule): UnifiedRule;
|
|
208
|
+
/**
|
|
209
|
+
* Define a constraint that validates mutations before they're applied.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* const noCloseWithoutHours = defineConstraint({
|
|
213
|
+
* id: 'no-close-without-hours',
|
|
214
|
+
* description: 'Cannot close a work item with 0 completed hours',
|
|
215
|
+
* watch: ['sprint/items'],
|
|
216
|
+
* validate: (values) => {
|
|
217
|
+
* const items = values['sprint/items'] ?? [];
|
|
218
|
+
* const bad = items.find(i => i.state === 'Closed' && !i.completedWork);
|
|
219
|
+
* if (bad) return `Item #${bad.id} cannot be closed with 0 hours`;
|
|
220
|
+
* return true;
|
|
221
|
+
* }
|
|
222
|
+
* });
|
|
223
|
+
*/
|
|
224
|
+
declare function defineConstraint(constraint: UnifiedConstraint): UnifiedConstraint;
|
|
225
|
+
/**
|
|
226
|
+
* Compose multiple rules into a named module.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* const sprintModule = defineModule('sprint-health', [
|
|
230
|
+
* sprintBehindRule,
|
|
231
|
+
* capacityRule,
|
|
232
|
+
* endNearRule,
|
|
233
|
+
* ]);
|
|
234
|
+
*/
|
|
235
|
+
declare function defineModule(name: string, rules: UnifiedRule[]): {
|
|
236
|
+
name: string;
|
|
237
|
+
rules: UnifiedRule[];
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
export { type LivenessConfig, type MutationResult, type PathSchema, type PraxisApp, type PraxisAppConfig, type QueryOptions, type ReactiveRef, RuleResult, type UnifiedConstraint, type UnifiedRule, createApp, defineConstraint, defineModule, definePath, defineRule };
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { R as RuleResult } from '../rule-result-Bo3sFMmN.js';
|
|
2
|
+
export { f as fact } from '../rule-result-Bo3sFMmN.js';
|
|
3
|
+
import { e as PraxisDiagnostics, b as PraxisFact } from '../protocol-DcyGMmWY.js';
|
|
4
|
+
|
|
5
|
+
/** Minimal store contract — anything with subscribe() */
|
|
6
|
+
interface Subscribable<T> {
|
|
7
|
+
subscribe(cb: (value: T) => void): (() => void) | {
|
|
8
|
+
unsubscribe(): void;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/** Schema definition for a graph path */
|
|
12
|
+
interface PathSchema<T = unknown> {
|
|
13
|
+
/** The graph path (e.g., 'sprint/current') */
|
|
14
|
+
path: string;
|
|
15
|
+
/** Default/initial value */
|
|
16
|
+
initial: T;
|
|
17
|
+
/** Optional TTL for staleness detection (ms) */
|
|
18
|
+
staleTtl?: number;
|
|
19
|
+
/** Whether this path is a collection (maps over children) */
|
|
20
|
+
collection?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Define a typed graph path.
|
|
24
|
+
* This is the primary API for declaring what data exists in your app.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* const Sprint = definePath<SprintInfo | null>('sprint/current', null);
|
|
28
|
+
* const Items = definePath<WorkItem[]>('sprint/items', [], { collection: true });
|
|
29
|
+
* const Loading = definePath<boolean>('sprint/loading', false);
|
|
30
|
+
*/
|
|
31
|
+
declare function definePath<T>(path: string, initial: T, opts?: Omit<PathSchema<T>, 'path' | 'initial'>): PathSchema<T>;
|
|
32
|
+
interface QueryOptions<T> {
|
|
33
|
+
/** Filter function for collections */
|
|
34
|
+
where?: (item: T extends (infer U)[] ? U : T) => boolean;
|
|
35
|
+
/** Select/map function */
|
|
36
|
+
select?: (item: T) => unknown;
|
|
37
|
+
/** Sort comparator */
|
|
38
|
+
sort?: (a: any, b: any) => number;
|
|
39
|
+
/** Limit results */
|
|
40
|
+
limit?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A reactive reference returned by query().
|
|
44
|
+
* Has a Svelte-compatible subscribe() and a .current getter.
|
|
45
|
+
*/
|
|
46
|
+
interface ReactiveRef<T> extends Subscribable<T> {
|
|
47
|
+
/** Current value (synchronous read) */
|
|
48
|
+
readonly current: T;
|
|
49
|
+
/** Svelte store contract — subscribe returns unsubscribe fn */
|
|
50
|
+
subscribe(cb: (value: T) => void): () => void;
|
|
51
|
+
}
|
|
52
|
+
interface MutationResult {
|
|
53
|
+
/** Whether the mutation was accepted */
|
|
54
|
+
accepted: boolean;
|
|
55
|
+
/** Constraint violations that blocked the mutation (if any) */
|
|
56
|
+
violations: PraxisDiagnostics[];
|
|
57
|
+
/** Facts emitted by rules triggered by this mutation */
|
|
58
|
+
facts: PraxisFact[];
|
|
59
|
+
}
|
|
60
|
+
interface UnifiedRule {
|
|
61
|
+
/** Unique rule ID */
|
|
62
|
+
id: string;
|
|
63
|
+
/** Human-readable description */
|
|
64
|
+
description?: string;
|
|
65
|
+
/** Graph paths this rule watches — auto-subscribed */
|
|
66
|
+
watch: string[];
|
|
67
|
+
/** Rule evaluation function — receives watched values by path */
|
|
68
|
+
evaluate: (values: Record<string, any>, facts: PraxisFact[]) => RuleResult;
|
|
69
|
+
}
|
|
70
|
+
interface UnifiedConstraint {
|
|
71
|
+
/** Unique constraint ID */
|
|
72
|
+
id: string;
|
|
73
|
+
/** Human-readable description */
|
|
74
|
+
description?: string;
|
|
75
|
+
/** Graph paths this constraint reads */
|
|
76
|
+
watch: string[];
|
|
77
|
+
/** Validation function — return true if valid, string if violated */
|
|
78
|
+
validate: (values: Record<string, any>) => true | string;
|
|
79
|
+
}
|
|
80
|
+
interface LivenessConfig {
|
|
81
|
+
/** Paths that must update within `timeoutMs` after init */
|
|
82
|
+
expect: string[];
|
|
83
|
+
/** Milliseconds to wait before flagging staleness (default: 5000) */
|
|
84
|
+
timeoutMs?: number;
|
|
85
|
+
/** Callback when a path is stale */
|
|
86
|
+
onStale?: (path: string, elapsed: number) => void;
|
|
87
|
+
}
|
|
88
|
+
interface PraxisAppConfig {
|
|
89
|
+
/** App name (used in Chronos context) */
|
|
90
|
+
name: string;
|
|
91
|
+
/** Graph schema — all paths the app uses */
|
|
92
|
+
schema: PathSchema[];
|
|
93
|
+
/** Business rules */
|
|
94
|
+
rules?: UnifiedRule[];
|
|
95
|
+
/** Constraints */
|
|
96
|
+
constraints?: UnifiedConstraint[];
|
|
97
|
+
/** Liveness monitoring */
|
|
98
|
+
liveness?: LivenessConfig;
|
|
99
|
+
/** Chronos options */
|
|
100
|
+
chronos?: {
|
|
101
|
+
batchMs?: number;
|
|
102
|
+
maxBatch?: number;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Praxis Unified Reactive Layer — Core
|
|
108
|
+
*
|
|
109
|
+
* createApp() → query() / mutate()
|
|
110
|
+
*
|
|
111
|
+
* The developer defines a schema + rules. Praxis handles:
|
|
112
|
+
* - Reactive state (backed by Unum graph DB)
|
|
113
|
+
* - Automatic rule evaluation on state changes
|
|
114
|
+
* - Constraint enforcement on mutations
|
|
115
|
+
* - Chronos logging for every state change
|
|
116
|
+
* - Liveness monitoring (detect broken plumbing)
|
|
117
|
+
* - Svelte-compatible store contract
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
interface TimelineEntry {
|
|
121
|
+
id: string;
|
|
122
|
+
timestamp: number;
|
|
123
|
+
path: string;
|
|
124
|
+
kind: 'mutation' | 'rule-eval' | 'constraint-check' | 'liveness';
|
|
125
|
+
data: Record<string, unknown>;
|
|
126
|
+
}
|
|
127
|
+
interface PraxisApp {
|
|
128
|
+
/** Reactive query — returns a Svelte-compatible store */
|
|
129
|
+
query: <T>(path: string, opts?: QueryOptions<T>) => ReactiveRef<T>;
|
|
130
|
+
/** Write to the graph — validates through constraints first */
|
|
131
|
+
mutate: (path: string, value: unknown) => MutationResult;
|
|
132
|
+
/** Batch multiple mutations atomically */
|
|
133
|
+
batch: (fn: (mutate: (path: string, value: unknown) => void) => void) => MutationResult;
|
|
134
|
+
/** Current facts */
|
|
135
|
+
facts: () => PraxisFact[];
|
|
136
|
+
/** Current constraint violations */
|
|
137
|
+
violations: () => PraxisDiagnostics[];
|
|
138
|
+
/** Timeline (Chronos entries) */
|
|
139
|
+
timeline: () => TimelineEntry[];
|
|
140
|
+
/** Force re-evaluate all rules */
|
|
141
|
+
evaluate: () => void;
|
|
142
|
+
/** Cleanup */
|
|
143
|
+
destroy: () => void;
|
|
144
|
+
/** Liveness status — which paths are stale */
|
|
145
|
+
liveness: () => Record<string, {
|
|
146
|
+
stale: boolean;
|
|
147
|
+
lastUpdated: number;
|
|
148
|
+
elapsed: number;
|
|
149
|
+
}>;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Create a Praxis application.
|
|
153
|
+
*
|
|
154
|
+
* This is the single entry point. It creates the reactive graph,
|
|
155
|
+
* wires rules and constraints, starts Chronos logging, and returns
|
|
156
|
+
* query() and mutate() — the only two functions a developer needs.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { createApp, definePath, defineRule } from '@plures/praxis';
|
|
161
|
+
*
|
|
162
|
+
* const Sprint = definePath<SprintInfo | null>('sprint/current', null);
|
|
163
|
+
* const Loading = definePath<boolean>('sprint/loading', false);
|
|
164
|
+
*
|
|
165
|
+
* const app = createApp({
|
|
166
|
+
* name: 'sprint-log',
|
|
167
|
+
* schema: [Sprint, Loading],
|
|
168
|
+
* rules: [sprintBehindRule, capacityRule],
|
|
169
|
+
* constraints: [noCloseWithoutHoursConstraint],
|
|
170
|
+
* });
|
|
171
|
+
*
|
|
172
|
+
* // In a Svelte component:
|
|
173
|
+
* const sprint = app.query<SprintInfo | null>('sprint/current');
|
|
174
|
+
* // $sprint is reactive — updates automatically
|
|
175
|
+
*
|
|
176
|
+
* // To write:
|
|
177
|
+
* app.mutate('sprint/current', sprintData);
|
|
178
|
+
* // Constraints validated, rules re-evaluated, Chronos logged — all automatic
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
declare function createApp(config: PraxisAppConfig): PraxisApp;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Praxis Unified — Rule DSL helpers
|
|
185
|
+
*
|
|
186
|
+
* Developers define rules as plain objects with watch paths.
|
|
187
|
+
* No manual subscriptions, no wirePraxis(), no context mapping.
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Define a rule that watches graph paths and auto-evaluates.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* const sprintBehind = defineRule({
|
|
195
|
+
* id: 'sprint.behind',
|
|
196
|
+
* watch: ['sprint/current'],
|
|
197
|
+
* evaluate: (values) => {
|
|
198
|
+
* const sprint = values['sprint/current'];
|
|
199
|
+
* if (!sprint) return RuleResult.skip('No sprint');
|
|
200
|
+
* const pace = sprint.currentDay / sprint.totalDays;
|
|
201
|
+
* const work = sprint.completedHours / sprint.totalHours;
|
|
202
|
+
* if (work >= pace) return RuleResult.retract(['sprint.behind']);
|
|
203
|
+
* return RuleResult.emit([fact('sprint.behind', { pace, work })]);
|
|
204
|
+
* }
|
|
205
|
+
* });
|
|
206
|
+
*/
|
|
207
|
+
declare function defineRule(rule: UnifiedRule): UnifiedRule;
|
|
208
|
+
/**
|
|
209
|
+
* Define a constraint that validates mutations before they're applied.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* const noCloseWithoutHours = defineConstraint({
|
|
213
|
+
* id: 'no-close-without-hours',
|
|
214
|
+
* description: 'Cannot close a work item with 0 completed hours',
|
|
215
|
+
* watch: ['sprint/items'],
|
|
216
|
+
* validate: (values) => {
|
|
217
|
+
* const items = values['sprint/items'] ?? [];
|
|
218
|
+
* const bad = items.find(i => i.state === 'Closed' && !i.completedWork);
|
|
219
|
+
* if (bad) return `Item #${bad.id} cannot be closed with 0 hours`;
|
|
220
|
+
* return true;
|
|
221
|
+
* }
|
|
222
|
+
* });
|
|
223
|
+
*/
|
|
224
|
+
declare function defineConstraint(constraint: UnifiedConstraint): UnifiedConstraint;
|
|
225
|
+
/**
|
|
226
|
+
* Compose multiple rules into a named module.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* const sprintModule = defineModule('sprint-health', [
|
|
230
|
+
* sprintBehindRule,
|
|
231
|
+
* capacityRule,
|
|
232
|
+
* endNearRule,
|
|
233
|
+
* ]);
|
|
234
|
+
*/
|
|
235
|
+
declare function defineModule(name: string, rules: UnifiedRule[]): {
|
|
236
|
+
name: string;
|
|
237
|
+
rules: UnifiedRule[];
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
export { type LivenessConfig, type MutationResult, type PathSchema, type PraxisApp, type PraxisAppConfig, type QueryOptions, type ReactiveRef, RuleResult, type UnifiedConstraint, type UnifiedRule, createApp, defineConstraint, defineModule, definePath, defineRule };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createApp,
|
|
3
|
+
defineConstraint,
|
|
4
|
+
defineModule,
|
|
5
|
+
definePath,
|
|
6
|
+
defineRule
|
|
7
|
+
} from "../chunk-6MVRT7CK.js";
|
|
8
|
+
import {
|
|
9
|
+
RuleResult,
|
|
10
|
+
fact
|
|
11
|
+
} from "../chunk-IG5BJ2MT.js";
|
|
12
|
+
import "../chunk-QGM4M3NI.js";
|
|
13
|
+
export {
|
|
14
|
+
RuleResult,
|
|
15
|
+
createApp,
|
|
16
|
+
defineConstraint,
|
|
17
|
+
defineModule,
|
|
18
|
+
definePath,
|
|
19
|
+
defineRule,
|
|
20
|
+
fact
|
|
21
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plures/praxis",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "The Full Plures Application Framework - declarative schemas, logic engine, component generation, and local-first data",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@9.15.1",
|
|
@@ -107,6 +107,12 @@
|
|
|
107
107
|
"import": "./dist/browser/project/index.js"
|
|
108
108
|
},
|
|
109
109
|
"default": "./dist/node/project/index.js"
|
|
110
|
+
},
|
|
111
|
+
"./unified": {
|
|
112
|
+
"browser": "./dist/browser/unified/index.js",
|
|
113
|
+
"import": "./dist/esm/unified/index.js",
|
|
114
|
+
"require": "./dist/cjs/unified/index.js",
|
|
115
|
+
"types": "./dist/esm/unified/index.d.ts"
|
|
110
116
|
}
|
|
111
117
|
},
|
|
112
118
|
"files": [
|
package/src/index.browser.ts
CHANGED
|
@@ -303,3 +303,23 @@ export type {
|
|
|
303
303
|
BranchRulesConfig,
|
|
304
304
|
PredefinedGateConfig,
|
|
305
305
|
} from './project/index.js';
|
|
306
|
+
|
|
307
|
+
// ── Unified Reactive Layer (v2.0) ───────────────────────────────────────────
|
|
308
|
+
export { createApp } from './unified/core.js';
|
|
309
|
+
export type { PraxisApp } from './unified/core.js';
|
|
310
|
+
export {
|
|
311
|
+
definePath,
|
|
312
|
+
defineRule as defineUnifiedRule,
|
|
313
|
+
defineConstraint as defineUnifiedConstraint,
|
|
314
|
+
defineModule as defineUnifiedModule,
|
|
315
|
+
} from './unified/index.js';
|
|
316
|
+
export type {
|
|
317
|
+
PathSchema,
|
|
318
|
+
QueryOptions,
|
|
319
|
+
ReactiveRef,
|
|
320
|
+
MutationResult,
|
|
321
|
+
UnifiedRule,
|
|
322
|
+
UnifiedConstraint,
|
|
323
|
+
LivenessConfig,
|
|
324
|
+
PraxisAppConfig,
|
|
325
|
+
} from './unified/types.js';
|
package/src/index.ts
CHANGED
|
@@ -487,3 +487,24 @@ export type {
|
|
|
487
487
|
FullBehavioralDiff,
|
|
488
488
|
} from './chronos/index.js';
|
|
489
489
|
|
|
490
|
+
|
|
491
|
+
// ── Unified Reactive Layer (v2.0) ───────────────────────────────────────────
|
|
492
|
+
// The zero-boilerplate API: createApp → query() + mutate()
|
|
493
|
+
export { createApp } from './unified/core.js';
|
|
494
|
+
export type { PraxisApp } from './unified/core.js';
|
|
495
|
+
export {
|
|
496
|
+
definePath,
|
|
497
|
+
defineRule as defineUnifiedRule,
|
|
498
|
+
defineConstraint as defineUnifiedConstraint,
|
|
499
|
+
defineModule as defineUnifiedModule,
|
|
500
|
+
} from './unified/index.js';
|
|
501
|
+
export type {
|
|
502
|
+
PathSchema,
|
|
503
|
+
QueryOptions,
|
|
504
|
+
ReactiveRef,
|
|
505
|
+
MutationResult,
|
|
506
|
+
UnifiedRule,
|
|
507
|
+
UnifiedConstraint,
|
|
508
|
+
LivenessConfig,
|
|
509
|
+
PraxisAppConfig,
|
|
510
|
+
} from './unified/types.js';
|