@omnibase/core-js 0.6.0 → 0.7.1

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.
@@ -102,4 +102,197 @@ import { PostgrestClient } from '@supabase/postgrest-js';
102
102
  */
103
103
  declare const createClient: <T = any>(url: string, anonKey: string, getCookie: (cookie: string) => string) => PostgrestClient<T>;
104
104
 
105
- export { createClient };
105
+ /**
106
+ * Real-time database events client for WebSocket subscriptions
107
+ *
108
+ * This module provides a universal WebSocket client for subscribing to real-time
109
+ * database changes with Row-Level Security (RLS) authentication. Works in both
110
+ * browser and Node.js environments.
111
+ *
112
+ * @module Database Events
113
+ */
114
+ /**
115
+ * Subscription options for database events
116
+ */
117
+ interface SubscriptionOptions {
118
+ /** Specific row ID to subscribe to (optional) */
119
+ rowId?: string;
120
+ /** Specific columns to filter updates (optional) */
121
+ columns?: string[];
122
+ /** Callback function triggered on data updates */
123
+ onChange?: (data: any, message: UpdateMessage) => void;
124
+ }
125
+ /**
126
+ * Subscription request sent to the server
127
+ */
128
+ interface Subscription {
129
+ table: string;
130
+ row_id?: string;
131
+ columns?: string[];
132
+ jwt: string;
133
+ }
134
+ /**
135
+ * Message sent from client to server
136
+ */
137
+ interface SubscriptionMessage {
138
+ action: "subscribe" | "unsubscribe";
139
+ subscription: Subscription;
140
+ }
141
+ /**
142
+ * Update message received from server
143
+ */
144
+ interface UpdateMessage {
145
+ type: "update";
146
+ table: string;
147
+ row_id: number;
148
+ data: any;
149
+ }
150
+ /**
151
+ * Status message received from server
152
+ */
153
+ interface StatusMessage {
154
+ status: "subscribed" | "unsubscribed" | "error";
155
+ table?: string;
156
+ row_id?: number;
157
+ error?: string;
158
+ }
159
+ /**
160
+ * Universal WebSocket client for real-time database events
161
+ *
162
+ * Connects to the database events WebSocket endpoint and manages subscriptions
163
+ * to table changes with automatic RLS authentication and reconnection.
164
+ *
165
+ * @example
166
+ * Basic usage:
167
+ * ```typescript
168
+ * const client = new EventsClient(
169
+ * 'ws://localhost:8080/api/v1/events/ws',
170
+ * 'your-jwt-token'
171
+ * );
172
+ *
173
+ * client.subscribe('tasks', {
174
+ * onChange: (data) => {
175
+ * console.log('Task updated:', data);
176
+ * }
177
+ * });
178
+ * ```
179
+ *
180
+ * @example
181
+ * Subscribe to specific row:
182
+ * ```typescript
183
+ * client.subscribe('users', {
184
+ * rowId: 123,
185
+ * onChange: (user) => {
186
+ * console.log('User 123 updated:', user);
187
+ * }
188
+ * });
189
+ * ```
190
+ *
191
+ * @example
192
+ * Subscribe to specific columns:
193
+ * ```typescript
194
+ * client.subscribe('posts', {
195
+ * rowId: 456,
196
+ * columns: ['title', 'content', 'status'],
197
+ * onChange: (post) => {
198
+ * console.log('Post columns updated:', post);
199
+ * }
200
+ * });
201
+ * ```
202
+ */
203
+ declare class EventsClient {
204
+ private url;
205
+ private jwt;
206
+ private subscriptions;
207
+ private ws;
208
+ private reconnectDelay;
209
+ private listeners;
210
+ private shouldReconnect;
211
+ /**
212
+ * Creates a new EventsClient instance
213
+ *
214
+ * @param url - WebSocket endpoint URL (e.g., 'ws://localhost:8080/api/v1/events/ws')
215
+ * @param jwt - JWT authentication token for RLS checks
216
+ */
217
+ constructor(url: string, jwt: string);
218
+ /**
219
+ * Establishes WebSocket connection with automatic reconnection
220
+ * @private
221
+ */
222
+ private connect;
223
+ /**
224
+ * Subscribe to database changes for a table
225
+ *
226
+ * @param table - Table name to subscribe to
227
+ * @param options - Subscription options (rowId, columns, onChange callback)
228
+ *
229
+ * @example
230
+ * Subscribe to entire table:
231
+ * ```typescript
232
+ * client.subscribe('tasks', {
233
+ * onChange: (task) => console.log('Task changed:', task)
234
+ * });
235
+ * ```
236
+ *
237
+ * @example
238
+ * Subscribe to specific row:
239
+ * ```typescript
240
+ * client.subscribe('users', {
241
+ * rowId: 123,
242
+ * onChange: (user) => console.log('User 123 changed:', user)
243
+ * });
244
+ * ```
245
+ */
246
+ subscribe(table: string, options?: SubscriptionOptions): void;
247
+ /**
248
+ * Unsubscribe from database changes
249
+ *
250
+ * @param table - Table name to unsubscribe from
251
+ * @param rowId - Optional row ID (if subscribing to specific row)
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * client.unsubscribe('tasks');
256
+ * client.unsubscribe('users', 123);
257
+ * ```
258
+ */
259
+ unsubscribe(table: string, rowId?: string): void;
260
+ /**
261
+ * Send message to WebSocket server
262
+ * @private
263
+ */
264
+ private send;
265
+ /**
266
+ * Handle incoming WebSocket messages
267
+ * @private
268
+ */
269
+ private handleMessage;
270
+ /**
271
+ * Update JWT token for authentication
272
+ *
273
+ * @param jwt - New JWT token
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * client.updateJWT(newToken);
278
+ * ```
279
+ */
280
+ updateJWT(jwt: string): void;
281
+ /**
282
+ * Close WebSocket connection and prevent reconnection
283
+ *
284
+ * @example
285
+ * ```typescript
286
+ * client.close();
287
+ * ```
288
+ */
289
+ close(): void;
290
+ /**
291
+ * Check if WebSocket is currently connected
292
+ *
293
+ * @returns true if connected, false otherwise
294
+ */
295
+ isConnected(): boolean;
296
+ }
297
+
298
+ export { EventsClient, type StatusMessage, type Subscription, type SubscriptionMessage, type SubscriptionOptions, type UpdateMessage, createClient };
@@ -102,4 +102,197 @@ import { PostgrestClient } from '@supabase/postgrest-js';
102
102
  */
103
103
  declare const createClient: <T = any>(url: string, anonKey: string, getCookie: (cookie: string) => string) => PostgrestClient<T>;
104
104
 
105
- export { createClient };
105
+ /**
106
+ * Real-time database events client for WebSocket subscriptions
107
+ *
108
+ * This module provides a universal WebSocket client for subscribing to real-time
109
+ * database changes with Row-Level Security (RLS) authentication. Works in both
110
+ * browser and Node.js environments.
111
+ *
112
+ * @module Database Events
113
+ */
114
+ /**
115
+ * Subscription options for database events
116
+ */
117
+ interface SubscriptionOptions {
118
+ /** Specific row ID to subscribe to (optional) */
119
+ rowId?: string;
120
+ /** Specific columns to filter updates (optional) */
121
+ columns?: string[];
122
+ /** Callback function triggered on data updates */
123
+ onChange?: (data: any, message: UpdateMessage) => void;
124
+ }
125
+ /**
126
+ * Subscription request sent to the server
127
+ */
128
+ interface Subscription {
129
+ table: string;
130
+ row_id?: string;
131
+ columns?: string[];
132
+ jwt: string;
133
+ }
134
+ /**
135
+ * Message sent from client to server
136
+ */
137
+ interface SubscriptionMessage {
138
+ action: "subscribe" | "unsubscribe";
139
+ subscription: Subscription;
140
+ }
141
+ /**
142
+ * Update message received from server
143
+ */
144
+ interface UpdateMessage {
145
+ type: "update";
146
+ table: string;
147
+ row_id: number;
148
+ data: any;
149
+ }
150
+ /**
151
+ * Status message received from server
152
+ */
153
+ interface StatusMessage {
154
+ status: "subscribed" | "unsubscribed" | "error";
155
+ table?: string;
156
+ row_id?: number;
157
+ error?: string;
158
+ }
159
+ /**
160
+ * Universal WebSocket client for real-time database events
161
+ *
162
+ * Connects to the database events WebSocket endpoint and manages subscriptions
163
+ * to table changes with automatic RLS authentication and reconnection.
164
+ *
165
+ * @example
166
+ * Basic usage:
167
+ * ```typescript
168
+ * const client = new EventsClient(
169
+ * 'ws://localhost:8080/api/v1/events/ws',
170
+ * 'your-jwt-token'
171
+ * );
172
+ *
173
+ * client.subscribe('tasks', {
174
+ * onChange: (data) => {
175
+ * console.log('Task updated:', data);
176
+ * }
177
+ * });
178
+ * ```
179
+ *
180
+ * @example
181
+ * Subscribe to specific row:
182
+ * ```typescript
183
+ * client.subscribe('users', {
184
+ * rowId: 123,
185
+ * onChange: (user) => {
186
+ * console.log('User 123 updated:', user);
187
+ * }
188
+ * });
189
+ * ```
190
+ *
191
+ * @example
192
+ * Subscribe to specific columns:
193
+ * ```typescript
194
+ * client.subscribe('posts', {
195
+ * rowId: 456,
196
+ * columns: ['title', 'content', 'status'],
197
+ * onChange: (post) => {
198
+ * console.log('Post columns updated:', post);
199
+ * }
200
+ * });
201
+ * ```
202
+ */
203
+ declare class EventsClient {
204
+ private url;
205
+ private jwt;
206
+ private subscriptions;
207
+ private ws;
208
+ private reconnectDelay;
209
+ private listeners;
210
+ private shouldReconnect;
211
+ /**
212
+ * Creates a new EventsClient instance
213
+ *
214
+ * @param url - WebSocket endpoint URL (e.g., 'ws://localhost:8080/api/v1/events/ws')
215
+ * @param jwt - JWT authentication token for RLS checks
216
+ */
217
+ constructor(url: string, jwt: string);
218
+ /**
219
+ * Establishes WebSocket connection with automatic reconnection
220
+ * @private
221
+ */
222
+ private connect;
223
+ /**
224
+ * Subscribe to database changes for a table
225
+ *
226
+ * @param table - Table name to subscribe to
227
+ * @param options - Subscription options (rowId, columns, onChange callback)
228
+ *
229
+ * @example
230
+ * Subscribe to entire table:
231
+ * ```typescript
232
+ * client.subscribe('tasks', {
233
+ * onChange: (task) => console.log('Task changed:', task)
234
+ * });
235
+ * ```
236
+ *
237
+ * @example
238
+ * Subscribe to specific row:
239
+ * ```typescript
240
+ * client.subscribe('users', {
241
+ * rowId: 123,
242
+ * onChange: (user) => console.log('User 123 changed:', user)
243
+ * });
244
+ * ```
245
+ */
246
+ subscribe(table: string, options?: SubscriptionOptions): void;
247
+ /**
248
+ * Unsubscribe from database changes
249
+ *
250
+ * @param table - Table name to unsubscribe from
251
+ * @param rowId - Optional row ID (if subscribing to specific row)
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * client.unsubscribe('tasks');
256
+ * client.unsubscribe('users', 123);
257
+ * ```
258
+ */
259
+ unsubscribe(table: string, rowId?: string): void;
260
+ /**
261
+ * Send message to WebSocket server
262
+ * @private
263
+ */
264
+ private send;
265
+ /**
266
+ * Handle incoming WebSocket messages
267
+ * @private
268
+ */
269
+ private handleMessage;
270
+ /**
271
+ * Update JWT token for authentication
272
+ *
273
+ * @param jwt - New JWT token
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * client.updateJWT(newToken);
278
+ * ```
279
+ */
280
+ updateJWT(jwt: string): void;
281
+ /**
282
+ * Close WebSocket connection and prevent reconnection
283
+ *
284
+ * @example
285
+ * ```typescript
286
+ * client.close();
287
+ * ```
288
+ */
289
+ close(): void;
290
+ /**
291
+ * Check if WebSocket is currently connected
292
+ *
293
+ * @returns true if connected, false otherwise
294
+ */
295
+ isConnected(): boolean;
296
+ }
297
+
298
+ export { EventsClient, type StatusMessage, type Subscription, type SubscriptionMessage, type SubscriptionOptions, type UpdateMessage, createClient };
@@ -8,6 +8,192 @@ var createClient = (url, anonKey, getCookie) => {
8
8
  }
9
9
  });
10
10
  };
11
+
12
+ // src/database/events.ts
13
+ var WS = typeof globalThis !== "undefined" && globalThis.WebSocket ? globalThis.WebSocket : null;
14
+ var EventsClient = class {
15
+ url;
16
+ jwt;
17
+ subscriptions = [];
18
+ ws = null;
19
+ reconnectDelay = 1e3;
20
+ listeners = /* @__PURE__ */ new Map();
21
+ shouldReconnect = true;
22
+ /**
23
+ * Creates a new EventsClient instance
24
+ *
25
+ * @param url - WebSocket endpoint URL (e.g., 'ws://localhost:8080/api/v1/events/ws')
26
+ * @param jwt - JWT authentication token for RLS checks
27
+ */
28
+ constructor(url, jwt) {
29
+ if (!WS) {
30
+ throw new Error(
31
+ 'WebSocket is not available in this environment. Install "ws" package for Node.js.'
32
+ );
33
+ }
34
+ this.url = url;
35
+ this.jwt = jwt;
36
+ this.connect();
37
+ }
38
+ /**
39
+ * Establishes WebSocket connection with automatic reconnection
40
+ * @private
41
+ */
42
+ connect() {
43
+ if (!WS) return;
44
+ this.ws = new WS(this.url);
45
+ this.ws.onopen = () => {
46
+ this.reconnectDelay = 1e3;
47
+ this.subscriptions.forEach((sub) => this.send(sub));
48
+ };
49
+ this.ws.onmessage = (event) => {
50
+ const data = typeof event.data === "string" ? event.data : event.data.toString();
51
+ const msg = JSON.parse(data);
52
+ this.handleMessage(msg);
53
+ };
54
+ this.ws.onerror = (error) => {
55
+ console.error("WebSocket error:", error);
56
+ };
57
+ this.ws.onclose = () => {
58
+ if (this.shouldReconnect) {
59
+ setTimeout(() => this.connect(), this.reconnectDelay);
60
+ this.reconnectDelay = Math.min(this.reconnectDelay * 2, 3e4);
61
+ }
62
+ };
63
+ }
64
+ /**
65
+ * Subscribe to database changes for a table
66
+ *
67
+ * @param table - Table name to subscribe to
68
+ * @param options - Subscription options (rowId, columns, onChange callback)
69
+ *
70
+ * @example
71
+ * Subscribe to entire table:
72
+ * ```typescript
73
+ * client.subscribe('tasks', {
74
+ * onChange: (task) => console.log('Task changed:', task)
75
+ * });
76
+ * ```
77
+ *
78
+ * @example
79
+ * Subscribe to specific row:
80
+ * ```typescript
81
+ * client.subscribe('users', {
82
+ * rowId: 123,
83
+ * onChange: (user) => console.log('User 123 changed:', user)
84
+ * });
85
+ * ```
86
+ */
87
+ subscribe(table, options = {}) {
88
+ const { rowId, columns, onChange } = options;
89
+ const sub = {
90
+ action: "subscribe",
91
+ subscription: {
92
+ table,
93
+ ...rowId !== void 0 && { row_id: rowId },
94
+ ...columns && { columns },
95
+ jwt: this.jwt
96
+ }
97
+ };
98
+ this.subscriptions.push(sub);
99
+ if (onChange) {
100
+ const key = `${table}:${rowId ?? "*"}`;
101
+ this.listeners.set(key, onChange);
102
+ }
103
+ this.send(sub);
104
+ }
105
+ /**
106
+ * Unsubscribe from database changes
107
+ *
108
+ * @param table - Table name to unsubscribe from
109
+ * @param rowId - Optional row ID (if subscribing to specific row)
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * client.unsubscribe('tasks');
114
+ * client.unsubscribe('users', 123);
115
+ * ```
116
+ */
117
+ unsubscribe(table, rowId) {
118
+ const sub = {
119
+ action: "unsubscribe",
120
+ subscription: {
121
+ table,
122
+ ...rowId !== void 0 && { row_id: rowId },
123
+ jwt: this.jwt
124
+ }
125
+ };
126
+ this.subscriptions = this.subscriptions.filter(
127
+ (s) => !(s.subscription.table === table && s.subscription.row_id === rowId)
128
+ );
129
+ const key = `${table}:${rowId ?? "*"}`;
130
+ this.listeners.delete(key);
131
+ this.send(sub);
132
+ }
133
+ /**
134
+ * Send message to WebSocket server
135
+ * @private
136
+ */
137
+ send(data) {
138
+ if (!WS) return;
139
+ if (this.ws?.readyState === WS.OPEN || this.ws?.readyState === 1) {
140
+ this.ws.send(JSON.stringify(data));
141
+ }
142
+ }
143
+ /**
144
+ * Handle incoming WebSocket messages
145
+ * @private
146
+ */
147
+ handleMessage(msg) {
148
+ if ("type" in msg && msg.type === "update") {
149
+ const key = `${msg.table}:${msg.row_id}`;
150
+ const wildcardKey = `${msg.table}:*`;
151
+ const listener = this.listeners.get(key) || this.listeners.get(wildcardKey);
152
+ if (listener) {
153
+ listener(msg.data, msg);
154
+ }
155
+ }
156
+ }
157
+ /**
158
+ * Update JWT token for authentication
159
+ *
160
+ * @param jwt - New JWT token
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * client.updateJWT(newToken);
165
+ * ```
166
+ */
167
+ updateJWT(jwt) {
168
+ this.jwt = jwt;
169
+ this.subscriptions = this.subscriptions.map((sub) => ({
170
+ ...sub,
171
+ subscription: { ...sub.subscription, jwt }
172
+ }));
173
+ }
174
+ /**
175
+ * Close WebSocket connection and prevent reconnection
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * client.close();
180
+ * ```
181
+ */
182
+ close() {
183
+ this.shouldReconnect = false;
184
+ this.ws?.close();
185
+ }
186
+ /**
187
+ * Check if WebSocket is currently connected
188
+ *
189
+ * @returns true if connected, false otherwise
190
+ */
191
+ isConnected() {
192
+ if (!WS) return false;
193
+ return this.ws?.readyState === WS.OPEN || this.ws?.readyState === 1;
194
+ }
195
+ };
11
196
  export {
197
+ EventsClient,
12
198
  createClient
13
199
  };