@directive-run/knowledge 0.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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +63 -0
  3. package/ai/ai-adapters.md +250 -0
  4. package/ai/ai-agents-streaming.md +269 -0
  5. package/ai/ai-budget-resilience.md +235 -0
  6. package/ai/ai-communication.md +281 -0
  7. package/ai/ai-debug-observability.md +243 -0
  8. package/ai/ai-guardrails-memory.md +332 -0
  9. package/ai/ai-mcp-rag.md +288 -0
  10. package/ai/ai-multi-agent.md +274 -0
  11. package/ai/ai-orchestrator.md +227 -0
  12. package/ai/ai-security.md +293 -0
  13. package/ai/ai-tasks.md +261 -0
  14. package/ai/ai-testing-evals.md +378 -0
  15. package/api-skeleton.md +5 -0
  16. package/core/anti-patterns.md +382 -0
  17. package/core/constraints.md +263 -0
  18. package/core/core-patterns.md +228 -0
  19. package/core/error-boundaries.md +322 -0
  20. package/core/multi-module.md +315 -0
  21. package/core/naming.md +283 -0
  22. package/core/plugins.md +344 -0
  23. package/core/react-adapter.md +262 -0
  24. package/core/resolvers.md +357 -0
  25. package/core/schema-types.md +262 -0
  26. package/core/system-api.md +271 -0
  27. package/core/testing.md +257 -0
  28. package/core/time-travel.md +238 -0
  29. package/dist/index.cjs +111 -0
  30. package/dist/index.cjs.map +1 -0
  31. package/dist/index.d.cts +10 -0
  32. package/dist/index.d.ts +10 -0
  33. package/dist/index.js +102 -0
  34. package/dist/index.js.map +1 -0
  35. package/examples/ab-testing.ts +385 -0
  36. package/examples/ai-checkpoint.ts +509 -0
  37. package/examples/ai-guardrails.ts +319 -0
  38. package/examples/ai-orchestrator.ts +589 -0
  39. package/examples/async-chains.ts +287 -0
  40. package/examples/auth-flow.ts +371 -0
  41. package/examples/batch-resolver.ts +341 -0
  42. package/examples/checkers.ts +589 -0
  43. package/examples/contact-form.ts +176 -0
  44. package/examples/counter.ts +393 -0
  45. package/examples/dashboard-loader.ts +512 -0
  46. package/examples/debounce-constraints.ts +105 -0
  47. package/examples/dynamic-modules.ts +293 -0
  48. package/examples/error-boundaries.ts +430 -0
  49. package/examples/feature-flags.ts +220 -0
  50. package/examples/form-wizard.ts +347 -0
  51. package/examples/fraud-analysis.ts +663 -0
  52. package/examples/goal-heist.ts +341 -0
  53. package/examples/multi-module.ts +57 -0
  54. package/examples/newsletter.ts +241 -0
  55. package/examples/notifications.ts +210 -0
  56. package/examples/optimistic-updates.ts +317 -0
  57. package/examples/pagination.ts +260 -0
  58. package/examples/permissions.ts +337 -0
  59. package/examples/provider-routing.ts +403 -0
  60. package/examples/server.ts +316 -0
  61. package/examples/shopping-cart.ts +422 -0
  62. package/examples/sudoku.ts +630 -0
  63. package/examples/theme-locale.ts +204 -0
  64. package/examples/time-machine.ts +225 -0
  65. package/examples/topic-guard.ts +306 -0
  66. package/examples/url-sync.ts +333 -0
  67. package/examples/websocket.ts +404 -0
  68. package/package.json +65 -0
@@ -0,0 +1,422 @@
1
+ // Example: shopping-cart
2
+ // Source: examples/shopping-cart/src/shopping-cart.ts
3
+ // Pure module file — no DOM wiring
4
+
5
+ /**
6
+ * Shopping Cart — Directive Modules
7
+ *
8
+ * Two modules:
9
+ * - cart: Items, coupons, checkout with cross-module auth dependency
10
+ * - auth: Simple authentication toggle for demo purposes
11
+ *
12
+ * Demonstrates cross-module constraints (`crossModuleDeps`),
13
+ * constraint ordering (`after`), priority-based resolution,
14
+ * and retry with exponential backoff.
15
+ */
16
+
17
+ import {
18
+ type ModuleSchema,
19
+ createModule,
20
+ createSystem,
21
+ t,
22
+ } from "@directive-run/core";
23
+ import { devtoolsPlugin } from "@directive-run/core/plugins";
24
+ import { processCheckout, validateCoupon } from "./mock-api.js";
25
+
26
+ // ============================================================================
27
+ // Types
28
+ // ============================================================================
29
+
30
+ export interface CartItem {
31
+ id: string;
32
+ name: string;
33
+ price: number;
34
+ quantity: number;
35
+ maxStock: number;
36
+ image: string;
37
+ }
38
+
39
+ // ============================================================================
40
+ // Auth Module
41
+ // ============================================================================
42
+
43
+ export const authSchema = {
44
+ facts: {
45
+ isAuthenticated: t.boolean(),
46
+ userName: t.string(),
47
+ },
48
+ derivations: {
49
+ isAuthenticated: t.boolean(),
50
+ },
51
+ events: {
52
+ toggleAuth: {},
53
+ },
54
+ requirements: {},
55
+ } satisfies ModuleSchema;
56
+
57
+ export const authModule = createModule("auth", {
58
+ schema: authSchema,
59
+
60
+ init: (facts) => {
61
+ facts.isAuthenticated = true;
62
+ facts.userName = "Demo User";
63
+ },
64
+
65
+ derive: {
66
+ isAuthenticated: (facts) => facts.isAuthenticated,
67
+ },
68
+
69
+ events: {
70
+ toggleAuth: (facts) => {
71
+ facts.isAuthenticated = !facts.isAuthenticated;
72
+ if (!facts.isAuthenticated) {
73
+ facts.userName = "";
74
+ } else {
75
+ facts.userName = "Demo User";
76
+ }
77
+ },
78
+ },
79
+ });
80
+
81
+ // ============================================================================
82
+ // Cart Module
83
+ // ============================================================================
84
+
85
+ export const cartSchema = {
86
+ facts: {
87
+ items: t.array<CartItem>(),
88
+ couponCode: t.string(),
89
+ couponDiscount: t.number(),
90
+ couponStatus: t.string<"idle" | "checking" | "valid" | "invalid">(),
91
+ checkoutRequested: t.boolean(),
92
+ checkoutStatus: t.string<"idle" | "processing" | "complete" | "failed">(),
93
+ checkoutError: t.string(),
94
+ },
95
+ derivations: {
96
+ subtotal: t.number(),
97
+ itemCount: t.number(),
98
+ isEmpty: t.boolean(),
99
+ discount: t.number(),
100
+ tax: t.number(),
101
+ total: t.number(),
102
+ hasOverstockedItem: t.boolean(),
103
+ freeShipping: t.boolean(),
104
+ },
105
+ events: {
106
+ addItem: {
107
+ id: t.string(),
108
+ name: t.string(),
109
+ price: t.number(),
110
+ maxStock: t.number(),
111
+ image: t.string(),
112
+ },
113
+ removeItem: { id: t.string() },
114
+ updateQuantity: { id: t.string(), quantity: t.number() },
115
+ applyCoupon: { code: t.string() },
116
+ clearCoupon: {},
117
+ requestCheckout: {},
118
+ resetCheckout: {},
119
+ },
120
+ requirements: {
121
+ ADJUST_QUANTITY: {},
122
+ VALIDATE_COUPON: { code: t.string() },
123
+ PROCESS_CHECKOUT: {},
124
+ },
125
+ } satisfies ModuleSchema;
126
+
127
+ export const cartModule = createModule("cart", {
128
+ schema: cartSchema,
129
+
130
+ crossModuleDeps: { auth: authSchema },
131
+
132
+ init: (facts) => {
133
+ facts.items = [
134
+ {
135
+ id: "headphones-1",
136
+ name: "Wireless Headphones",
137
+ price: 79.99,
138
+ quantity: 1,
139
+ maxStock: 5,
140
+ image: "headphones",
141
+ },
142
+ {
143
+ id: "keyboard-1",
144
+ name: "Mechanical Keyboard",
145
+ price: 129.99,
146
+ quantity: 1,
147
+ maxStock: 3,
148
+ image: "keyboard",
149
+ },
150
+ {
151
+ id: "hub-1",
152
+ name: "USB-C Hub",
153
+ price: 49.99,
154
+ quantity: 2,
155
+ maxStock: 10,
156
+ image: "hub",
157
+ },
158
+ ];
159
+ facts.couponCode = "";
160
+ facts.couponDiscount = 0;
161
+ facts.couponStatus = "idle";
162
+ facts.checkoutRequested = false;
163
+ facts.checkoutStatus = "idle";
164
+ facts.checkoutError = "";
165
+ },
166
+
167
+ // ============================================================================
168
+ // Derivations
169
+ // ============================================================================
170
+
171
+ derive: {
172
+ subtotal: (facts) => {
173
+ return facts.self.items.reduce(
174
+ (sum: number, item: CartItem) => sum + item.price * item.quantity,
175
+ 0,
176
+ );
177
+ },
178
+
179
+ itemCount: (facts) => {
180
+ return facts.self.items.reduce(
181
+ (sum: number, item: CartItem) => sum + item.quantity,
182
+ 0,
183
+ );
184
+ },
185
+
186
+ isEmpty: (facts) => {
187
+ return facts.self.items.length === 0;
188
+ },
189
+
190
+ discount: (facts, derive) => {
191
+ const sub = derive.subtotal as number;
192
+
193
+ return sub * (facts.self.couponDiscount / 100);
194
+ },
195
+
196
+ tax: (facts, derive) => {
197
+ const sub = derive.subtotal as number;
198
+ const disc = derive.discount as number;
199
+
200
+ return (sub - disc) * 0.08;
201
+ },
202
+
203
+ total: (_facts, derive) => {
204
+ const sub = derive.subtotal as number;
205
+ const disc = derive.discount as number;
206
+ const tx = derive.tax as number;
207
+
208
+ return sub - disc + tx;
209
+ },
210
+
211
+ hasOverstockedItem: (facts) => {
212
+ return facts.self.items.some(
213
+ (item: CartItem) => item.quantity > item.maxStock,
214
+ );
215
+ },
216
+
217
+ freeShipping: (_facts, derive) => {
218
+ const sub = derive.subtotal as number;
219
+
220
+ return sub >= 75;
221
+ },
222
+ },
223
+
224
+ // ============================================================================
225
+ // Events
226
+ // ============================================================================
227
+
228
+ events: {
229
+ addItem: (facts, { id, name, price, maxStock, image }) => {
230
+ const existing = facts.items.find((item: CartItem) => item.id === id);
231
+ if (existing) {
232
+ facts.items = facts.items.map((item: CartItem) =>
233
+ item.id === id
234
+ ? { ...item, quantity: Math.min(item.quantity + 1, item.maxStock) }
235
+ : item,
236
+ );
237
+ } else {
238
+ facts.items = [
239
+ ...facts.items,
240
+ { id, name, price, quantity: 1, maxStock, image },
241
+ ];
242
+ }
243
+ },
244
+
245
+ removeItem: (facts, { id }) => {
246
+ facts.items = facts.items.filter((item: CartItem) => item.id !== id);
247
+ },
248
+
249
+ updateQuantity: (facts, { id, quantity }) => {
250
+ if (quantity <= 0) {
251
+ facts.items = facts.items.filter((item: CartItem) => item.id !== id);
252
+
253
+ return;
254
+ }
255
+
256
+ facts.items = facts.items.map((item: CartItem) =>
257
+ item.id === id ? { ...item, quantity } : item,
258
+ );
259
+ },
260
+
261
+ applyCoupon: (facts, { code }) => {
262
+ facts.couponCode = code;
263
+ facts.couponStatus = "idle";
264
+ facts.couponDiscount = 0;
265
+ },
266
+
267
+ clearCoupon: (facts) => {
268
+ facts.couponCode = "";
269
+ facts.couponDiscount = 0;
270
+ facts.couponStatus = "idle";
271
+ },
272
+
273
+ requestCheckout: (facts) => {
274
+ facts.checkoutRequested = true;
275
+ facts.checkoutStatus = "idle";
276
+ facts.checkoutError = "";
277
+ },
278
+
279
+ resetCheckout: (facts) => {
280
+ facts.checkoutRequested = false;
281
+ facts.checkoutStatus = "idle";
282
+ facts.checkoutError = "";
283
+ },
284
+ },
285
+
286
+ // ============================================================================
287
+ // Constraints
288
+ // ============================================================================
289
+
290
+ constraints: {
291
+ quantityLimit: {
292
+ priority: 80,
293
+ when: (facts) => {
294
+ const hasOverstocked = facts.self.items.some(
295
+ (item: CartItem) => item.quantity > item.maxStock,
296
+ );
297
+
298
+ return hasOverstocked;
299
+ },
300
+ require: { type: "ADJUST_QUANTITY" },
301
+ },
302
+
303
+ couponValidation: {
304
+ priority: 70,
305
+ when: (facts) => {
306
+ return (
307
+ facts.self.couponCode !== "" && facts.self.couponStatus === "idle"
308
+ );
309
+ },
310
+ require: (facts) => ({
311
+ type: "VALIDATE_COUPON",
312
+ code: facts.self.couponCode,
313
+ }),
314
+ },
315
+
316
+ checkoutReady: {
317
+ priority: 60,
318
+ after: ["quantityLimit", "couponValidation"],
319
+ when: (facts) => {
320
+ const items = facts.self.items as CartItem[];
321
+ const notEmpty = items.length > 0;
322
+ const noOverstock = !items.some(
323
+ (item: CartItem) => item.quantity > item.maxStock,
324
+ );
325
+
326
+ return (
327
+ facts.self.checkoutRequested === true &&
328
+ notEmpty &&
329
+ noOverstock &&
330
+ facts.auth.isAuthenticated === true
331
+ );
332
+ },
333
+ require: { type: "PROCESS_CHECKOUT" },
334
+ },
335
+ },
336
+
337
+ // ============================================================================
338
+ // Resolvers
339
+ // ============================================================================
340
+
341
+ resolvers: {
342
+ adjustQuantity: {
343
+ requirement: "ADJUST_QUANTITY",
344
+ resolve: async (_req, context) => {
345
+ context.facts.items = context.facts.items.map((item: CartItem) => {
346
+ if (item.quantity > item.maxStock) {
347
+ return { ...item, quantity: item.maxStock };
348
+ }
349
+
350
+ return item;
351
+ });
352
+ },
353
+ },
354
+
355
+ validateCoupon: {
356
+ requirement: "VALIDATE_COUPON",
357
+ key: (req) => `coupon-${req.code}`,
358
+ resolve: async (req, context) => {
359
+ context.facts.couponStatus = "checking";
360
+
361
+ const result = await validateCoupon(req.code);
362
+
363
+ if (result.valid) {
364
+ context.facts.couponDiscount = result.discount;
365
+ context.facts.couponStatus = "valid";
366
+ } else {
367
+ context.facts.couponDiscount = 0;
368
+ context.facts.couponStatus = "invalid";
369
+ }
370
+ },
371
+ },
372
+
373
+ processCheckout: {
374
+ requirement: "PROCESS_CHECKOUT",
375
+ retry: { attempts: 2, backoff: "exponential" },
376
+ resolve: async (_req, context) => {
377
+ context.facts.checkoutStatus = "processing";
378
+
379
+ try {
380
+ const items = context.facts.items.map((item: CartItem) => ({
381
+ id: item.id,
382
+ name: item.name,
383
+ quantity: item.quantity,
384
+ price: item.price,
385
+ }));
386
+
387
+ await processCheckout(items, context.facts.couponCode);
388
+
389
+ context.facts.checkoutStatus = "complete";
390
+ context.facts.items = [];
391
+ context.facts.couponCode = "";
392
+ context.facts.couponDiscount = 0;
393
+ context.facts.couponStatus = "idle";
394
+ context.facts.checkoutRequested = false;
395
+ } catch (err) {
396
+ const msg = err instanceof Error ? err.message : "Checkout failed";
397
+ context.facts.checkoutStatus = "failed";
398
+ context.facts.checkoutError = msg;
399
+ context.facts.checkoutRequested = false;
400
+ throw err;
401
+ }
402
+ },
403
+ },
404
+ },
405
+ });
406
+
407
+ // ============================================================================
408
+ // System
409
+ // ============================================================================
410
+
411
+ export const system = createSystem({
412
+ modules: {
413
+ cart: cartModule,
414
+ auth: authModule,
415
+ },
416
+ plugins: [devtoolsPlugin({ name: "shopping-cart", panel: true })],
417
+ debug: {
418
+ timeTravel: true,
419
+ maxSnapshots: 50,
420
+ runHistory: true,
421
+ },
422
+ });