@omnibase/core-js 0.5.10 → 0.7.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.
@@ -1,13 +1,226 @@
1
1
  // src/database/client.ts
2
2
  import { PostgrestClient } from "@supabase/postgrest-js";
3
3
  var createClient = (url, anonKey, getCookie) => {
4
- const jwt = getCookie("postgrest_jwt") || anonKey;
4
+ const jwt = getCookie("omnibase_postgrest_jwt") || anonKey;
5
5
  return new PostgrestClient(url, {
6
6
  headers: {
7
7
  Authorization: `Bearer ${jwt}`
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
+ console.log("\u2705 Connected to database events");
47
+ this.reconnectDelay = 1e3;
48
+ this.subscriptions.forEach((sub) => this.send(sub));
49
+ };
50
+ this.ws.onmessage = (event) => {
51
+ const data = typeof event.data === "string" ? event.data : event.data.toString();
52
+ const msg = JSON.parse(data);
53
+ this.handleMessage(msg);
54
+ };
55
+ this.ws.onerror = (error) => {
56
+ console.error("\u274C WebSocket error:", error);
57
+ };
58
+ this.ws.onclose = () => {
59
+ if (this.shouldReconnect) {
60
+ console.log(
61
+ `\u26A0\uFE0F Disconnected, reconnecting in ${this.reconnectDelay}ms`
62
+ );
63
+ setTimeout(() => this.connect(), this.reconnectDelay);
64
+ this.reconnectDelay = Math.min(this.reconnectDelay * 2, 3e4);
65
+ } else {
66
+ console.log("Disconnected from database events");
67
+ }
68
+ };
69
+ }
70
+ /**
71
+ * Subscribe to database changes for a table
72
+ *
73
+ * @param table - Table name to subscribe to
74
+ * @param options - Subscription options (rowId, columns, onChange callback)
75
+ *
76
+ * @example
77
+ * Subscribe to entire table:
78
+ * ```typescript
79
+ * client.subscribe('tasks', {
80
+ * onChange: (task) => console.log('Task changed:', task)
81
+ * });
82
+ * ```
83
+ *
84
+ * @example
85
+ * Subscribe to specific row:
86
+ * ```typescript
87
+ * client.subscribe('users', {
88
+ * rowId: 123,
89
+ * onChange: (user) => console.log('User 123 changed:', user)
90
+ * });
91
+ * ```
92
+ */
93
+ subscribe(table, options = {}) {
94
+ const { rowId, columns, onChange } = options;
95
+ const sub = {
96
+ action: "subscribe",
97
+ subscription: {
98
+ table,
99
+ ...rowId !== void 0 && { row_id: rowId },
100
+ ...columns && { columns },
101
+ jwt: this.jwt
102
+ }
103
+ };
104
+ this.subscriptions.push(sub);
105
+ if (onChange) {
106
+ const key = `${table}:${rowId ?? "*"}`;
107
+ this.listeners.set(key, onChange);
108
+ }
109
+ this.send(sub);
110
+ }
111
+ /**
112
+ * Unsubscribe from database changes
113
+ *
114
+ * @param table - Table name to unsubscribe from
115
+ * @param rowId - Optional row ID (if subscribing to specific row)
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * client.unsubscribe('tasks');
120
+ * client.unsubscribe('users', 123);
121
+ * ```
122
+ */
123
+ unsubscribe(table, rowId) {
124
+ const sub = {
125
+ action: "unsubscribe",
126
+ subscription: {
127
+ table,
128
+ ...rowId !== void 0 && { row_id: rowId },
129
+ jwt: this.jwt
130
+ }
131
+ };
132
+ this.subscriptions = this.subscriptions.filter(
133
+ (s) => !(s.subscription.table === table && s.subscription.row_id === rowId)
134
+ );
135
+ const key = `${table}:${rowId ?? "*"}`;
136
+ this.listeners.delete(key);
137
+ this.send(sub);
138
+ }
139
+ /**
140
+ * Send message to WebSocket server
141
+ * @private
142
+ */
143
+ send(data) {
144
+ if (!WS) return;
145
+ if (this.ws?.readyState === WS.OPEN || this.ws?.readyState === 1) {
146
+ this.ws.send(JSON.stringify(data));
147
+ }
148
+ }
149
+ /**
150
+ * Handle incoming WebSocket messages
151
+ * @private
152
+ */
153
+ handleMessage(msg) {
154
+ if ("type" in msg && msg.type === "update") {
155
+ const key = `${msg.table}:${msg.row_id}`;
156
+ const wildcardKey = `${msg.table}:*`;
157
+ const listener = this.listeners.get(key) || this.listeners.get(wildcardKey);
158
+ if (listener) {
159
+ listener(msg.data, msg);
160
+ }
161
+ } else if ("status" in msg) {
162
+ if (msg.status === "subscribed") {
163
+ console.log(
164
+ "\u2705 Subscribed to",
165
+ msg.table,
166
+ msg.row_id ? `(row ${msg.row_id})` : "(all rows)"
167
+ );
168
+ } else if (msg.status === "unsubscribed") {
169
+ console.log(
170
+ "Unsubscribed from",
171
+ msg.table,
172
+ msg.row_id ? `(row ${msg.row_id})` : "(all rows)"
173
+ );
174
+ } else if (msg.status === "error") {
175
+ console.error(
176
+ "\u274C Subscription error:",
177
+ msg.error,
178
+ "for table:",
179
+ msg.table
180
+ );
181
+ }
182
+ }
183
+ }
184
+ /**
185
+ * Update JWT token for authentication
186
+ *
187
+ * @param jwt - New JWT token
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * client.updateJWT(newToken);
192
+ * ```
193
+ */
194
+ updateJWT(jwt) {
195
+ this.jwt = jwt;
196
+ this.subscriptions = this.subscriptions.map((sub) => ({
197
+ ...sub,
198
+ subscription: { ...sub.subscription, jwt }
199
+ }));
200
+ }
201
+ /**
202
+ * Close WebSocket connection and prevent reconnection
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * client.close();
207
+ * ```
208
+ */
209
+ close() {
210
+ this.shouldReconnect = false;
211
+ this.ws?.close();
212
+ }
213
+ /**
214
+ * Check if WebSocket is currently connected
215
+ *
216
+ * @returns true if connected, false otherwise
217
+ */
218
+ isConnected() {
219
+ if (!WS) return false;
220
+ return this.ws?.readyState === WS.OPEN || this.ws?.readyState === 1;
221
+ }
222
+ };
11
223
  export {
224
+ EventsClient,
12
225
  createClient
13
226
  };