@loom-framework/core 0.1.0-alpha.150 → 0.1.0-alpha.151

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 (83) hide show
  1. package/builtin-skills/app-skill/SKILL.md +2 -1
  2. package/builtin-skills/app-skill/references/events.md +119 -0
  3. package/dist/backend/auth/request-context.d.ts +15 -0
  4. package/dist/backend/auth/request-context.d.ts.map +1 -0
  5. package/dist/backend/auth/request-context.js +17 -0
  6. package/dist/backend/auth/request-context.js.map +1 -0
  7. package/dist/backend/events/event-bus.d.ts +39 -0
  8. package/dist/backend/events/event-bus.d.ts.map +1 -0
  9. package/dist/backend/events/event-bus.js +182 -0
  10. package/dist/backend/events/event-bus.js.map +1 -0
  11. package/dist/backend/events/event-emitting-adapter.d.ts +31 -0
  12. package/dist/backend/events/event-emitting-adapter.d.ts.map +1 -0
  13. package/dist/backend/events/event-emitting-adapter.js +70 -0
  14. package/dist/backend/events/event-emitting-adapter.js.map +1 -0
  15. package/dist/backend/events/event-registry.d.ts +24 -0
  16. package/dist/backend/events/event-registry.d.ts.map +1 -0
  17. package/dist/backend/events/event-registry.js +22 -0
  18. package/dist/backend/events/event-registry.js.map +1 -0
  19. package/dist/backend/events/index.d.ts +7 -0
  20. package/dist/backend/events/index.d.ts.map +1 -0
  21. package/dist/backend/events/index.js +7 -0
  22. package/dist/backend/events/index.js.map +1 -0
  23. package/dist/backend/index.d.ts +8 -0
  24. package/dist/backend/index.d.ts.map +1 -1
  25. package/dist/backend/index.js +93 -3
  26. package/dist/backend/index.js.map +1 -1
  27. package/dist/backend/routes/ai-config.d.ts +2 -0
  28. package/dist/backend/routes/ai-config.d.ts.map +1 -1
  29. package/dist/backend/routes/ai-config.js +2 -1
  30. package/dist/backend/routes/ai-config.js.map +1 -1
  31. package/dist/backend/routes/auth-routes.d.ts +2 -0
  32. package/dist/backend/routes/auth-routes.d.ts.map +1 -1
  33. package/dist/backend/routes/auth-routes.js +8 -1
  34. package/dist/backend/routes/auth-routes.js.map +1 -1
  35. package/dist/backend/routes/chat.d.ts +2 -0
  36. package/dist/backend/routes/chat.d.ts.map +1 -1
  37. package/dist/backend/routes/chat.js +3 -2
  38. package/dist/backend/routes/chat.js.map +1 -1
  39. package/dist/backend/routes/data.d.ts +2 -1
  40. package/dist/backend/routes/data.d.ts.map +1 -1
  41. package/dist/backend/routes/data.js +7 -1
  42. package/dist/backend/routes/data.js.map +1 -1
  43. package/dist/backend/routes/event-routes.d.ts +15 -0
  44. package/dist/backend/routes/event-routes.d.ts.map +1 -0
  45. package/dist/backend/routes/event-routes.js +35 -0
  46. package/dist/backend/routes/event-routes.js.map +1 -0
  47. package/dist/backend/routes/index.d.ts +2 -0
  48. package/dist/backend/routes/index.d.ts.map +1 -1
  49. package/dist/backend/routes/index.js +1 -0
  50. package/dist/backend/routes/index.js.map +1 -1
  51. package/dist/backend/routes/session-routes.d.ts +2 -0
  52. package/dist/backend/routes/session-routes.d.ts.map +1 -1
  53. package/dist/backend/routes/session-routes.js +4 -1
  54. package/dist/backend/routes/session-routes.js.map +1 -1
  55. package/dist/backend/routes/skills.d.ts +2 -0
  56. package/dist/backend/routes/skills.d.ts.map +1 -1
  57. package/dist/backend/routes/skills.js +4 -0
  58. package/dist/backend/routes/skills.js.map +1 -1
  59. package/dist/cli/commands/data.d.ts.map +1 -1
  60. package/dist/cli/commands/data.js +14 -0
  61. package/dist/cli/commands/data.js.map +1 -1
  62. package/dist/cli/generators/capability-generator.d.ts.map +1 -1
  63. package/dist/cli/generators/capability-generator.js +12 -1
  64. package/dist/cli/generators/capability-generator.js.map +1 -1
  65. package/dist/config.d.ts +329 -13
  66. package/dist/config.d.ts.map +1 -1
  67. package/dist/config.js +24 -1
  68. package/dist/config.js.map +1 -1
  69. package/dist/index.d.ts +5 -0
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +5 -0
  72. package/dist/index.js.map +1 -1
  73. package/dist/types/config.d.ts +2 -0
  74. package/dist/types/config.d.ts.map +1 -1
  75. package/dist/types/event.d.ts +87 -0
  76. package/dist/types/event.d.ts.map +1 -0
  77. package/dist/types/event.js +38 -0
  78. package/dist/types/event.js.map +1 -0
  79. package/dist/types/index.d.ts +2 -0
  80. package/dist/types/index.d.ts.map +1 -1
  81. package/dist/types/index.js +1 -0
  82. package/dist/types/index.js.map +1 -1
  83. package/package.json +1 -1
@@ -29,4 +29,5 @@ version: 1.0.0
29
29
 
30
30
  - 数据模型结构、CLI 语法和操作规范:**references/models.md**
31
31
  - 语义引导(示例数据生成、筛选选择、关系推断):**references/data-semantics.md**
32
- <!-- AUTH_REF -->
32
+ <!-- AUTH_REF -->
33
+ <!-- EVENTS_REF -->
@@ -0,0 +1,119 @@
1
+ # 事件系统参考
2
+
3
+ Loom 事件系统在数据变更和系统操作时自动触发事件,可用于通知、审计和自动化。
4
+
5
+ ## 事件模式格式
6
+
7
+ 事件使用 `category:action:target` 三段式模式:
8
+
9
+ | 段 | 说明 | 示例 |
10
+ |----|------|------|
11
+ | category | 事件类别 | `data`, `user`, `skill`, `ai`, `session`, `file` |
12
+ | action | 操作类型 | `create`, `update`, `delete`, `login`, `logout` |
13
+ | target | 操作对象 | 模型名、`models`、技能名等 |
14
+
15
+ ## 通配符订阅
16
+
17
+ | 通配符 | 匹配规则 | 示例 |
18
+ |--------|----------|------|
19
+ | `*` | 单段匹配 | `data:*:tasks` 匹配 `data:create:tasks`、`data:update:tasks` |
20
+ | `**` | 任意深度匹配 | `data:**` 匹配所有 data 类事件 |
21
+
22
+ ## 数据事件(EventEmittingAdapter 自动触发)
23
+
24
+ 这些事件由 DataAdapter 操作自动触发,无需手动代码:
25
+
26
+ | 事件模式 | 触发时机 | Payload 字段 |
27
+ |----------|----------|-------------|
28
+ | `data:create:<model>` | 创建记录 | model, id, data |
29
+ | `data:update:<model>` | 更新记录 | model, id, data, previousData, changedFields |
30
+ | `data:delete:<model>` | 删除记录 | model, id, previousData |
31
+ | `data:import:<model>` | CSV 导入完成 | model, imported, errors |
32
+ | `data:batch_delete:<model>` | 批量删除完成 | model, count, errors |
33
+
34
+ ## 认证事件
35
+
36
+ | 事件模式 | 触发时机 | Payload 字段 |
37
+ |----------|----------|-------------|
38
+ | `user:login` | 用户登录 | userId, username, role |
39
+ | `user:logout` | 用户登出 | userId |
40
+ | `user:created` | 创建用户 | userId, username, role |
41
+ | `user:updated` | 更新用户 | userId, username, role |
42
+ | `user:deleted` | 删除用户 | userId |
43
+
44
+ ## 技能管理事件
45
+
46
+ | 事件模式 | 触发时机 | Payload 字段 |
47
+ |----------|----------|-------------|
48
+ | `skill:created` | 创建技能 | skillName |
49
+ | `skill:deleted` | 删除技能 | skillName |
50
+ | `skill:file_updated` | 更新技能文件 | skillName, filename, path |
51
+
52
+ ## AI 配置事件
53
+
54
+ | 事件模式 | 触发时机 | Payload 字段 |
55
+ |----------|----------|-------------|
56
+ | `ai:models_updated` | 模型列表更新 | count |
57
+
58
+ ## 会话事件
59
+
60
+ | 事件模式 | 触发时机 | Payload 字段 |
61
+ |----------|----------|-------------|
62
+ | `session:created` | 创建会话 | sessionId |
63
+ | `session:deleted` | 删除会话 | sessionId |
64
+ | `session:truncated` | 截断会话消息 | sessionId, fromIndex |
65
+
66
+ ## 文件上传事件
67
+
68
+ | 事件模式 | 触发时机 | Payload 字段 |
69
+ |----------|----------|-------------|
70
+ | `file:uploaded` | 文件上传成功 | filename, sessionId, path, size |
71
+
72
+ ## 配置声明式订阅
73
+
74
+ 在 `loom.config.ts` 中声明事件处理器:
75
+
76
+ ```typescript
77
+ export default defineConfig({
78
+ // ...
79
+ events: {
80
+ subscriptions: [
81
+ {
82
+ pattern: 'data:create:orders',
83
+ handler: 'webhook',
84
+ config: { url: 'https://example.com/webhook' },
85
+ },
86
+ {
87
+ pattern: 'user:login',
88
+ handler: 'log',
89
+ config: { level: 'info' },
90
+ },
91
+ ],
92
+ },
93
+ });
94
+ ```
95
+
96
+ ## 事件 API
97
+
98
+ | 端点 | 方法 | 说明 |
99
+ |------|------|------|
100
+ | `/api/v1/events/notify` | POST | 外部事件注入(CLI 使用) |
101
+ | `/api/v1/events/patterns` | GET | 查看已注册的事件模式 |
102
+
103
+ ### POST /api/v1/events/notify
104
+
105
+ ```json
106
+ {
107
+ "pattern": "data:create:tasks",
108
+ "payload": { "model": "tasks", "id": "rec_123" },
109
+ "source": "cli"
110
+ }
111
+ ```
112
+
113
+ ## 订阅可用处理器
114
+
115
+ | handler | 说明 | config 字段 |
116
+ |---------|------|------------|
117
+ | `log` | 写入服务器日志 | `level`: info/debug/warn |
118
+ | `webhook` | 发送 HTTP 请求 | `url`, `method`, `headers` |
119
+ | `process` | 启动进程(未来) | `process`, `filter` |
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Request-scoped context via AsyncLocalStorage
3
+ *
4
+ * Allows EventEmittingAdapter to access userId from the current
5
+ * HTTP request without coupling to the Fastify request object.
6
+ */
7
+ interface RequestContext {
8
+ userId?: string;
9
+ }
10
+ /** Get the current request context (undefined if outside a request) */
11
+ export declare function getRequestContext(): RequestContext | undefined;
12
+ /** Set context for the current async execution path */
13
+ export declare function setRequestContext(ctx: RequestContext): void;
14
+ export {};
15
+ //# sourceMappingURL=request-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../../src/backend/auth/request-context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,uEAAuE;AACvE,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CAE9D;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAE3D"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Request-scoped context via AsyncLocalStorage
3
+ *
4
+ * Allows EventEmittingAdapter to access userId from the current
5
+ * HTTP request without coupling to the Fastify request object.
6
+ */
7
+ import { AsyncLocalStorage } from 'async_hooks';
8
+ const asyncLocalStorage = new AsyncLocalStorage();
9
+ /** Get the current request context (undefined if outside a request) */
10
+ export function getRequestContext() {
11
+ return asyncLocalStorage.getStore();
12
+ }
13
+ /** Set context for the current async execution path */
14
+ export function setRequestContext(ctx) {
15
+ asyncLocalStorage.enterWith(ctx);
16
+ }
17
+ //# sourceMappingURL=request-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../../src/backend/auth/request-context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAMhD,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAkB,CAAC;AAElE,uEAAuE;AACvE,MAAM,UAAU,iBAAiB;IAC/B,OAAO,iBAAiB,CAAC,QAAQ,EAAE,CAAC;AACtC,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,iBAAiB,CAAC,GAAmB;IACnD,iBAAiB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * EventBus - Universal event bus with pattern matching and batch support
3
+ *
4
+ * - Pattern matching: `data:create:tasks`, `data:*:tasks`, `data:**`, `*:create:*`
5
+ * - Wildcards: `*` = single segment (`[^:]+`), `**` = any depth (`.*`)
6
+ * - Fire-and-forget emit: handler errors are caught and logged, never propagated
7
+ * - beginBatch/endBatch: suppress fine-grained events, emit aggregate only
8
+ * - Circular detection: warn when emit depth exceeds 10
9
+ */
10
+ import type { LoomEvent, EventMeta } from '../../types/event.js';
11
+ type EventHandler = (event: LoomEvent) => void | Promise<void>;
12
+ export declare class EventBus {
13
+ private handlers;
14
+ private wildcards;
15
+ private patternCache;
16
+ private batchStack;
17
+ private suppressedEvents;
18
+ private emitDepth;
19
+ /** Subscribe to an event pattern. Returns unsubscribe function. */
20
+ on(pattern: string, handler: EventHandler): () => void;
21
+ /** Unsubscribe a handler from a pattern. */
22
+ off(pattern: string, handler: EventHandler): void;
23
+ /** Emit an event — fire-and-forget. Handler errors are caught and logged. */
24
+ emit(pattern: string, payload: Record<string, unknown>, meta?: EventMeta): void;
25
+ /** Check if a pattern has any subscribers (for previousData optimization). */
26
+ hasSubscribers(pattern: string): boolean;
27
+ /** Begin a batch operation. Returns batchId. */
28
+ beginBatch(batchPattern: string): string;
29
+ /** End a batch operation. Emits aggregate event with merged payload. */
30
+ endBatch(batchId: string, payload: Record<string, unknown>, meta?: EventMeta): void;
31
+ /** Remove all handlers (for server shutdown). */
32
+ removeAllHandlers(): void;
33
+ /** Dispatch event to all matching handlers. Fire-and-forget: errors are caught, never propagated. */
34
+ private dispatch;
35
+ /** Compile a pattern string to a RegExp. Caches compiled patterns. */
36
+ private compilePattern;
37
+ }
38
+ export {};
39
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../../src/backend/events/event-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjE,KAAK,YAAY,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAQ/D,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,UAAU,CAAmD;IACrE,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,SAAS,CAAK;IAEtB,mEAAmE;IACnE,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,IAAI;IAuBtD,4CAA4C;IAC5C,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAejD,6EAA6E;IAC7E,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI;IA4B/E,8EAA8E;IAC9E,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAOxC,gDAAgD;IAChD,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAMxC,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI;IAkBnF,iDAAiD;IACjD,iBAAiB,IAAI,IAAI;IAQzB,qGAAqG;IACrG,OAAO,CAAC,QAAQ;IAkChB,sEAAsE;IACtE,OAAO,CAAC,cAAc;CAwBvB"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * EventBus - Universal event bus with pattern matching and batch support
3
+ *
4
+ * - Pattern matching: `data:create:tasks`, `data:*:tasks`, `data:**`, `*:create:*`
5
+ * - Wildcards: `*` = single segment (`[^:]+`), `**` = any depth (`.*`)
6
+ * - Fire-and-forget emit: handler errors are caught and logged, never propagated
7
+ * - beginBatch/endBatch: suppress fine-grained events, emit aggregate only
8
+ * - Circular detection: warn when emit depth exceeds 10
9
+ */
10
+ export class EventBus {
11
+ handlers = new Map();
12
+ wildcards = [];
13
+ patternCache = new Map();
14
+ batchStack = [];
15
+ suppressedEvents = [];
16
+ emitDepth = 0;
17
+ /** Subscribe to an event pattern. Returns unsubscribe function. */
18
+ on(pattern, handler) {
19
+ if (pattern.includes('*')) {
20
+ const regex = this.compilePattern(pattern);
21
+ this.wildcards.push({ pattern, regex, handler });
22
+ return () => {
23
+ const idx = this.wildcards.findIndex(w => w.pattern === pattern && w.handler === handler);
24
+ if (idx !== -1)
25
+ this.wildcards.splice(idx, 1);
26
+ };
27
+ }
28
+ const list = this.handlers.get(pattern) ?? [];
29
+ list.push(handler);
30
+ this.handlers.set(pattern, list);
31
+ return () => {
32
+ const arr = this.handlers.get(pattern);
33
+ if (arr) {
34
+ const idx = arr.indexOf(handler);
35
+ if (idx !== -1)
36
+ arr.splice(idx, 1);
37
+ if (arr.length === 0)
38
+ this.handlers.delete(pattern);
39
+ }
40
+ };
41
+ }
42
+ /** Unsubscribe a handler from a pattern. */
43
+ off(pattern, handler) {
44
+ if (pattern.includes('*')) {
45
+ const idx = this.wildcards.findIndex(w => w.pattern === pattern && w.handler === handler);
46
+ if (idx !== -1)
47
+ this.wildcards.splice(idx, 1);
48
+ return;
49
+ }
50
+ const arr = this.handlers.get(pattern);
51
+ if (arr) {
52
+ const idx = arr.indexOf(handler);
53
+ if (idx !== -1)
54
+ arr.splice(idx, 1);
55
+ if (arr.length === 0)
56
+ this.handlers.delete(pattern);
57
+ }
58
+ }
59
+ /** Emit an event — fire-and-forget. Handler errors are caught and logged. */
60
+ emit(pattern, payload, meta) {
61
+ this.emitDepth++;
62
+ if (this.emitDepth > 10) {
63
+ console.warn(`[EventBus] Circular emit detected (depth=${this.emitDepth}) for pattern: ${pattern}`);
64
+ }
65
+ try {
66
+ const event = {
67
+ id: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`,
68
+ pattern,
69
+ payload,
70
+ userId: meta?.userId,
71
+ source: meta?.source ?? 'server',
72
+ timestamp: new Date().toISOString(),
73
+ };
74
+ // If inside a batch, suppress the event
75
+ if (this.batchStack.length > 0) {
76
+ this.suppressedEvents.push(event);
77
+ return;
78
+ }
79
+ this.dispatch(event);
80
+ }
81
+ finally {
82
+ this.emitDepth--;
83
+ }
84
+ }
85
+ /** Check if a pattern has any subscribers (for previousData optimization). */
86
+ hasSubscribers(pattern) {
87
+ if (this.handlers.has(pattern) && this.handlers.get(pattern).length > 0) {
88
+ return true;
89
+ }
90
+ return this.wildcards.some(w => w.regex.test(pattern));
91
+ }
92
+ /** Begin a batch operation. Returns batchId. */
93
+ beginBatch(batchPattern) {
94
+ const batchId = `batch_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
95
+ this.batchStack.push({ batchId, pattern: batchPattern });
96
+ return batchId;
97
+ }
98
+ /** End a batch operation. Emits aggregate event with merged payload. */
99
+ endBatch(batchId, payload, meta) {
100
+ const idx = this.batchStack.findIndex(b => b.batchId === batchId);
101
+ if (idx === -1)
102
+ return;
103
+ const batch = this.batchStack[idx];
104
+ // Remove from stack
105
+ this.batchStack.splice(idx, 1);
106
+ // Clear suppressed events when batch stack is empty
107
+ if (this.batchStack.length === 0) {
108
+ this.suppressedEvents = [];
109
+ }
110
+ // Emit aggregate event using the stored pattern
111
+ this.emit(batch.pattern, payload, meta);
112
+ }
113
+ /** Remove all handlers (for server shutdown). */
114
+ removeAllHandlers() {
115
+ this.handlers.clear();
116
+ this.wildcards = [];
117
+ this.patternCache.clear();
118
+ this.batchStack = [];
119
+ this.suppressedEvents = [];
120
+ }
121
+ /** Dispatch event to all matching handlers. Fire-and-forget: errors are caught, never propagated. */
122
+ dispatch(event) {
123
+ // Exact match handlers
124
+ const exactHandlers = this.handlers.get(event.pattern) ?? [];
125
+ for (const handler of exactHandlers) {
126
+ try {
127
+ const result = handler(event);
128
+ // If handler returns a promise, catch its rejection silently
129
+ if (result instanceof Promise) {
130
+ result.catch(err => {
131
+ console.error(`[EventBus] Async handler error for ${event.pattern}:`, err);
132
+ });
133
+ }
134
+ }
135
+ catch (err) {
136
+ console.error(`[EventBus] Handler error for ${event.pattern}:`, err);
137
+ }
138
+ }
139
+ // Wildcard handlers
140
+ for (const entry of this.wildcards) {
141
+ if (entry.regex.test(event.pattern)) {
142
+ try {
143
+ const result = entry.handler(event);
144
+ if (result instanceof Promise) {
145
+ result.catch(err => {
146
+ console.error(`[EventBus] Async handler error for wildcard ${entry.pattern}:`, err);
147
+ });
148
+ }
149
+ }
150
+ catch (err) {
151
+ console.error(`[EventBus] Handler error for wildcard ${entry.pattern}:`, err);
152
+ }
153
+ }
154
+ }
155
+ }
156
+ /** Compile a pattern string to a RegExp. Caches compiled patterns. */
157
+ compilePattern(pattern) {
158
+ const cached = this.patternCache.get(pattern);
159
+ if (cached)
160
+ return cached;
161
+ // Lone `*` matches everything
162
+ if (pattern === '*') {
163
+ const regex = /^.*$/;
164
+ this.patternCache.set(pattern, regex);
165
+ return regex;
166
+ }
167
+ const regexStr = pattern
168
+ .split(':')
169
+ .map(segment => {
170
+ if (segment === '**')
171
+ return '.*';
172
+ if (segment.includes('*'))
173
+ return segment.replace(/\*/g, '[^:]+');
174
+ return segment;
175
+ })
176
+ .join(':');
177
+ const regex = new RegExp(`^${regexStr}$`);
178
+ this.patternCache.set(pattern, regex);
179
+ return regex;
180
+ }
181
+ }
182
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/backend/events/event-bus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * EventEmittingAdapter - Decorator that wraps DataAdapter to auto-emit events
3
+ *
4
+ * - write() → emits data:create:<model> with { model, id, data }
5
+ * - update() → emits data:update:<model> with { model, id, data, previousData, changedFields }
6
+ * - delete() → emits data:delete:<model> with { model, id, previousData }
7
+ * - hasSubscribers() optimization: skips previousData read when no subscribers
8
+ * - Events only emitted after inner operation succeeds
9
+ * - getUserId callback for injecting userId (auth-aware)
10
+ */
11
+ import type { DataAdapter, DataRecord, ReadOptions } from '../../types/adapter.js';
12
+ import type { ModelSchema } from '../../types/model.js';
13
+ import type { EventBus } from './event-bus.js';
14
+ export declare class EventEmittingAdapter implements DataAdapter {
15
+ private inner;
16
+ private eventBus;
17
+ private source;
18
+ private getUserId?;
19
+ readonly name: string;
20
+ constructor(inner: DataAdapter, eventBus: EventBus, source: 'server' | 'cli', getUserId?: (() => string | undefined) | undefined);
21
+ write(model: string, data: DataRecord): Promise<DataRecord>;
22
+ update(model: string, id: string, data: DataRecord): Promise<DataRecord>;
23
+ delete(model: string, id: string): Promise<void>;
24
+ read(model: string, options?: ReadOptions): Promise<DataRecord | DataRecord[] | null>;
25
+ count(model: string, options?: Omit<ReadOptions, 'limit' | 'offset' | 'sort'>): Promise<number>;
26
+ getSchema(model: string): Promise<ModelSchema | undefined>;
27
+ listModels(): Promise<string[]>;
28
+ initialize(): Promise<void>;
29
+ healthCheck(): Promise<boolean>;
30
+ }
31
+ //# sourceMappingURL=event-emitting-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-emitting-adapter.d.ts","sourceRoot":"","sources":["../../../src/backend/events/event-emitting-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,qBAAa,oBAAqB,YAAW,WAAW;IAIpD,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS,CAAC;IANpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAGZ,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,QAAQ,GAAG,KAAK,EACxB,SAAS,CAAC,GAAE,MAAM,MAAM,GAAG,SAAS,aAAA;IAKxC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAU3D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAiBxE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAehD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC;IAIrF,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/F,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAI1D,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAGtC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * EventEmittingAdapter - Decorator that wraps DataAdapter to auto-emit events
3
+ *
4
+ * - write() → emits data:create:<model> with { model, id, data }
5
+ * - update() → emits data:update:<model> with { model, id, data, previousData, changedFields }
6
+ * - delete() → emits data:delete:<model> with { model, id, previousData }
7
+ * - hasSubscribers() optimization: skips previousData read when no subscribers
8
+ * - Events only emitted after inner operation succeeds
9
+ * - getUserId callback for injecting userId (auth-aware)
10
+ */
11
+ import { EventPatterns } from '../../types/event.js';
12
+ export class EventEmittingAdapter {
13
+ inner;
14
+ eventBus;
15
+ source;
16
+ getUserId;
17
+ name;
18
+ constructor(inner, eventBus, source, getUserId) {
19
+ this.inner = inner;
20
+ this.eventBus = eventBus;
21
+ this.source = source;
22
+ this.getUserId = getUserId;
23
+ this.name = `event-emitting:${inner.name}`;
24
+ }
25
+ async write(model, data) {
26
+ const record = await this.inner.write(model, data);
27
+ void this.eventBus.emit(EventPatterns.DATA_CREATE(model), { model, id: record.id, data: record }, { userId: this.getUserId?.(), source: this.source });
28
+ return record;
29
+ }
30
+ async update(model, id, data) {
31
+ const pattern = EventPatterns.DATA_UPDATE(model);
32
+ const previous = this.eventBus.hasSubscribers(pattern)
33
+ ? await this.inner.read(model, { id }).catch(() => null)
34
+ : null;
35
+ const record = await this.inner.update(model, id, data);
36
+ const changedFields = previous
37
+ ? Object.keys(data).filter(k => data[k] !== previous?.[k])
38
+ : undefined;
39
+ void this.eventBus.emit(pattern, { model, id, data: record, previousData: previous ?? undefined, changedFields }, { userId: this.getUserId?.(), source: this.source });
40
+ return record;
41
+ }
42
+ async delete(model, id) {
43
+ const pattern = EventPatterns.DATA_DELETE(model);
44
+ const previous = this.eventBus.hasSubscribers(pattern)
45
+ ? await this.inner.read(model, { id }).catch(() => null)
46
+ : null;
47
+ await this.inner.delete(model, id);
48
+ void this.eventBus.emit(pattern, { model, id, previousData: previous ?? undefined }, { userId: this.getUserId?.(), source: this.source });
49
+ }
50
+ // ── Pure delegation (no events for read operations) ──
51
+ async read(model, options) {
52
+ return this.inner.read(model, options);
53
+ }
54
+ async count(model, options) {
55
+ return this.inner.count(model, options);
56
+ }
57
+ async getSchema(model) {
58
+ return this.inner.getSchema(model);
59
+ }
60
+ async listModels() {
61
+ return this.inner.listModels();
62
+ }
63
+ async initialize() {
64
+ return this.inner.initialize();
65
+ }
66
+ async healthCheck() {
67
+ return this.inner.healthCheck();
68
+ }
69
+ }
70
+ //# sourceMappingURL=event-emitting-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-emitting-adapter.js","sourceRoot":"","sources":["../../../src/backend/events/event-emitting-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * EventRegistry - Tracks registered event patterns (P0 internal use only)
3
+ *
4
+ * Provides introspection for GET /api/v1/events/patterns (P1 API).
5
+ * Currently used internally by capability-generator for events.md generation.
6
+ */
7
+ export declare class EventRegistry {
8
+ private patterns;
9
+ register(pattern: string, category: string, description: string, payloadShape: string): void;
10
+ isRegistered(pattern: string): boolean;
11
+ getPatterns(): Array<{
12
+ pattern: string;
13
+ category: string;
14
+ description: string;
15
+ payloadShape: string;
16
+ }>;
17
+ getByCategory(category: string): Array<{
18
+ pattern: string;
19
+ category: string;
20
+ description: string;
21
+ payloadShape: string;
22
+ }>;
23
+ }
24
+ //# sourceMappingURL=event-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-registry.d.ts","sourceRoot":"","sources":["../../../src/backend/events/event-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAA2F;IAE3G,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAI5F,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAItC,WAAW,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAItG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAGzH"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * EventRegistry - Tracks registered event patterns (P0 internal use only)
3
+ *
4
+ * Provides introspection for GET /api/v1/events/patterns (P1 API).
5
+ * Currently used internally by capability-generator for events.md generation.
6
+ */
7
+ export class EventRegistry {
8
+ patterns = new Map();
9
+ register(pattern, category, description, payloadShape) {
10
+ this.patterns.set(pattern, { category, description, payloadShape });
11
+ }
12
+ isRegistered(pattern) {
13
+ return this.patterns.has(pattern);
14
+ }
15
+ getPatterns() {
16
+ return Array.from(this.patterns.entries()).map(([pattern, info]) => ({ pattern, ...info }));
17
+ }
18
+ getByCategory(category) {
19
+ return this.getPatterns().filter(p => p.category === category);
20
+ }
21
+ }
22
+ //# sourceMappingURL=event-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-registry.js","sourceRoot":"","sources":["../../../src/backend/events/event-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,OAAO,aAAa;IAChB,QAAQ,GAAiF,IAAI,GAAG,EAAE,CAAC;IAE3G,QAAQ,CAAC,OAAe,EAAE,QAAgB,EAAE,WAAmB,EAAE,YAAoB;QACnF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,YAAY,CAAC,OAAe;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,WAAW;QACT,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,aAAa,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IACjE,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Events Module - Barrel Export
3
+ */
4
+ export { EventBus } from './event-bus.js';
5
+ export { EventEmittingAdapter } from './event-emitting-adapter.js';
6
+ export { EventRegistry } from './event-registry.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/backend/events/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Events Module - Barrel Export
3
+ */
4
+ export { EventBus } from './event-bus.js';
5
+ export { EventEmittingAdapter } from './event-emitting-adapter.js';
6
+ export { EventRegistry } from './event-registry.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/backend/events/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -13,6 +13,8 @@ import type { AIEngine } from '../types/ai.js';
13
13
  import type { DataAdapter } from '../types/adapter.js';
14
14
  import { UserStore } from './auth/user-store.js';
15
15
  import { TokenStore } from './auth/token-store.js';
16
+ import { EventBus } from './events/event-bus.js';
17
+ import { EventRegistry } from './events/event-registry.js';
16
18
  export interface LoomServerOptions {
17
19
  /** Project root directory containing loom.config.ts */
18
20
  projectRoot: string;
@@ -34,6 +36,8 @@ export declare class LoomServer {
34
36
  private fastify;
35
37
  private userStore?;
36
38
  private tokenStore?;
39
+ private eventBus?;
40
+ private eventRegistry?;
37
41
  private projectRoot;
38
42
  private options;
39
43
  constructor(options: LoomServerOptions);
@@ -59,6 +63,10 @@ export declare class LoomServer {
59
63
  getUserStore(): UserStore | undefined;
60
64
  /** Expose token store for testing */
61
65
  getTokenStore(): TokenStore | undefined;
66
+ /** Expose event bus for testing */
67
+ getEventBus(): EventBus | undefined;
68
+ /** Expose event registry for testing */
69
+ getEventRegistry(): EventRegistry | undefined;
62
70
  }
63
71
  /**
64
72
  * Create and start a LoomServer from a project root
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,mBAAmB;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAoB;gBAEvB,OAAO,EAAE,iBAAiB;IAKtC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiIjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,0CAA0C;IAC1C,UAAU,IAAI,UAAU,CAAC,OAAO,OAAO,CAAC;IAIxC,gCAAgC;IAChC,SAAS,IAAI,UAAU;IAIvB,iCAAiC;IACjC,UAAU,IAAI,WAAW;IAIzB,oCAAoC;IACpC,YAAY,IAAI,SAAS,GAAG,SAAS;IAIrC,qCAAqC;IACrC,aAAa,IAAI,UAAU,GAAG,SAAS;CAGxC;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAK1E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAG3D,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,mBAAmB;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAC,CAAW;IAC5B,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAoB;gBAEvB,OAAO,EAAE,iBAAiB;IAKtC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA6MjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,0CAA0C;IAC1C,UAAU,IAAI,UAAU,CAAC,OAAO,OAAO,CAAC;IAIxC,gCAAgC;IAChC,SAAS,IAAI,UAAU;IAIvB,iCAAiC;IACjC,UAAU,IAAI,WAAW;IAIzB,oCAAoC;IACpC,YAAY,IAAI,SAAS,GAAG,SAAS;IAIrC,qCAAqC;IACrC,aAAa,IAAI,UAAU,GAAG,SAAS;IAIvC,mCAAmC;IACnC,WAAW,IAAI,QAAQ,GAAG,SAAS;IAInC,wCAAwC;IACxC,gBAAgB,IAAI,aAAa,GAAG,SAAS;CAG9C;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAK1E"}