@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.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/ai/ai-adapters.md +250 -0
- package/ai/ai-agents-streaming.md +269 -0
- package/ai/ai-budget-resilience.md +235 -0
- package/ai/ai-communication.md +281 -0
- package/ai/ai-debug-observability.md +243 -0
- package/ai/ai-guardrails-memory.md +332 -0
- package/ai/ai-mcp-rag.md +288 -0
- package/ai/ai-multi-agent.md +274 -0
- package/ai/ai-orchestrator.md +227 -0
- package/ai/ai-security.md +293 -0
- package/ai/ai-tasks.md +261 -0
- package/ai/ai-testing-evals.md +378 -0
- package/api-skeleton.md +5 -0
- package/core/anti-patterns.md +382 -0
- package/core/constraints.md +263 -0
- package/core/core-patterns.md +228 -0
- package/core/error-boundaries.md +322 -0
- package/core/multi-module.md +315 -0
- package/core/naming.md +283 -0
- package/core/plugins.md +344 -0
- package/core/react-adapter.md +262 -0
- package/core/resolvers.md +357 -0
- package/core/schema-types.md +262 -0
- package/core/system-api.md +271 -0
- package/core/testing.md +257 -0
- package/core/time-travel.md +238 -0
- package/dist/index.cjs +111 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +102 -0
- package/dist/index.js.map +1 -0
- package/examples/ab-testing.ts +385 -0
- package/examples/ai-checkpoint.ts +509 -0
- package/examples/ai-guardrails.ts +319 -0
- package/examples/ai-orchestrator.ts +589 -0
- package/examples/async-chains.ts +287 -0
- package/examples/auth-flow.ts +371 -0
- package/examples/batch-resolver.ts +341 -0
- package/examples/checkers.ts +589 -0
- package/examples/contact-form.ts +176 -0
- package/examples/counter.ts +393 -0
- package/examples/dashboard-loader.ts +512 -0
- package/examples/debounce-constraints.ts +105 -0
- package/examples/dynamic-modules.ts +293 -0
- package/examples/error-boundaries.ts +430 -0
- package/examples/feature-flags.ts +220 -0
- package/examples/form-wizard.ts +347 -0
- package/examples/fraud-analysis.ts +663 -0
- package/examples/goal-heist.ts +341 -0
- package/examples/multi-module.ts +57 -0
- package/examples/newsletter.ts +241 -0
- package/examples/notifications.ts +210 -0
- package/examples/optimistic-updates.ts +317 -0
- package/examples/pagination.ts +260 -0
- package/examples/permissions.ts +337 -0
- package/examples/provider-routing.ts +403 -0
- package/examples/server.ts +316 -0
- package/examples/shopping-cart.ts +422 -0
- package/examples/sudoku.ts +630 -0
- package/examples/theme-locale.ts +204 -0
- package/examples/time-machine.ts +225 -0
- package/examples/topic-guard.ts +306 -0
- package/examples/url-sync.ts +333 -0
- package/examples/websocket.ts +404 -0
- package/package.json +65 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// Example: theme-locale
|
|
2
|
+
// Source: examples/theme-locale/src/theme-locale.ts
|
|
3
|
+
// Pure module file — no DOM wiring
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Theme & Locale — Directive Modules
|
|
7
|
+
*
|
|
8
|
+
* Two modules:
|
|
9
|
+
* - `preferences` — theme, locale, sidebar, translations, system dark preference
|
|
10
|
+
* - `layout` — responsive breakpoint tracking
|
|
11
|
+
*
|
|
12
|
+
* Demonstrates multi-module composition, auto-tracked derivations,
|
|
13
|
+
* effects for DOM side-effects, and persistence plugin for user prefs.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { type ModuleSchema, createModule, t } from "@directive-run/core";
|
|
17
|
+
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Types
|
|
20
|
+
// ============================================================================
|
|
21
|
+
|
|
22
|
+
export interface Translations {
|
|
23
|
+
greeting: string;
|
|
24
|
+
settings: string;
|
|
25
|
+
theme: string;
|
|
26
|
+
language: string;
|
|
27
|
+
sidebar: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type ThemeChoice = "light" | "dark" | "system";
|
|
31
|
+
export type Breakpoint = "mobile" | "tablet" | "desktop";
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Translation data
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
37
|
+
const TRANSLATIONS: Record<string, Translations> = {
|
|
38
|
+
en: {
|
|
39
|
+
greeting: "Hello",
|
|
40
|
+
settings: "Settings",
|
|
41
|
+
theme: "Theme",
|
|
42
|
+
language: "Language",
|
|
43
|
+
sidebar: "Sidebar",
|
|
44
|
+
},
|
|
45
|
+
es: {
|
|
46
|
+
greeting: "Hola",
|
|
47
|
+
settings: "Configuraci\u00f3n",
|
|
48
|
+
theme: "Tema",
|
|
49
|
+
language: "Idioma",
|
|
50
|
+
sidebar: "Barra lateral",
|
|
51
|
+
},
|
|
52
|
+
fr: {
|
|
53
|
+
greeting: "Bonjour",
|
|
54
|
+
settings: "Param\u00e8tres",
|
|
55
|
+
theme: "Th\u00e8me",
|
|
56
|
+
language: "Langue",
|
|
57
|
+
sidebar: "Barre lat\u00e9rale",
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
function getTranslations(locale: string): Translations {
|
|
62
|
+
return TRANSLATIONS[locale] ?? TRANSLATIONS.en;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// Preferences Schema
|
|
67
|
+
// ============================================================================
|
|
68
|
+
|
|
69
|
+
export const preferencesSchema = {
|
|
70
|
+
facts: {
|
|
71
|
+
theme: t.string<ThemeChoice>(),
|
|
72
|
+
locale: t.string(),
|
|
73
|
+
sidebarOpen: t.boolean(),
|
|
74
|
+
systemPrefersDark: t.boolean(),
|
|
75
|
+
loadedLocale: t.string(),
|
|
76
|
+
translations: t.object<Translations>(),
|
|
77
|
+
},
|
|
78
|
+
derivations: {
|
|
79
|
+
effectiveTheme: t.string(),
|
|
80
|
+
isRTL: t.boolean(),
|
|
81
|
+
},
|
|
82
|
+
events: {
|
|
83
|
+
setTheme: { value: t.string() },
|
|
84
|
+
setLocale: { value: t.string() },
|
|
85
|
+
toggleSidebar: {},
|
|
86
|
+
setSystemPreference: { value: t.boolean() },
|
|
87
|
+
},
|
|
88
|
+
requirements: {},
|
|
89
|
+
} satisfies ModuleSchema;
|
|
90
|
+
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// Layout Schema
|
|
93
|
+
// ============================================================================
|
|
94
|
+
|
|
95
|
+
export const layoutSchema = {
|
|
96
|
+
facts: {
|
|
97
|
+
breakpoint: t.string<Breakpoint>(),
|
|
98
|
+
},
|
|
99
|
+
derivations: {},
|
|
100
|
+
events: {
|
|
101
|
+
setBreakpoint: { value: t.string() },
|
|
102
|
+
},
|
|
103
|
+
requirements: {},
|
|
104
|
+
} satisfies ModuleSchema;
|
|
105
|
+
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Preferences Module
|
|
108
|
+
// ============================================================================
|
|
109
|
+
|
|
110
|
+
export const preferencesModule = createModule("preferences", {
|
|
111
|
+
schema: preferencesSchema,
|
|
112
|
+
|
|
113
|
+
init: (facts) => {
|
|
114
|
+
facts.theme = "system";
|
|
115
|
+
facts.locale = "en";
|
|
116
|
+
facts.sidebarOpen = true;
|
|
117
|
+
facts.systemPrefersDark = false;
|
|
118
|
+
facts.loadedLocale = "en";
|
|
119
|
+
facts.translations = getTranslations("en");
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
// ============================================================================
|
|
123
|
+
// Derivations
|
|
124
|
+
// ============================================================================
|
|
125
|
+
|
|
126
|
+
derive: {
|
|
127
|
+
effectiveTheme: (facts) => {
|
|
128
|
+
if (facts.theme === "system") {
|
|
129
|
+
return facts.systemPrefersDark ? "dark" : "light";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return facts.theme;
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
isRTL: (facts) => {
|
|
136
|
+
const rtlLocales = ["ar", "he", "fa", "ur"];
|
|
137
|
+
|
|
138
|
+
return rtlLocales.includes(facts.locale as string);
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
// ============================================================================
|
|
143
|
+
// Events
|
|
144
|
+
// ============================================================================
|
|
145
|
+
|
|
146
|
+
events: {
|
|
147
|
+
setTheme: (facts, { value }) => {
|
|
148
|
+
facts.theme = value;
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
setLocale: (facts, { value }) => {
|
|
152
|
+
facts.locale = value;
|
|
153
|
+
facts.loadedLocale = value;
|
|
154
|
+
facts.translations = getTranslations(value);
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
toggleSidebar: (facts) => {
|
|
158
|
+
facts.sidebarOpen = !facts.sidebarOpen;
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
setSystemPreference: (facts, { value }) => {
|
|
162
|
+
facts.systemPrefersDark = value;
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
// ============================================================================
|
|
167
|
+
// Effects
|
|
168
|
+
// ============================================================================
|
|
169
|
+
|
|
170
|
+
effects: {
|
|
171
|
+
applyTheme: {
|
|
172
|
+
run: (facts) => {
|
|
173
|
+
const effective =
|
|
174
|
+
facts.theme === "system"
|
|
175
|
+
? facts.systemPrefersDark
|
|
176
|
+
? "dark"
|
|
177
|
+
: "light"
|
|
178
|
+
: facts.theme;
|
|
179
|
+
document.documentElement.setAttribute(
|
|
180
|
+
"data-theme",
|
|
181
|
+
effective as string,
|
|
182
|
+
);
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// ============================================================================
|
|
189
|
+
// Layout Module
|
|
190
|
+
// ============================================================================
|
|
191
|
+
|
|
192
|
+
export const layoutModule = createModule("layout", {
|
|
193
|
+
schema: layoutSchema,
|
|
194
|
+
|
|
195
|
+
init: (facts) => {
|
|
196
|
+
facts.breakpoint = "desktop";
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
events: {
|
|
200
|
+
setBreakpoint: (facts, { value }) => {
|
|
201
|
+
facts.breakpoint = value;
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
});
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
// Example: time-machine
|
|
2
|
+
// Source: examples/time-machine/src/main.ts
|
|
3
|
+
// Extracted for AI rules — DOM wiring stripped
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Time Machine — Time-Travel Debugging
|
|
7
|
+
*
|
|
8
|
+
* Drawing canvas where each stroke is a fact mutation. Full time-travel:
|
|
9
|
+
* undo/redo, export/import JSON, replay animation, changesets, snapshot slider.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
type ModuleSchema,
|
|
14
|
+
createModule,
|
|
15
|
+
createSystem,
|
|
16
|
+
t,
|
|
17
|
+
} from "@directive-run/core";
|
|
18
|
+
import { devtoolsPlugin } from "@directive-run/core/plugins";
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Types
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
interface Stroke {
|
|
25
|
+
id: string;
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
color: string;
|
|
29
|
+
size: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface TimelineEntry {
|
|
33
|
+
time: number;
|
|
34
|
+
event: string;
|
|
35
|
+
detail: string;
|
|
36
|
+
type:
|
|
37
|
+
| "stroke"
|
|
38
|
+
| "undo"
|
|
39
|
+
| "redo"
|
|
40
|
+
| "changeset"
|
|
41
|
+
| "export"
|
|
42
|
+
| "import"
|
|
43
|
+
| "replay"
|
|
44
|
+
| "goto";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Timeline
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
const timeline: TimelineEntry[] = [];
|
|
52
|
+
|
|
53
|
+
function addTimeline(
|
|
54
|
+
event: string,
|
|
55
|
+
detail: string,
|
|
56
|
+
type: TimelineEntry["type"],
|
|
57
|
+
) {
|
|
58
|
+
timeline.unshift({ time: Date.now(), event, detail, type });
|
|
59
|
+
if (timeline.length > 50) {
|
|
60
|
+
timeline.length = 50;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// Schema
|
|
66
|
+
// ============================================================================
|
|
67
|
+
|
|
68
|
+
const schema = {
|
|
69
|
+
facts: {
|
|
70
|
+
strokes: t.object<Stroke[]>(),
|
|
71
|
+
currentColor: t.string(),
|
|
72
|
+
brushSize: t.number(),
|
|
73
|
+
changesetActive: t.boolean(),
|
|
74
|
+
changesetLabel: t.string(),
|
|
75
|
+
},
|
|
76
|
+
derivations: {
|
|
77
|
+
strokeCount: t.number(),
|
|
78
|
+
canUndo: t.boolean(),
|
|
79
|
+
canRedo: t.boolean(),
|
|
80
|
+
currentIndex: t.number(),
|
|
81
|
+
totalSnapshots: t.number(),
|
|
82
|
+
},
|
|
83
|
+
events: {
|
|
84
|
+
addStroke: { x: t.number(), y: t.number() },
|
|
85
|
+
setColor: { value: t.string() },
|
|
86
|
+
setBrushSize: { value: t.number() },
|
|
87
|
+
clearCanvas: {},
|
|
88
|
+
},
|
|
89
|
+
requirements: {},
|
|
90
|
+
} satisfies ModuleSchema;
|
|
91
|
+
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// Module
|
|
94
|
+
// ============================================================================
|
|
95
|
+
|
|
96
|
+
const canvasModule = createModule("canvas", {
|
|
97
|
+
schema,
|
|
98
|
+
|
|
99
|
+
init: (facts) => {
|
|
100
|
+
facts.strokes = [];
|
|
101
|
+
facts.currentColor = "#5ba3a3";
|
|
102
|
+
facts.brushSize = 12;
|
|
103
|
+
facts.changesetActive = false;
|
|
104
|
+
facts.changesetLabel = "";
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
derive: {
|
|
108
|
+
strokeCount: (facts) => facts.strokes.length,
|
|
109
|
+
// These will be updated from the time-travel manager
|
|
110
|
+
canUndo: () => false,
|
|
111
|
+
canRedo: () => false,
|
|
112
|
+
currentIndex: () => 0,
|
|
113
|
+
totalSnapshots: () => 0,
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
events: {
|
|
117
|
+
addStroke: (facts, { x, y }) => {
|
|
118
|
+
const stroke: Stroke = {
|
|
119
|
+
id: `s${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
|
120
|
+
x,
|
|
121
|
+
y,
|
|
122
|
+
color: facts.currentColor,
|
|
123
|
+
size: facts.brushSize,
|
|
124
|
+
};
|
|
125
|
+
facts.strokes = [...facts.strokes, stroke];
|
|
126
|
+
},
|
|
127
|
+
setColor: (facts, { value }) => {
|
|
128
|
+
facts.currentColor = value;
|
|
129
|
+
},
|
|
130
|
+
setBrushSize: (facts, { value }) => {
|
|
131
|
+
facts.brushSize = value;
|
|
132
|
+
},
|
|
133
|
+
clearCanvas: (facts) => {
|
|
134
|
+
facts.strokes = [];
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// System with Time-Travel
|
|
141
|
+
// ============================================================================
|
|
142
|
+
|
|
143
|
+
const system = createSystem({
|
|
144
|
+
module: canvasModule,
|
|
145
|
+
debug: { timeTravel: true, maxSnapshots: 200, runHistory: true },
|
|
146
|
+
plugins: [devtoolsPlugin({ name: "time-machine" })],
|
|
147
|
+
});
|
|
148
|
+
system.start();
|
|
149
|
+
|
|
150
|
+
const tt = system.debug!;
|
|
151
|
+
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// DOM References
|
|
154
|
+
// ============================================================================
|
|
155
|
+
|
|
156
|
+
const ctx = canvasEl.getContext("2d")!;
|
|
157
|
+
"tm-brush-size",
|
|
158
|
+
"tm-snapshot-slider",
|
|
159
|
+
"tm-export-area",
|
|
160
|
+
"tm-begin-changeset",
|
|
161
|
+
"tm-end-changeset",
|
|
162
|
+
|
|
163
|
+
// Timeline
|
|
164
|
+
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// Canvas Rendering
|
|
167
|
+
// ============================================================================
|
|
168
|
+
|
|
169
|
+
function drawCanvas(): void {
|
|
170
|
+
ctx.fillStyle = "#0f172a";
|
|
171
|
+
ctx.fillRect(0, 0, canvasEl.width, canvasEl.height);
|
|
172
|
+
|
|
173
|
+
const strokes = system.facts.strokes as Stroke[];
|
|
174
|
+
for (const stroke of strokes) {
|
|
175
|
+
ctx.beginPath();
|
|
176
|
+
ctx.arc(stroke.x, stroke.y, stroke.size / 2, 0, Math.PI * 2);
|
|
177
|
+
ctx.fillStyle = stroke.color;
|
|
178
|
+
ctx.fill();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// Render
|
|
184
|
+
// ============================================================================
|
|
185
|
+
|
|
186
|
+
function escapeHtml(text: string): string {
|
|
187
|
+
|
|
188
|
+
return div.innerHTML;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
// ============================================================================
|
|
193
|
+
// Subscribe
|
|
194
|
+
// ============================================================================
|
|
195
|
+
|
|
196
|
+
const allKeys = [...Object.keys(schema.facts)];
|
|
197
|
+
system.subscribe(allKeys, render);
|
|
198
|
+
|
|
199
|
+
// ============================================================================
|
|
200
|
+
// Canvas Interaction (pointer events for mouse + touch)
|
|
201
|
+
// ============================================================================
|
|
202
|
+
|
|
203
|
+
let isDrawing = false;
|
|
204
|
+
|
|
205
|
+
function canvasCoords(e: PointerEvent): { x: number; y: number } {
|
|
206
|
+
const scaleX = canvasEl.width / rect.width;
|
|
207
|
+
const scaleY = canvasEl.height / rect.height;
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
x: Math.round((e.clientX - rect.left) * scaleX),
|
|
211
|
+
y: Math.round((e.clientY - rect.top) * scaleY),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// Controls
|
|
218
|
+
// ============================================================================
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
// ============================================================================
|
|
222
|
+
// Initial Render
|
|
223
|
+
// ============================================================================
|
|
224
|
+
|
|
225
|
+
render();
|