Skip to content

Commit 7b752b1

Browse files
Claudehotlong
andauthored
Phase 1: Add event schemas and extend IRealtimeService
- Add packages/spec/src/api/events.zod.ts with MetadataEvent and DataEvent schemas - Extend IRealtimeService with RealtimeSubscriptionFilter - Add subscribeMetadata() and subscribeData() convenience methods Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/6a38da2b-8234-4c22-b456-ec507a8f82f2 Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 86b56ea commit 7b752b1

3 files changed

Lines changed: 177 additions & 0 deletions

File tree

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import { z } from 'zod';
4+
5+
/**
6+
* Metadata Event Types
7+
*
8+
* Triggered when metadata items are created, updated, or deleted.
9+
* Follows the pattern: `metadata.{type}.{action}`
10+
*
11+
* Examples:
12+
* - `metadata.object.created` - A new object was created
13+
* - `metadata.view.updated` - A view was updated
14+
* - `metadata.agent.deleted` - An agent was deleted
15+
*/
16+
export const MetadataEventType = z.enum([
17+
'metadata.object.created',
18+
'metadata.object.updated',
19+
'metadata.object.deleted',
20+
'metadata.field.created',
21+
'metadata.field.updated',
22+
'metadata.field.deleted',
23+
'metadata.view.created',
24+
'metadata.view.updated',
25+
'metadata.view.deleted',
26+
'metadata.app.created',
27+
'metadata.app.updated',
28+
'metadata.app.deleted',
29+
'metadata.agent.created',
30+
'metadata.agent.updated',
31+
'metadata.agent.deleted',
32+
'metadata.tool.created',
33+
'metadata.tool.updated',
34+
'metadata.tool.deleted',
35+
'metadata.flow.created',
36+
'metadata.flow.updated',
37+
'metadata.flow.deleted',
38+
'metadata.action.created',
39+
'metadata.action.updated',
40+
'metadata.action.deleted',
41+
'metadata.workflow.created',
42+
'metadata.workflow.updated',
43+
'metadata.workflow.deleted',
44+
'metadata.dashboard.created',
45+
'metadata.dashboard.updated',
46+
'metadata.dashboard.deleted',
47+
'metadata.report.created',
48+
'metadata.report.updated',
49+
'metadata.report.deleted',
50+
'metadata.role.created',
51+
'metadata.role.updated',
52+
'metadata.role.deleted',
53+
'metadata.permission.created',
54+
'metadata.permission.updated',
55+
'metadata.permission.deleted',
56+
]);
57+
58+
export type MetadataEventType = z.infer<typeof MetadataEventType>;
59+
60+
/**
61+
* Data Event Types
62+
*
63+
* Triggered when data records are created, updated, or deleted.
64+
* Follows the pattern: `data.record.{action}`
65+
*/
66+
export const DataEventType = z.enum([
67+
'data.record.created',
68+
'data.record.updated',
69+
'data.record.deleted',
70+
'data.field.changed',
71+
]);
72+
73+
export type DataEventType = z.infer<typeof DataEventType>;
74+
75+
/**
76+
* Metadata Event Payload
77+
*
78+
* Represents a metadata change event (create, update, delete).
79+
* Used for real-time synchronization of metadata across clients.
80+
*/
81+
export const MetadataEventSchema = z.object({
82+
/** Unique event identifier */
83+
id: z.string().uuid().describe('Unique event identifier'),
84+
85+
/** Event type (metadata.{type}.{action}) */
86+
type: MetadataEventType.describe('Event type'),
87+
88+
/** Metadata type (object, view, agent, tool, etc.) */
89+
metadataType: z.string().describe('Metadata type (object, view, agent, etc.)'),
90+
91+
/** Metadata item name */
92+
name: z.string().describe('Metadata item name'),
93+
94+
/** Package ID (if applicable) */
95+
packageId: z.string().optional().describe('Package ID'),
96+
97+
/** Full definition (only for create/update events) */
98+
definition: z.unknown().optional().describe('Full definition (create/update only)'),
99+
100+
/** User who triggered the event */
101+
userId: z.string().optional().describe('User who triggered the event'),
102+
103+
/** Event timestamp (ISO 8601) */
104+
timestamp: z.string().datetime().describe('Event timestamp'),
105+
});
106+
107+
export type MetadataEvent = z.infer<typeof MetadataEventSchema>;
108+
109+
/**
110+
* Data Event Payload
111+
*
112+
* Represents a data record change event (create, update, delete).
113+
* Used for real-time synchronization of data records across clients.
114+
*/
115+
export const DataEventSchema = z.object({
116+
/** Unique event identifier */
117+
id: z.string().uuid().describe('Unique event identifier'),
118+
119+
/** Event type (data.record.{action}) */
120+
type: DataEventType.describe('Event type'),
121+
122+
/** Object name */
123+
object: z.string().describe('Object name'),
124+
125+
/** Record ID */
126+
recordId: z.string().describe('Record ID'),
127+
128+
/** Changed fields (update events only) */
129+
changes: z.record(z.string(), z.unknown()).optional().describe('Changed fields'),
130+
131+
/** Record before update (update events only) */
132+
before: z.record(z.string(), z.unknown()).optional().describe('Before state'),
133+
134+
/** Record after update (create/update events) */
135+
after: z.record(z.string(), z.unknown()).optional().describe('After state'),
136+
137+
/** User who triggered the event */
138+
userId: z.string().optional().describe('User who triggered the event'),
139+
140+
/** Event timestamp (ISO 8601) */
141+
timestamp: z.string().datetime().describe('Event timestamp'),
142+
});
143+
144+
export type DataEvent = z.infer<typeof DataEventSchema>;

packages/spec/src/api/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
export * from './contract.zod';
1717
export * from './endpoint.zod';
1818
export * from './discovery.zod';
19+
export * from './events.zod';
1920
export * from './realtime-shared.zod';
2021
export * from './realtime.zod';
2122
export * from './websocket.zod';

packages/spec/src/contracts/realtime-service.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ export interface RealtimeSubscriptionOptions {
4444
filter?: Record<string, unknown>;
4545
}
4646

47+
/**
48+
* Enhanced subscription filter for metadata and data events
49+
*/
50+
export interface RealtimeSubscriptionFilter {
51+
/** Metadata type filter (object, view, agent, tool, etc.) */
52+
type?: string;
53+
/** Package ID filter */
54+
packageId?: string;
55+
/** Event types to listen for */
56+
eventTypes?: string[];
57+
/** Record ID filter (for data events) */
58+
recordId?: string;
59+
/** Field names filter (for data events) */
60+
fields?: string[];
61+
}
62+
4763
export interface IRealtimeService {
4864
/**
4965
* Publish an event to all subscribers
@@ -72,4 +88,20 @@ export interface IRealtimeService {
7288
* @returns Standard Response object
7389
*/
7490
handleUpgrade?(request: Request): Promise<Response>;
91+
92+
/**
93+
* Subscribe to metadata events (convenience method)
94+
* @param filter - Subscription filter
95+
* @param handler - Event handler function
96+
* @returns Subscription identifier for unsubscribing
97+
*/
98+
subscribeMetadata?(filter: RealtimeSubscriptionFilter, handler: RealtimeEventHandler): Promise<string>;
99+
100+
/**
101+
* Subscribe to data events (convenience method)
102+
* @param filter - Subscription filter
103+
* @param handler - Event handler function
104+
* @returns Subscription identifier for unsubscribing
105+
*/
106+
subscribeData?(filter: RealtimeSubscriptionFilter, handler: RealtimeEventHandler): Promise<string>;
75107
}

0 commit comments

Comments
 (0)