superso-js-sdk 1.0.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.
@@ -0,0 +1,65 @@
1
+ import { SupersoClient } from "../core/client";
2
+ export interface RealtimeEvent {
3
+ id?: string;
4
+ project_id?: string;
5
+ channel_id?: string;
6
+ channel?: string;
7
+ auth_user_id?: string;
8
+ auth_method?: string;
9
+ event_name?: string;
10
+ event?: string;
11
+ payload?: any;
12
+ data?: any;
13
+ status?: string;
14
+ timestamp?: any;
15
+ created_at?: string;
16
+ }
17
+ export interface RealtimeOptions {
18
+ token?: string;
19
+ reconnect?: boolean;
20
+ reconnectInterval?: number;
21
+ maxRetries?: number;
22
+ heartbeat?: boolean;
23
+ heartbeatInterval?: number;
24
+ }
25
+ export declare class SupersoRealtime {
26
+ private client;
27
+ private socket;
28
+ private channel;
29
+ private handlers;
30
+ private reconnect;
31
+ private reconnectInterval;
32
+ private maxRetries;
33
+ private retryCount;
34
+ private token?;
35
+ private heartbeat;
36
+ private heartbeatInterval;
37
+ private heartbeatTimer;
38
+ constructor(client: SupersoClient);
39
+ connect(channel: string, options?: RealtimeOptions): void;
40
+ private startHeartbeat;
41
+ private stopHeartbeat;
42
+ private emit;
43
+ on(event: string, callback: Function): void;
44
+ off(event: string, callback?: Function): void;
45
+ send(event: string, data?: any): void;
46
+ ping(): void;
47
+ refreshToken(refreshToken: string): void;
48
+ startTyping(): void;
49
+ stopTyping(): void;
50
+ disconnect(): void;
51
+ getSocket(): WebSocket | null;
52
+ getChannel(): string;
53
+ isConnected(): boolean;
54
+ }
55
+ export declare function subscribeCollection(realtime: SupersoRealtime, collection: string, options?: RealtimeOptions): void;
56
+ export declare function liveQuery(realtime: SupersoRealtime, callback: Function): void;
57
+ export declare function subscribeNotifications(realtime: SupersoRealtime, callback?: Function): void;
58
+ export declare function subscribePresence(realtime: SupersoRealtime, callback: Function): void;
59
+ export declare function subscribeTyping(realtime: SupersoRealtime, callback: Function): void;
60
+ export declare function subscribeVerificationRequired(realtime: SupersoRealtime, callback: Function): void;
61
+ export declare function publishEvent(client: SupersoClient, channel: string, event_name: string, payload?: any): Promise<any>;
62
+ export declare function listEvents(client: SupersoClient, channel: string): Promise<any>;
63
+ export declare function replayEvents(client: SupersoClient, channel: string, sequence: number): Promise<any>;
64
+ export declare function replayEventsSince(client: SupersoClient, channel: string, timestamp: string): Promise<any>;
65
+ export declare function getLatestSequence(client: SupersoClient, channel: string): Promise<any>;
@@ -0,0 +1,365 @@
1
+ // =======================================
2
+ // REALTIME CLASS
3
+ // =======================================
4
+ export class SupersoRealtime {
5
+ constructor(client) {
6
+ this.socket = null;
7
+ this.channel = "";
8
+ this.handlers = {};
9
+ this.reconnect = true;
10
+ this.reconnectInterval = 3000;
11
+ this.maxRetries = 10;
12
+ this.retryCount = 0;
13
+ this.heartbeat = true;
14
+ this.heartbeatInterval = 30000;
15
+ this.heartbeatTimer = null;
16
+ this.client = client;
17
+ }
18
+ // =======================================
19
+ // CONNECT
20
+ // =======================================
21
+ connect(channel, options) {
22
+ var _a, _b, _c, _d, _e;
23
+ if (this.socket &&
24
+ (this.socket.readyState ===
25
+ WebSocket.OPEN ||
26
+ this.socket.readyState ===
27
+ WebSocket.CONNECTING) &&
28
+ this.channel ===
29
+ channel) {
30
+ return;
31
+ }
32
+ this.channel =
33
+ channel;
34
+ this.token =
35
+ options === null || options === void 0 ? void 0 : options.token;
36
+ this.reconnect =
37
+ (_a = options === null || options === void 0 ? void 0 : options.reconnect) !== null && _a !== void 0 ? _a : true;
38
+ this.reconnectInterval =
39
+ (_b = options === null || options === void 0 ? void 0 : options.reconnectInterval) !== null && _b !== void 0 ? _b : 3000;
40
+ this.maxRetries =
41
+ (_c = options === null || options === void 0 ? void 0 : options.maxRetries) !== null && _c !== void 0 ? _c : 10;
42
+ this.heartbeat =
43
+ (_d = options === null || options === void 0 ? void 0 : options.heartbeat) !== null && _d !== void 0 ? _d : true;
44
+ this.heartbeatInterval =
45
+ (_e = options === null || options === void 0 ? void 0 : options.heartbeatInterval) !== null && _e !== void 0 ? _e : 30000;
46
+ const params = new URLSearchParams({
47
+ key: this.client.apiKey,
48
+ });
49
+ if (this.token) {
50
+ params.append("token", this.token);
51
+ }
52
+ const protocol = this.client.baseUrl.startsWith("https")
53
+ ? "wss"
54
+ : "ws";
55
+ const cleanBase = this.client.baseUrl
56
+ .replace("https://", "")
57
+ .replace("http://", "");
58
+ const wsUrl = `${protocol}://${cleanBase}/ws/project/${this.client.projectId}/channel/${channel}?${params}`;
59
+ this.socket =
60
+ new WebSocket(wsUrl);
61
+ // =======================================
62
+ // OPEN
63
+ // =======================================
64
+ this.socket.onopen =
65
+ () => {
66
+ this.retryCount = 0;
67
+ console.log(`Realtime connected: ${channel}`);
68
+ this.emit("connected", {
69
+ channel,
70
+ });
71
+ if (this.heartbeat) {
72
+ this.startHeartbeat();
73
+ }
74
+ };
75
+ // =======================================
76
+ // MESSAGE
77
+ // =======================================
78
+ this.socket.onmessage =
79
+ (event) => {
80
+ try {
81
+ const parsed = JSON.parse(event.data);
82
+ const eventName = parsed.event_name ||
83
+ parsed.event ||
84
+ "message";
85
+ // internal pong
86
+ if (eventName ===
87
+ "pong") {
88
+ return;
89
+ }
90
+ // emit event
91
+ this.emit(eventName, parsed);
92
+ // wildcard
93
+ this.emit("*", parsed);
94
+ }
95
+ catch (error) {
96
+ console.error("Realtime parse error", error);
97
+ }
98
+ };
99
+ // =======================================
100
+ // CLOSE
101
+ // =======================================
102
+ this.socket.onclose =
103
+ () => {
104
+ console.log("Realtime disconnected");
105
+ this.stopHeartbeat();
106
+ this.emit("disconnected", {
107
+ channel: this.channel,
108
+ });
109
+ if (this.reconnect &&
110
+ this.retryCount <
111
+ this.maxRetries) {
112
+ this.retryCount += 1;
113
+ setTimeout(() => {
114
+ this.connect(this.channel, {
115
+ token: this.token,
116
+ reconnect: this.reconnect,
117
+ reconnectInterval: this.reconnectInterval,
118
+ maxRetries: this.maxRetries,
119
+ heartbeat: this.heartbeat,
120
+ heartbeatInterval: this.heartbeatInterval,
121
+ });
122
+ }, this.reconnectInterval);
123
+ }
124
+ };
125
+ // =======================================
126
+ // ERROR
127
+ // =======================================
128
+ this.socket.onerror =
129
+ (error) => {
130
+ console.error("Realtime error", error);
131
+ this.emit("error", error);
132
+ };
133
+ }
134
+ // =======================================
135
+ // HEARTBEAT
136
+ // =======================================
137
+ startHeartbeat() {
138
+ this.stopHeartbeat();
139
+ this.heartbeatTimer =
140
+ setInterval(() => {
141
+ this.ping();
142
+ }, this.heartbeatInterval);
143
+ }
144
+ stopHeartbeat() {
145
+ if (this.heartbeatTimer) {
146
+ clearInterval(this.heartbeatTimer);
147
+ this.heartbeatTimer =
148
+ null;
149
+ }
150
+ }
151
+ // =======================================
152
+ // EMIT
153
+ // =======================================
154
+ emit(event, payload) {
155
+ if (!this.handlers[event]) {
156
+ return;
157
+ }
158
+ this.handlers[event]
159
+ .forEach((callback) => {
160
+ callback(payload);
161
+ });
162
+ }
163
+ // =======================================
164
+ // ON
165
+ // =======================================
166
+ on(event, callback) {
167
+ if (!this.handlers[event]) {
168
+ this.handlers[event] =
169
+ [];
170
+ }
171
+ this.handlers[event]
172
+ .push(callback);
173
+ }
174
+ // =======================================
175
+ // OFF
176
+ // =======================================
177
+ off(event, callback) {
178
+ if (!this.handlers[event]) {
179
+ return;
180
+ }
181
+ if (!callback) {
182
+ delete this.handlers[event];
183
+ return;
184
+ }
185
+ this.handlers[event] =
186
+ this.handlers[event].filter((cb) => cb !== callback);
187
+ }
188
+ // =======================================
189
+ // SEND
190
+ // =======================================
191
+ send(event, data) {
192
+ if (!this.socket ||
193
+ this.socket.readyState !==
194
+ WebSocket.OPEN) {
195
+ return;
196
+ }
197
+ this.socket.send(JSON.stringify({
198
+ event,
199
+ data,
200
+ }));
201
+ }
202
+ // =======================================
203
+ // PING
204
+ // =======================================
205
+ ping() {
206
+ this.send("ping");
207
+ }
208
+ // =======================================
209
+ // TOKEN REFRESH
210
+ // =======================================
211
+ refreshToken(refreshToken) {
212
+ this.send("token_refresh", {
213
+ refresh_token: refreshToken,
214
+ });
215
+ }
216
+ // =======================================
217
+ // TYPING
218
+ // =======================================
219
+ startTyping() {
220
+ this.send("typing", {
221
+ is_typing: true,
222
+ });
223
+ }
224
+ stopTyping() {
225
+ this.send("typing", {
226
+ is_typing: false,
227
+ });
228
+ }
229
+ // =======================================
230
+ // DISCONNECT
231
+ // =======================================
232
+ disconnect() {
233
+ var _a;
234
+ this.reconnect =
235
+ false;
236
+ this.stopHeartbeat();
237
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.close();
238
+ this.socket = null;
239
+ }
240
+ // =======================================
241
+ // GETTERS
242
+ // =======================================
243
+ getSocket() {
244
+ return this.socket;
245
+ }
246
+ getChannel() {
247
+ return this.channel;
248
+ }
249
+ isConnected() {
250
+ var _a;
251
+ return (((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) ===
252
+ WebSocket.OPEN);
253
+ }
254
+ }
255
+ // =======================================
256
+ // COLLECTION REALTIME
257
+ // =======================================
258
+ export function subscribeCollection(realtime, collection, options) {
259
+ realtime.connect(`${collection}-realtime`, options);
260
+ }
261
+ // =======================================
262
+ // DATABASE LIVE QUERY
263
+ // =======================================
264
+ export function liveQuery(realtime, callback) {
265
+ realtime.on("document_created", callback);
266
+ realtime.on("document_updated", callback);
267
+ realtime.on("document_deleted", callback);
268
+ }
269
+ // =======================================
270
+ // NOTIFICATIONS
271
+ // =======================================
272
+ export function subscribeNotifications(realtime, callback) {
273
+ realtime.on("notification", callback ||
274
+ ((event) => {
275
+ console.log("Notification:", event);
276
+ }));
277
+ realtime.on("notification.received", callback ||
278
+ ((event) => {
279
+ console.log("Notification:", event);
280
+ }));
281
+ }
282
+ // =======================================
283
+ // PRESENCE
284
+ // =======================================
285
+ export function subscribePresence(realtime, callback) {
286
+ realtime.on("user_presence", callback);
287
+ }
288
+ // =======================================
289
+ // TYPING
290
+ // =======================================
291
+ export function subscribeTyping(realtime, callback) {
292
+ realtime.on("typing", callback);
293
+ }
294
+ // =======================================
295
+ // VERIFICATION
296
+ // =======================================
297
+ export function subscribeVerificationRequired(realtime, callback) {
298
+ realtime.on("verification_required", callback);
299
+ }
300
+ // =======================================
301
+ // REST EVENT PUBLISH
302
+ // =======================================
303
+ export async function publishEvent(client, channel, event_name, payload) {
304
+ const response = await fetch(`${client.baseUrl}/api/project/${client.projectId}/realtime/channels/${channel}/events`, {
305
+ method: "POST",
306
+ headers: {
307
+ "Content-Type": "application/json",
308
+ "X-Superso-Project-Key": client.apiKey,
309
+ },
310
+ body: JSON.stringify({
311
+ event_name,
312
+ payload,
313
+ }),
314
+ });
315
+ const data = await response.json();
316
+ if (!response.ok) {
317
+ throw new Error((data === null || data === void 0 ? void 0 : data.message) ||
318
+ "Publish event failed");
319
+ }
320
+ return data;
321
+ }
322
+ // =======================================
323
+ // LIST EVENTS
324
+ // =======================================
325
+ export async function listEvents(client, channel) {
326
+ const response = await fetch(`${client.baseUrl}/api/project/${client.projectId}/realtime/channels/${channel}/events`, {
327
+ headers: {
328
+ "X-Superso-Project-Key": client.apiKey,
329
+ },
330
+ });
331
+ return await response.json();
332
+ }
333
+ // =======================================
334
+ // REPLAY EVENTS
335
+ // =======================================
336
+ export async function replayEvents(client, channel, sequence) {
337
+ const response = await fetch(`${client.baseUrl}/api/project/${client.projectId}/realtime/channels/${channel}/events/replay?sequence=${sequence}`, {
338
+ headers: {
339
+ "X-Superso-Project-Key": client.apiKey,
340
+ },
341
+ });
342
+ return await response.json();
343
+ }
344
+ // =======================================
345
+ // REPLAY SINCE
346
+ // =======================================
347
+ export async function replayEventsSince(client, channel, timestamp) {
348
+ const response = await fetch(`${client.baseUrl}/api/project/${client.projectId}/realtime/channels/${channel}/events/replay/since?timestamp=${timestamp}`, {
349
+ headers: {
350
+ "X-Superso-Project-Key": client.apiKey,
351
+ },
352
+ });
353
+ return await response.json();
354
+ }
355
+ // =======================================
356
+ // LATEST SEQUENCE
357
+ // =======================================
358
+ export async function getLatestSequence(client, channel) {
359
+ const response = await fetch(`${client.baseUrl}/api/project/${client.projectId}/realtime/channels/${channel}/events/latest-seq`, {
360
+ headers: {
361
+ "X-Superso-Project-Key": client.apiKey,
362
+ },
363
+ });
364
+ return await response.json();
365
+ }
@@ -0,0 +1,69 @@
1
+ import { SupersoClient } from "../core/client";
2
+ export interface UploadOptions {
3
+ path?: string;
4
+ alt_text?: string;
5
+ caption?: string;
6
+ token?: string;
7
+ onProgress?: (percent: number) => void;
8
+ }
9
+ export interface StorageAsset {
10
+ id: string;
11
+ owner_type?: string;
12
+ owner_id?: string;
13
+ project_id?: string;
14
+ url: string;
15
+ secure_url: string;
16
+ public_id: string;
17
+ file_name: string;
18
+ mime_type: string;
19
+ size_bytes: number;
20
+ width?: number;
21
+ height?: number;
22
+ provider?: string;
23
+ folder?: string;
24
+ alt_text?: string;
25
+ caption?: string;
26
+ metadata?: any;
27
+ created_at?: string;
28
+ updated_at?: string;
29
+ }
30
+ export interface StorageUsage {
31
+ used_bytes: number;
32
+ used_mb: number;
33
+ limit_mb: number;
34
+ limit_bytes: number;
35
+ percent_used: number;
36
+ feature_on: boolean;
37
+ configured: boolean;
38
+ warning_level: "ok" | "soft" | "strong" | "urgent" | "blocked";
39
+ }
40
+ export declare function uploadFile(client: SupersoClient, file: File, options?: UploadOptions): Promise<unknown>;
41
+ export declare function uploadFiles(client: SupersoClient, files: File[], options?: UploadOptions): Promise<unknown[]>;
42
+ export declare function listAssets(client: SupersoClient, token?: string): Promise<any>;
43
+ export declare function listFiles(client: SupersoClient, token?: string): Promise<any>;
44
+ export declare function getAsset(client: SupersoClient, assetId: string, token?: string): Promise<any>;
45
+ export declare function deleteAsset(client: SupersoClient, assetId: string, token?: string): Promise<any>;
46
+ export declare function deleteFile(client: SupersoClient, assetId: string, token?: string): Promise<any>;
47
+ export declare function removeFile(client: SupersoClient, assetId: string, token?: string): Promise<any>;
48
+ export declare function getStorageUsage(client: SupersoClient, token?: string): Promise<StorageUsage>;
49
+ export declare function getFileExtension(fileName: string): string | undefined;
50
+ export declare function formatBytes(bytes: number, decimals?: number): string;
51
+ export declare function isImage(mimeType: string): boolean;
52
+ export declare function isVideo(mimeType: string): boolean;
53
+ export declare function isAudio(mimeType: string): boolean;
54
+ export declare function isPDF(mimeType: string): mimeType is "application/pdf";
55
+ export declare function isDocument(mimeType: string): boolean;
56
+ export declare function validateFile(file: File): boolean;
57
+ export declare function optimizeImage(url: string): string;
58
+ export declare function convertToWebP(url: string): string;
59
+ export declare function resizeImage(url: string, width: number, height?: number): string;
60
+ export declare function thumbnail(url: string, size?: number): string;
61
+ export declare function cropImage(url: string, width: number, height: number): string;
62
+ export declare function blurImage(url: string): string;
63
+ export declare function grayscaleImage(url: string): string;
64
+ export declare function autoQuality(url: string): string;
65
+ export declare function autoFormat(url: string): string;
66
+ export declare function getSecureUrl(asset: StorageAsset): string;
67
+ export declare function getPublicUrl(asset: StorageAsset): string;
68
+ export declare function buildAuthenticatedUrl(cloudName: string, publicId: string): void;
69
+ export declare function buildPrivateUrl(cloudName: string, publicId: string): void;