@directive-run/knowledge 0.2.0 → 0.4.2

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 (54) hide show
  1. package/README.md +3 -3
  2. package/ai/ai-adapters.md +7 -7
  3. package/ai/ai-agents-streaming.md +8 -8
  4. package/ai/ai-budget-resilience.md +5 -5
  5. package/ai/ai-communication.md +1 -1
  6. package/ai/ai-guardrails-memory.md +7 -7
  7. package/ai/ai-mcp-rag.md +5 -5
  8. package/ai/ai-multi-agent.md +14 -14
  9. package/ai/ai-orchestrator.md +8 -8
  10. package/ai/ai-security.md +2 -2
  11. package/ai/ai-tasks.md +9 -9
  12. package/ai/ai-testing-evals.md +2 -2
  13. package/core/anti-patterns.md +39 -39
  14. package/core/constraints.md +15 -15
  15. package/core/core-patterns.md +9 -9
  16. package/core/error-boundaries.md +7 -7
  17. package/core/multi-module.md +16 -16
  18. package/core/naming.md +21 -21
  19. package/core/plugins.md +14 -14
  20. package/core/react-adapter.md +13 -13
  21. package/core/resolvers.md +14 -14
  22. package/core/schema-types.md +22 -22
  23. package/core/system-api.md +16 -16
  24. package/core/testing.md +5 -5
  25. package/core/time-travel.md +20 -20
  26. package/dist/index.cjs +6 -105
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.js +7 -97
  29. package/dist/index.js.map +1 -1
  30. package/examples/ab-testing.ts +18 -90
  31. package/examples/ai-checkpoint.ts +68 -87
  32. package/examples/ai-guardrails.ts +20 -70
  33. package/examples/auth-flow.ts +2 -2
  34. package/examples/batch-resolver.ts +19 -59
  35. package/examples/contact-form.ts +220 -69
  36. package/examples/counter.ts +77 -95
  37. package/examples/dashboard-loader.ts +37 -55
  38. package/examples/debounce-constraints.ts +0 -2
  39. package/examples/dynamic-modules.ts +17 -20
  40. package/examples/error-boundaries.ts +30 -81
  41. package/examples/newsletter.ts +22 -49
  42. package/examples/notifications.ts +24 -23
  43. package/examples/optimistic-updates.ts +36 -41
  44. package/examples/pagination.ts +2 -2
  45. package/examples/permissions.ts +22 -32
  46. package/examples/provider-routing.ts +26 -83
  47. package/examples/shopping-cart.ts +8 -8
  48. package/examples/sudoku.ts +55 -62
  49. package/examples/theme-locale.ts +4 -7
  50. package/examples/time-machine.ts +12 -90
  51. package/examples/topic-guard.ts +30 -38
  52. package/examples/url-sync.ts +8 -8
  53. package/examples/websocket.ts +5 -5
  54. package/package.json +3 -3
@@ -1,9 +1,9 @@
1
1
  // Example: newsletter
2
- // Source: examples/newsletter/src/main.ts
3
- // Extracted for AI rules — DOM wiring stripped
2
+ // Source: examples/newsletter/src/module.ts
3
+ // Pure module fileno DOM wiring
4
4
 
5
5
  /**
6
- * Newsletter Signup - Vanilla Directive Example
6
+ * Newsletter Signup Directive Module
7
7
  *
8
8
  * Demonstrates all six primitives with the simplest possible module:
9
9
  * - Facts: email, touched, status, errorMessage, lastSubmittedAt
@@ -31,11 +31,22 @@ import { devtoolsPlugin } from "@directive-run/core/plugins";
31
31
  const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
32
32
  const RATE_LIMIT_MS = 10_000; // 10 seconds (shorter for demo)
33
33
 
34
+ // ============================================================================
35
+ // Logs (external mutable array, same pattern as fraud-analysis)
36
+ // ============================================================================
37
+
38
+ export const logs: string[] = [];
39
+
40
+ export function addLog(msg: string): void {
41
+ console.log(`[newsletter] ${msg}`);
42
+ logs.push(`${new Date().toLocaleTimeString()}: ${msg}`);
43
+ }
44
+
34
45
  // ============================================================================
35
46
  // Schema
36
47
  // ============================================================================
37
48
 
38
- const schema = {
49
+ export const schema = {
39
50
  facts: {
40
51
  email: t.string(),
41
52
  touched: t.boolean(),
@@ -141,7 +152,7 @@ const newsletter = createModule("newsletter", {
141
152
  subscribe: {
142
153
  requirement: "SUBSCRIBE",
143
154
  resolve: async (req, context) => {
144
- log(`Subscribing: ${context.facts.email}`);
155
+ addLog(`Subscribing: ${context.facts.email}`);
145
156
 
146
157
  // Simulate network delay
147
158
  await new Promise((resolve) => setTimeout(resolve, 1500));
@@ -151,27 +162,27 @@ const newsletter = createModule("newsletter", {
151
162
  context.facts.status = "error";
152
163
  context.facts.errorMessage =
153
164
  "Simulated error — try again (20% failure rate for demo).";
154
- log("Subscription failed (simulated)");
165
+ addLog("Subscription failed (simulated)");
155
166
 
156
167
  return;
157
168
  }
158
169
 
159
170
  context.facts.status = "success";
160
171
  context.facts.lastSubmittedAt = Date.now();
161
- log("Subscription succeeded");
172
+ addLog("Subscription succeeded");
162
173
  },
163
174
  },
164
175
 
165
176
  resetAfterDelay: {
166
177
  requirement: "RESET_AFTER_DELAY",
167
178
  resolve: async (req, context) => {
168
- log("Auto-resetting in 5 seconds...");
179
+ addLog("Auto-resetting in 5 seconds...");
169
180
  await new Promise((resolve) => setTimeout(resolve, 5000));
170
181
  context.facts.email = "";
171
182
  context.facts.touched = false;
172
183
  context.facts.status = "idle";
173
184
  context.facts.errorMessage = "";
174
- log("Form reset");
185
+ addLog("Form reset");
175
186
  },
176
187
  },
177
188
  },
@@ -185,7 +196,7 @@ const newsletter = createModule("newsletter", {
185
196
  }
186
197
 
187
198
  if (facts.status !== prev.status) {
188
- log(`Status: ${prev.status} → ${facts.status}`);
199
+ addLog(`Status: ${prev.status} → ${facts.status}`);
189
200
  }
190
201
  },
191
202
  },
@@ -196,46 +207,8 @@ const newsletter = createModule("newsletter", {
196
207
  // System
197
208
  // ============================================================================
198
209
 
199
- const system = createSystem({
210
+ export const system = createSystem({
200
211
  module: newsletter,
201
212
  debug: { runHistory: true },
202
213
  plugins: [devtoolsPlugin({ name: "newsletter" })],
203
214
  });
204
- system.start();
205
-
206
- // ============================================================================
207
- // Logging helper
208
- // ============================================================================
209
-
210
- function log(msg: string) {
211
- console.log(`[newsletter] ${msg}`);
212
- }
213
-
214
- // ============================================================================
215
- // DOM Bindings
216
- // ============================================================================
217
-
218
-
219
- // ============================================================================
220
- // Render
221
- // ============================================================================
222
-
223
-
224
- // Subscribe to all relevant facts and derivations
225
- system.subscribe(
226
- [
227
- "email",
228
- "touched",
229
- "status",
230
- "errorMessage",
231
- "lastSubmittedAt",
232
- "emailError",
233
- "isValid",
234
- "canSubmit",
235
- ],
236
- render,
237
- );
238
-
239
- // Initial render
240
- render();
241
- log("Newsletter signup ready. Enter an email and subscribe.");
@@ -30,13 +30,13 @@ export interface Notification {
30
30
 
31
31
  export const notificationsSchema = {
32
32
  facts: {
33
- queue: t.object<Notification[]>(),
33
+ queue: t.array<Notification>(),
34
34
  maxVisible: t.number(),
35
35
  now: t.number(),
36
36
  idCounter: t.number(),
37
37
  },
38
38
  derivations: {
39
- visibleNotifications: t.object<Notification[]>(),
39
+ visibleNotifications: t.array<Notification>(),
40
40
  hasNotifications: t.boolean(),
41
41
  oldestExpired: t.object<Notification | null>(),
42
42
  },
@@ -71,24 +71,20 @@ export const notificationsModule = createModule("notifications", {
71
71
 
72
72
  derive: {
73
73
  visibleNotifications: (facts) => {
74
- return (facts.queue as Notification[]).slice(
75
- 0,
76
- facts.maxVisible as number,
77
- );
74
+ return facts.queue.slice(0, facts.maxVisible);
78
75
  },
79
76
 
80
77
  hasNotifications: (facts) => {
81
- return (facts.queue as Notification[]).length > 0;
78
+ return facts.queue.length > 0;
82
79
  },
83
80
 
84
81
  oldestExpired: (facts) => {
85
- const queue = facts.queue as Notification[];
86
- const oldest = queue[0];
82
+ const oldest = facts.queue[0];
87
83
  if (!oldest) {
88
84
  return null;
89
85
  }
90
86
 
91
- if ((facts.now as number) > oldest.createdAt + oldest.ttl) {
87
+ if (facts.now > oldest.createdAt + oldest.ttl) {
92
88
  return oldest;
93
89
  }
94
90
 
@@ -103,23 +99,28 @@ export const notificationsModule = createModule("notifications", {
103
99
  constraints: {
104
100
  autoDismiss: {
105
101
  priority: 50,
106
- when: (_facts, derive) => derive.oldestExpired !== null,
107
- require: (_facts, derive) => ({
102
+ when: (facts) => {
103
+ const oldest = facts.queue[0];
104
+ if (!oldest) {
105
+ return false;
106
+ }
107
+
108
+ return facts.now > oldest.createdAt + oldest.ttl;
109
+ },
110
+ require: (facts) => ({
108
111
  type: "DISMISS_NOTIFICATION" as const,
109
- id: (derive.oldestExpired as Notification).id,
112
+ id: facts.queue[0].id,
110
113
  }),
111
114
  },
112
115
 
113
116
  overflow: {
114
117
  priority: 60,
115
118
  when: (facts) => {
116
- const queue = facts.queue as Notification[];
117
-
118
- return queue.length > (facts.maxVisible as number) + 5;
119
+ return facts.queue.length > facts.maxVisible + 5;
119
120
  },
120
121
  require: (facts) => ({
121
122
  type: "DISMISS_NOTIFICATION" as const,
122
- id: (facts.queue as Notification[])[0].id,
123
+ id: facts.queue[0].id,
123
124
  }),
124
125
  },
125
126
  },
@@ -132,7 +133,7 @@ export const notificationsModule = createModule("notifications", {
132
133
  dismiss: {
133
134
  requirement: "DISMISS_NOTIFICATION",
134
135
  resolve: async (req, context) => {
135
- context.facts.queue = (context.facts.queue as Notification[]).filter(
136
+ context.facts.queue = context.facts.queue.filter(
136
137
  (n) => n.id !== req.id,
137
138
  );
138
139
  },
@@ -154,7 +155,7 @@ export const notificationsModule = createModule("notifications", {
154
155
  warning: 6000,
155
156
  error: 10000,
156
157
  };
157
- const counter = (facts.idCounter as number) + 1;
158
+ const counter = facts.idCounter + 1;
158
159
  facts.idCounter = counter;
159
160
 
160
161
  const notification: Notification = {
@@ -165,11 +166,11 @@ export const notificationsModule = createModule("notifications", {
165
166
  ttl: payload.ttl ?? ttlMap[payload.level] ?? 4000,
166
167
  };
167
168
 
168
- facts.queue = [...(facts.queue as Notification[]), notification];
169
+ facts.queue = [...facts.queue, notification];
169
170
  },
170
171
 
171
172
  dismissNotification: (facts, { id }: { id: string }) => {
172
- facts.queue = (facts.queue as Notification[]).filter((n) => n.id !== id);
173
+ facts.queue = facts.queue.filter((n) => n.id !== id);
173
174
  },
174
175
 
175
176
  tick: (facts) => {
@@ -188,7 +189,7 @@ export const notificationsModule = createModule("notifications", {
188
189
 
189
190
  export const appSchema = {
190
191
  facts: {
191
- actionLog: t.object<string[]>(),
192
+ actionLog: t.array<string>(),
192
193
  },
193
194
  events: {
194
195
  simulateAction: { message: t.string(), level: t.string() },
@@ -204,7 +205,7 @@ export const appModule = createModule("app", {
204
205
 
205
206
  events: {
206
207
  simulateAction: (facts, { message }: { message: string }) => {
207
- facts.actionLog = [...(facts.actionLog as string[]), message];
208
+ facts.actionLog = [...facts.actionLog, message];
208
209
  },
209
210
  },
210
211
  });
@@ -51,15 +51,15 @@ let nextOpId = 1;
51
51
 
52
52
  export const optimisticUpdatesSchema = {
53
53
  facts: {
54
- items: t.object<TodoItem[]>(),
55
- syncQueue: t.object<SyncQueueEntry[]>(),
54
+ items: t.array<TodoItem>(),
55
+ syncQueue: t.array<SyncQueueEntry>(),
56
56
  syncingOpId: t.string(),
57
57
  newItemText: t.string(),
58
58
  serverDelay: t.number(),
59
59
  failRate: t.number(),
60
60
  toastMessage: t.string(),
61
61
  toastType: t.string(),
62
- eventLog: t.object<EventLogEntry[]>(),
62
+ eventLog: t.array<EventLogEntry>(),
63
63
  },
64
64
  derivations: {
65
65
  totalCount: t.number(),
@@ -127,16 +127,15 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
127
127
  // ============================================================================
128
128
 
129
129
  derive: {
130
- totalCount: (facts) => (facts.items as TodoItem[]).length,
130
+ totalCount: (facts) => facts.items.length,
131
131
 
132
- doneCount: (facts) =>
133
- (facts.items as TodoItem[]).filter((i) => i.done).length,
132
+ doneCount: (facts) => facts.items.filter((i) => i.done).length,
134
133
 
135
- pendingCount: (facts) => (facts.syncQueue as SyncQueueEntry[]).length,
134
+ pendingCount: (facts) => facts.syncQueue.length,
136
135
 
137
- canAdd: (facts) => (facts.newItemText as string).trim() !== "",
136
+ canAdd: (facts) => facts.newItemText.trim() !== "",
138
137
 
139
- isSyncing: (facts) => (facts.syncingOpId as string) !== "",
138
+ isSyncing: (facts) => facts.syncingOpId !== "",
140
139
  },
141
140
 
142
141
  // ============================================================================
@@ -145,15 +144,14 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
145
144
 
146
145
  events: {
147
146
  toggleItem: (facts, { id }) => {
148
- const items = facts.items as TodoItem[];
149
- const undoItems = items.map((i) => ({ ...i }));
147
+ const undoItems = facts.items.map((i) => ({ ...i }));
150
148
 
151
- facts.items = items.map((i) =>
149
+ facts.items = facts.items.map((i) =>
152
150
  i.id === id ? { ...i, done: !i.done } : i,
153
151
  );
154
152
 
155
153
  const opId = String(nextOpId++);
156
- const queue = [...(facts.syncQueue as SyncQueueEntry[])];
154
+ const queue = [...facts.syncQueue];
157
155
  queue.push({ opId, itemId: id, op: "toggle", undoItems });
158
156
  facts.syncQueue = queue;
159
157
 
@@ -161,13 +159,12 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
161
159
  },
162
160
 
163
161
  deleteItem: (facts, { id }) => {
164
- const items = facts.items as TodoItem[];
165
- const undoItems = items.map((i) => ({ ...i }));
162
+ const undoItems = facts.items.map((i) => ({ ...i }));
166
163
 
167
- facts.items = items.filter((i) => i.id !== id);
164
+ facts.items = facts.items.filter((i) => i.id !== id);
168
165
 
169
166
  const opId = String(nextOpId++);
170
- const queue = [...(facts.syncQueue as SyncQueueEntry[])];
167
+ const queue = [...facts.syncQueue];
171
168
  queue.push({ opId, itemId: id, op: "delete", undoItems });
172
169
  facts.syncQueue = queue;
173
170
 
@@ -175,20 +172,19 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
175
172
  },
176
173
 
177
174
  addItem: (facts) => {
178
- const text = (facts.newItemText as string).trim();
175
+ const text = facts.newItemText.trim();
179
176
  if (!text) {
180
177
  return;
181
178
  }
182
179
 
183
- const items = facts.items as TodoItem[];
184
- const undoItems = items.map((i) => ({ ...i }));
180
+ const undoItems = facts.items.map((i) => ({ ...i }));
185
181
 
186
182
  const itemId = String(nextId++);
187
- facts.items = [...items, { id: itemId, text, done: false }];
183
+ facts.items = [...facts.items, { id: itemId, text, done: false }];
188
184
  facts.newItemText = "";
189
185
 
190
186
  const opId = String(nextOpId++);
191
- const queue = [...(facts.syncQueue as SyncQueueEntry[])];
187
+ const queue = [...facts.syncQueue];
192
188
  queue.push({ opId, itemId, op: "add", undoItems });
193
189
  facts.syncQueue = queue;
194
190
 
@@ -221,17 +217,12 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
221
217
  needsSync: {
222
218
  priority: 100,
223
219
  when: (facts) => {
224
- const queue = facts.syncQueue as SyncQueueEntry[];
225
- const syncingOpId = facts.syncingOpId as string;
226
-
227
- return queue.length > 0 && syncingOpId === "";
220
+ return facts.syncQueue.length > 0 && facts.syncingOpId === "";
228
221
  },
229
222
  require: (facts) => {
230
- const queue = facts.syncQueue as SyncQueueEntry[];
231
-
232
223
  return {
233
224
  type: "SYNC_TODO",
234
- opId: queue[0].opId,
225
+ opId: facts.syncQueue[0].opId,
235
226
  };
236
227
  },
237
228
  },
@@ -247,8 +238,7 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
247
238
  key: (req) => `sync-${req.opId}`,
248
239
  timeout: 10000,
249
240
  resolve: async (req, context) => {
250
- const queue = context.facts.syncQueue as SyncQueueEntry[];
251
- const entry = queue.find((e) => e.opId === req.opId);
241
+ const entry = context.facts.syncQueue.find((e) => e.opId === req.opId);
252
242
  if (!entry) {
253
243
  return;
254
244
  }
@@ -260,8 +250,8 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
260
250
  `Syncing ${entry.op} for item ${entry.itemId}...`,
261
251
  );
262
252
 
263
- const serverDelay = context.facts.serverDelay as number;
264
- const failRate = context.facts.failRate as number;
253
+ const serverDelay = context.facts.serverDelay;
254
+ const failRate = context.facts.failRate;
265
255
 
266
256
  try {
267
257
  await mockServerSync(entry.op, entry.itemId, serverDelay, failRate);
@@ -285,8 +275,7 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
285
275
  }
286
276
 
287
277
  // Remove entry from queue
288
- const currentQueue = context.facts.syncQueue as SyncQueueEntry[];
289
- context.facts.syncQueue = currentQueue.filter(
278
+ context.facts.syncQueue = context.facts.syncQueue.filter(
290
279
  (e) => e.opId !== req.opId,
291
280
  );
292
281
  context.facts.syncingOpId = "";
@@ -303,12 +292,18 @@ export const optimisticUpdatesModule = createModule("optimistic-updates", {
303
292
  deps: ["syncingOpId"],
304
293
  run: (facts, prev) => {
305
294
  if (prev) {
306
- const prevId = prev.syncingOpId as string;
307
- const currId = facts.syncingOpId as string;
308
- if (prevId === "" && currId !== "") {
309
- addLogEntry(facts, "status", `Sync started: op ${currId}`);
310
- } else if (prevId !== "" && currId === "") {
311
- addLogEntry(facts, "status", `Sync completed: op ${prevId}`);
295
+ if (prev.syncingOpId === "" && facts.syncingOpId !== "") {
296
+ addLogEntry(
297
+ facts,
298
+ "status",
299
+ `Sync started: op ${facts.syncingOpId}`,
300
+ );
301
+ } else if (prev.syncingOpId !== "" && facts.syncingOpId === "") {
302
+ addLogEntry(
303
+ facts,
304
+ "status",
305
+ `Sync completed: op ${prev.syncingOpId}`,
306
+ );
312
307
  }
313
308
  }
314
309
  },
@@ -56,7 +56,7 @@ export const filtersModule = createModule("filters", {
56
56
  facts.search = value;
57
57
  },
58
58
  setSortBy: (facts, { value }) => {
59
- facts.sortBy = value;
59
+ facts.sortBy = value as "newest" | "oldest" | "title";
60
60
  },
61
61
  setCategory: (facts, { value }) => {
62
62
  facts.category = value;
@@ -70,7 +70,7 @@ export const filtersModule = createModule("filters", {
70
70
 
71
71
  export const listSchema = {
72
72
  facts: {
73
- items: t.object<ListItem[]>(),
73
+ items: t.array<ListItem>(),
74
74
  cursor: t.string(),
75
75
  hasMore: t.boolean(),
76
76
  isLoadingMore: t.boolean(),
@@ -101,7 +101,7 @@ export const authModule = createModule("auth", {
101
101
 
102
102
  export const permissionsSchema = {
103
103
  facts: {
104
- permissions: t.object<string[]>(),
104
+ permissions: t.array<string>(),
105
105
  loaded: t.boolean(),
106
106
  },
107
107
  derivations: {
@@ -132,18 +132,14 @@ export const permissionsModule = createModule("permissions", {
132
132
  },
133
133
 
134
134
  derive: {
135
- canEdit: (facts) =>
136
- (facts.self.permissions as string[]).includes("content.edit"),
137
- canPublish: (facts) =>
138
- (facts.self.permissions as string[]).includes("content.publish"),
139
- canDelete: (facts) =>
140
- (facts.self.permissions as string[]).includes("content.delete"),
141
- canManageUsers: (facts) =>
142
- (facts.self.permissions as string[]).includes("users.manage"),
135
+ canEdit: (facts) => facts.self.permissions.includes("content.edit"),
136
+ canPublish: (facts) => facts.self.permissions.includes("content.publish"),
137
+ canDelete: (facts) => facts.self.permissions.includes("content.delete"),
138
+ canManageUsers: (facts) => facts.self.permissions.includes("users.manage"),
143
139
  canViewAnalytics: (facts) =>
144
- (facts.self.permissions as string[]).includes("analytics.view"),
145
- isAdmin: (_facts, derive) => derive.canManageUsers as boolean,
146
- permissionCount: (facts) => (facts.self.permissions as string[]).length,
140
+ facts.self.permissions.includes("analytics.view"),
141
+ isAdmin: (_facts, derive) => derive.canManageUsers,
142
+ permissionCount: (facts) => facts.self.permissions.length,
147
143
  },
148
144
 
149
145
  events: {
@@ -156,13 +152,11 @@ export const permissionsModule = createModule("permissions", {
156
152
  constraints: {
157
153
  loadPermissions: {
158
154
  when: (facts) => {
159
- return (
160
- (facts.auth.token as string) !== "" && !(facts.self.loaded as boolean)
161
- );
155
+ return facts.auth.token !== "" && !facts.self.loaded;
162
156
  },
163
157
  require: (facts) => ({
164
158
  type: "FETCH_PERMISSIONS",
165
- role: facts.auth.role as string,
159
+ role: facts.auth.role,
166
160
  }),
167
161
  },
168
162
  },
@@ -186,7 +180,7 @@ export const permissionsModule = createModule("permissions", {
186
180
 
187
181
  export const contentSchema = {
188
182
  facts: {
189
- articles: t.object<Article[]>(),
183
+ articles: t.array<Article>(),
190
184
  loaded: t.boolean(),
191
185
  publishRequested: t.string(),
192
186
  deleteRequested: t.string(),
@@ -221,9 +215,7 @@ export const contentModule = createModule("content", {
221
215
  constraints: {
222
216
  loadContent: {
223
217
  when: (facts) => {
224
- return (
225
- (facts.auth.token as string) !== "" && !(facts.self.loaded as boolean)
226
- );
218
+ return facts.auth.token !== "" && !facts.self.loaded;
227
219
  },
228
220
  require: { type: "LOAD_CONTENT" },
229
221
  },
@@ -231,28 +223,26 @@ export const contentModule = createModule("content", {
231
223
  publishArticle: {
232
224
  when: (facts) => {
233
225
  return (
234
- (facts.self.publishRequested as string) !== "" &&
235
- (facts.permissions.permissions as string[]).includes(
236
- "content.publish",
237
- )
226
+ facts.self.publishRequested !== "" &&
227
+ facts.permissions.permissions.includes("content.publish")
238
228
  );
239
229
  },
240
230
  require: (facts) => ({
241
231
  type: "PUBLISH_ARTICLE",
242
- articleId: facts.self.publishRequested as string,
232
+ articleId: facts.self.publishRequested,
243
233
  }),
244
234
  },
245
235
 
246
236
  deleteArticle: {
247
237
  when: (facts) => {
248
238
  return (
249
- (facts.self.deleteRequested as string) !== "" &&
250
- (facts.permissions.permissions as string[]).includes("content.delete")
239
+ facts.self.deleteRequested !== "" &&
240
+ facts.permissions.permissions.includes("content.delete")
251
241
  );
252
242
  },
253
243
  require: (facts) => ({
254
244
  type: "DELETE_ARTICLE",
255
- articleId: facts.self.deleteRequested as string,
245
+ articleId: facts.self.deleteRequested,
256
246
  }),
257
247
  },
258
248
  },
@@ -275,8 +265,7 @@ export const contentModule = createModule("content", {
275
265
  context.facts.actionStatus = "publishing";
276
266
  await apiPublishArticle(req.articleId);
277
267
 
278
- const articles = context.facts.articles as Article[];
279
- context.facts.articles = articles.map((a) => {
268
+ context.facts.articles = context.facts.articles.map((a) => {
280
269
  if (a.id === req.articleId) {
281
270
  return { ...a, status: "published" as const };
282
271
  }
@@ -295,8 +284,9 @@ export const contentModule = createModule("content", {
295
284
  context.facts.actionStatus = "deleting";
296
285
  await apiDeleteArticle(req.articleId);
297
286
 
298
- const articles = context.facts.articles as Article[];
299
- context.facts.articles = articles.filter((a) => a.id !== req.articleId);
287
+ context.facts.articles = context.facts.articles.filter(
288
+ (a) => a.id !== req.articleId,
289
+ );
300
290
  context.facts.deleteRequested = "";
301
291
  context.facts.actionStatus = "done";
302
292
  },