@dcimorra/authhub-sdk 1.1.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.
package/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # authhub-sdk
2
+
3
+ Official TypeScript SDK for [Auth Hub](https://github.com/dcimorra/auth-hub) — self-hosted authentication, database, and storage as a service.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install authhub-sdk
9
+ ```
10
+
11
+ Or copy the `sdk/` directory into your project and import from it directly.
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { AuthHubClient } from "authhub-sdk";
17
+
18
+ const hub = new AuthHubClient({
19
+ baseUrl: "https://auth.example.com",
20
+ projectId: "your-project-uuid",
21
+ apiKey: "sk_your_api_key",
22
+ });
23
+ ```
24
+
25
+ ## Authentication
26
+
27
+ ```typescript
28
+ // Register
29
+ await hub.auth.register("user@example.com", "securePassword123");
30
+
31
+ // Login — tokens are stored automatically
32
+ const { user } = await hub.auth.login("user@example.com", "securePassword123");
33
+
34
+ // Get current user (auto-refreshes token if expired)
35
+ const me = await hub.auth.getUser();
36
+
37
+ // Change password
38
+ await hub.auth.changePassword("oldPassword", "newPassword");
39
+
40
+ // Password recovery flow
41
+ await hub.auth.recover("user@example.com");
42
+ // User receives email with token...
43
+ await hub.auth.resetPassword(tokenFromEmail, "newPassword");
44
+
45
+ // Logout — clears tokens locally and revokes on server
46
+ await hub.auth.logout();
47
+
48
+ // Check auth state
49
+ const isLoggedIn = await hub.auth.isAuthenticated();
50
+ ```
51
+
52
+ ### Token Management
53
+
54
+ Tokens are automatically stored and refreshed. You can customize the storage:
55
+
56
+ ```typescript
57
+ // Browser (default): localStorage
58
+ const hub = new AuthHubClient({ ..., tokenStore: "localStorage" });
59
+
60
+ // Node.js (default): in-memory
61
+ const hub = new AuthHubClient({ ..., tokenStore: "memory" });
62
+
63
+ // Custom store (e.g. React Native AsyncStorage)
64
+ const hub = new AuthHubClient({
65
+ ...,
66
+ tokenStore: {
67
+ get: (key) => AsyncStorage.getItem(key),
68
+ set: (key, value) => AsyncStorage.setItem(key, value),
69
+ remove: (key) => AsyncStorage.removeItem(key),
70
+ },
71
+ });
72
+
73
+ // Handle session expiry (refresh token expired/revoked)
74
+ const hub = new AuthHubClient({
75
+ ...,
76
+ onSessionExpired: () => {
77
+ window.location.href = "/login";
78
+ },
79
+ });
80
+ ```
81
+
82
+ ## Database
83
+
84
+ Full CRUD with advanced query operators.
85
+
86
+ ```typescript
87
+ // Insert
88
+ const { rows } = await hub.db.create({
89
+ table: "products",
90
+ data: { name: "Widget", price: 29.99, active: true },
91
+ });
92
+
93
+ // Query with operators
94
+ const { rows, count } = await hub.db.read({
95
+ table: "products",
96
+ select: ["id", "name", "price"],
97
+ where: {
98
+ price: { $gte: 10, $lte: 100 },
99
+ status: { $in: ["active", "sale"] },
100
+ deleted_at: { $is: null },
101
+ },
102
+ orderBy: [
103
+ { column: "price", order: "ASC" },
104
+ { column: "name", order: "DESC" },
105
+ ],
106
+ limit: 50,
107
+ offset: 0,
108
+ });
109
+
110
+ // Update
111
+ await hub.db.update({
112
+ table: "products",
113
+ data: { price: 24.99 },
114
+ where: { id: 1 },
115
+ });
116
+
117
+ // Delete
118
+ await hub.db.delete({
119
+ table: "products",
120
+ where: { active: false },
121
+ });
122
+
123
+ // Convenience methods
124
+ const product = await hub.db.findById("products", 1);
125
+ const user = await hub.db.findOne("users", { email: "alice@example.com" });
126
+ const total = await hub.db.count("products", { active: true });
127
+ ```
128
+
129
+ ### Query Operators
130
+
131
+ | Operator | SQL | Example |
132
+ |----------|-----|---------|
133
+ | `$eq` | `=` | `{ status: { $eq: "active" } }` |
134
+ | `$neq` | `!=` | `{ role: { $neq: "admin" } }` |
135
+ | `$gt` | `>` | `{ price: { $gt: 10 } }` |
136
+ | `$gte` | `>=` | `{ age: { $gte: 18 } }` |
137
+ | `$lt` | `<` | `{ stock: { $lt: 5 } }` |
138
+ | `$lte` | `<=` | `{ priority: { $lte: 3 } }` |
139
+ | `$in` | `IN (...)` | `{ status: { $in: ["a", "b"] } }` |
140
+ | `$nin` | `NOT IN (...)` | `{ id: { $nin: [1, 2, 3] } }` |
141
+ | `$like` | `LIKE` | `{ name: { $like: "%widget%" } }` |
142
+ | `$ilike` | `ILIKE` | `{ name: { $ilike: "%Widget%" } }` |
143
+ | `$is` | `IS` | `{ deleted_at: { $is: null } }` |
144
+ | `$not` | `IS NOT` | `{ email: { $not: null } }` |
145
+
146
+ ## Storage
147
+
148
+ File upload, download, and bucket management.
149
+
150
+ ```typescript
151
+ // Create a bucket
152
+ await hub.storage.createBucket({
153
+ name: "avatars",
154
+ isPublic: true,
155
+ maxFileSize: 5 * 1024 * 1024, // 5MB
156
+ });
157
+
158
+ // Upload a file (browser)
159
+ const fileInput = document.querySelector<HTMLInputElement>("#file");
160
+ await hub.storage.upload({
161
+ bucket: "avatars",
162
+ key: "users/user1.jpg",
163
+ file: fileInput.files[0],
164
+ });
165
+
166
+ // Upload from Node.js
167
+ import { readFileSync } from "fs";
168
+ await hub.storage.upload({
169
+ bucket: "avatars",
170
+ key: "users/user1.jpg",
171
+ file: readFileSync("photo.jpg"),
172
+ contentType: "image/jpeg",
173
+ });
174
+
175
+ // Download
176
+ const response = await hub.storage.download("avatars", "users/user1.jpg");
177
+ const blob = await response.blob(); // browser
178
+ // or
179
+ const buffer = await hub.storage.downloadBuffer("avatars", "users/user1.jpg");
180
+
181
+ // Public URL (for <img src=...> etc.)
182
+ const url = hub.storage.getPublicUrl("avatars", "users/user1.jpg");
183
+
184
+ // List files
185
+ const { objects, count } = await hub.storage.list({
186
+ bucket: "avatars",
187
+ prefix: "users/",
188
+ limit: 50,
189
+ });
190
+
191
+ // Delete
192
+ await hub.storage.deleteObject("avatars", "users/user1.jpg");
193
+
194
+ // Bucket management
195
+ const buckets = await hub.storage.listBuckets();
196
+ await hub.storage.deleteBucket("old-bucket");
197
+ ```
198
+
199
+ ## Error Handling
200
+
201
+ All methods throw `AuthHubError` on failure:
202
+
203
+ ```typescript
204
+ import { AuthHubError } from "authhub-sdk";
205
+
206
+ try {
207
+ await hub.auth.login("user@example.com", "wrong-password");
208
+ } catch (err) {
209
+ if (err instanceof AuthHubError) {
210
+ console.log(err.message); // "Invalid credentials"
211
+ console.log(err.status); // 401
212
+ console.log(err.code); // optional error code
213
+ }
214
+ }
215
+ ```
216
+
217
+ ## Build from Source
218
+
219
+ ```bash
220
+ cd sdk
221
+ npm install
222
+ npm run build
223
+ ```
224
+
225
+ This produces `dist/` with CJS, ESM, and type declarations.
@@ -0,0 +1,458 @@
1
+ interface AuthHubConfig {
2
+ /** Base URL of the Auth Hub instance (e.g. "https://auth.example.com") */
3
+ baseUrl: string;
4
+ /** Project UUID */
5
+ projectId: string;
6
+ /** Project API key (sk_...) */
7
+ apiKey: string;
8
+ /**
9
+ * Token storage strategy.
10
+ * - "localStorage" (default in browser) — persists across tabs/refreshes
11
+ * - "memory" (default in Node) — tokens lost on process exit
12
+ * - Custom object implementing TokenStore interface
13
+ */
14
+ tokenStore?: "localStorage" | "memory" | TokenStore;
15
+ /** Auto-refresh access token when expired. Default: true */
16
+ autoRefresh?: boolean;
17
+ /** Called when the session is lost (refresh token expired/revoked) */
18
+ onSessionExpired?: () => void;
19
+ }
20
+ interface TokenStore {
21
+ get(key: string): string | null | Promise<string | null>;
22
+ set(key: string, value: string): void | Promise<void>;
23
+ remove(key: string): void | Promise<void>;
24
+ }
25
+ interface TokenPair {
26
+ accessToken: string;
27
+ refreshToken: string;
28
+ expiresAt: number;
29
+ }
30
+ interface User {
31
+ id: string;
32
+ email: string;
33
+ confirmed_at: string | null;
34
+ created_at: string;
35
+ last_sign_in_at: string | null;
36
+ app_metadata: {
37
+ provider: string;
38
+ };
39
+ user_metadata: Record<string, unknown>;
40
+ }
41
+ interface AuthResponse {
42
+ access_token: string;
43
+ refresh_token: string;
44
+ token_type: "bearer";
45
+ expires_in: number;
46
+ user: User;
47
+ }
48
+ interface RegisterResponse {
49
+ message: string;
50
+ user: {
51
+ id: string;
52
+ email: string;
53
+ };
54
+ }
55
+ interface MessageResponse {
56
+ message: string;
57
+ }
58
+ interface SessionResponse {
59
+ user: User;
60
+ }
61
+ /** Comparison operators for where clauses */
62
+ type WhereOperator = {
63
+ $eq: unknown;
64
+ } | {
65
+ $neq: unknown;
66
+ } | {
67
+ $gt: unknown;
68
+ } | {
69
+ $gte: unknown;
70
+ } | {
71
+ $lt: unknown;
72
+ } | {
73
+ $lte: unknown;
74
+ } | {
75
+ $in: unknown[];
76
+ } | {
77
+ $nin: unknown[];
78
+ } | {
79
+ $like: string;
80
+ } | {
81
+ $ilike: string;
82
+ } | {
83
+ $is: null | boolean;
84
+ } | {
85
+ $not: null | boolean;
86
+ };
87
+ type WhereClause = Record<string, unknown | WhereOperator>;
88
+ interface OrderBy {
89
+ column: string;
90
+ order?: "ASC" | "DESC";
91
+ }
92
+ interface DbReadOptions {
93
+ table: string;
94
+ select?: string[];
95
+ where?: WhereClause;
96
+ limit?: number;
97
+ offset?: number;
98
+ orderBy?: OrderBy | OrderBy[];
99
+ }
100
+ interface DbCreateOptions {
101
+ table: string;
102
+ data: Record<string, unknown>;
103
+ }
104
+ interface DbUpdateOptions {
105
+ table: string;
106
+ data: Record<string, unknown>;
107
+ where: WhereClause;
108
+ }
109
+ interface DbDeleteOptions {
110
+ table: string;
111
+ where: WhereClause;
112
+ }
113
+ interface DbReadResult<T = Record<string, unknown>> {
114
+ rows: T[];
115
+ count: number;
116
+ }
117
+ interface DbMutationResult<T = Record<string, unknown>> {
118
+ rows: T[];
119
+ [key: string]: unknown;
120
+ }
121
+ interface Bucket {
122
+ id: string;
123
+ name: string;
124
+ isPublic: boolean;
125
+ maxFileSize: number;
126
+ allowedMimeTypes: string | null;
127
+ createdAt: string;
128
+ _count?: {
129
+ objects: number;
130
+ };
131
+ }
132
+ interface StorageObject {
133
+ id: string;
134
+ key: string;
135
+ size: number;
136
+ mimeType: string;
137
+ bucketId: string;
138
+ createdAt: string;
139
+ updatedAt?: string;
140
+ }
141
+ interface StorageListResult {
142
+ objects: StorageObject[];
143
+ count: number;
144
+ }
145
+ interface CreateBucketOptions {
146
+ name: string;
147
+ isPublic?: boolean;
148
+ maxFileSize?: number;
149
+ allowedMimeTypes?: string;
150
+ }
151
+ interface UploadOptions {
152
+ bucket: string;
153
+ key: string;
154
+ file: Blob | File | Buffer;
155
+ contentType?: string;
156
+ }
157
+ interface ListObjectsOptions {
158
+ bucket: string;
159
+ prefix?: string;
160
+ limit?: number;
161
+ offset?: number;
162
+ }
163
+ type OAuthProvider = "google" | "github";
164
+ interface OAuthHashParams {
165
+ access_token: string;
166
+ refresh_token: string;
167
+ token_type: string;
168
+ expires_in: number;
169
+ provider: string;
170
+ }
171
+ interface RealtimeConfig {
172
+ /** WebSocket server URL (e.g. "ws://localhost:4000") */
173
+ url: string;
174
+ /** Project UUID */
175
+ projectId: string;
176
+ }
177
+ interface RealtimeMessage {
178
+ type: string;
179
+ channel?: string;
180
+ event?: string;
181
+ status?: string;
182
+ data?: Record<string, unknown>;
183
+ message?: string;
184
+ }
185
+ type RealtimeMutationHandler = (event: string, data: Record<string, unknown>) => void;
186
+ interface SessionLoginResult$1 {
187
+ user: User;
188
+ /** Set-Cookie headers from Auth Hub — forward these to the browser response */
189
+ setCookieHeaders: string[];
190
+ }
191
+ interface AuthHubErrorData {
192
+ message: string;
193
+ code?: string;
194
+ status: number;
195
+ }
196
+
197
+ declare class MemoryTokenStore implements TokenStore {
198
+ private store;
199
+ get(key: string): string | null;
200
+ set(key: string, value: string): void;
201
+ remove(key: string): void;
202
+ }
203
+ declare class LocalStorageTokenStore implements TokenStore {
204
+ get(key: string): string | null;
205
+ set(key: string, value: string): void;
206
+ remove(key: string): void;
207
+ }
208
+ declare class TokenManager {
209
+ private store;
210
+ constructor(store: TokenStore);
211
+ getTokens(): Promise<TokenPair | null>;
212
+ setTokens(tokens: TokenPair): Promise<void>;
213
+ clear(): Promise<void>;
214
+ isExpired(): Promise<boolean>;
215
+ }
216
+
217
+ declare class AuthHubClient {
218
+ private baseUrl;
219
+ private projectId;
220
+ private apiKey;
221
+ private tokens;
222
+ private autoRefresh;
223
+ private onSessionExpired?;
224
+ private refreshPromise;
225
+ /** Auth operations (register, login, logout, etc.) */
226
+ readonly auth: AuthModule;
227
+ /** Cookie-based session operations (for server-side Next.js / SSR apps) */
228
+ readonly session: SessionModule;
229
+ /** Database CRUD operations */
230
+ readonly db: DbModule;
231
+ /** File storage operations */
232
+ readonly storage: StorageModule;
233
+ /** OAuth social login helpers */
234
+ readonly oauth: OAuthModule;
235
+ constructor(config: AuthHubConfig);
236
+ /**
237
+ * Create a Realtime client for subscribing to database changes via WebSocket.
238
+ *
239
+ * ```ts
240
+ * const realtime = hub.realtime("ws://localhost:4000");
241
+ * await realtime.connect(accessToken);
242
+ * realtime.on("table:users", (event, data) => console.log(event, data));
243
+ * ```
244
+ */
245
+ realtime(wsUrl: string): RealtimeClient;
246
+ /** @internal */
247
+ _url(path: string): string;
248
+ /** @internal — API key auth request */
249
+ _apiRequest<T>(path: string, options?: RequestInit): Promise<T>;
250
+ /** @internal — Bearer JWT auth request (auto-refreshes if needed) */
251
+ _authRequest<T>(path: string, options?: RequestInit): Promise<T>;
252
+ /** @internal */
253
+ _handleResponse<T>(res: Response): Promise<T>;
254
+ /** @internal — Save tokens from an auth response */
255
+ _saveAuthTokens(response: AuthResponse): Promise<void>;
256
+ /** @internal — Get valid access token, refreshing if necessary */
257
+ private _getValidAccessToken;
258
+ /** @internal — Refresh with dedup (prevents concurrent refresh calls) */
259
+ private _refreshTokens;
260
+ /** Get the token manager (for advanced usage) */
261
+ getTokenManager(): TokenManager;
262
+ }
263
+ declare class AuthModule {
264
+ private client;
265
+ constructor(client: AuthHubClient);
266
+ /** Register a new user account */
267
+ register(email: string, password: string, redirectTo?: string): Promise<RegisterResponse>;
268
+ /** Login with email and password. Stores tokens automatically. */
269
+ login(email: string, password: string): Promise<AuthResponse>;
270
+ /** Logout — revokes tokens on server and clears local storage */
271
+ logout(): Promise<void>;
272
+ /** Get current authenticated user profile */
273
+ getUser(): Promise<User>;
274
+ /** Change password for the authenticated user */
275
+ changePassword(currentPassword: string, newPassword: string): Promise<MessageResponse>;
276
+ /** Request password recovery email */
277
+ recover(email: string): Promise<MessageResponse>;
278
+ /** Reset password using token from recovery email */
279
+ resetPassword(token: string, newPassword: string): Promise<MessageResponse>;
280
+ /**
281
+ * Refresh tokens using a refresh token.
282
+ * Normally called automatically — use this for manual refresh.
283
+ */
284
+ refreshToken(refreshToken: string): Promise<AuthResponse>;
285
+ /** Check if the user has a stored session (tokens exist and access token not expired) */
286
+ isAuthenticated(): Promise<boolean>;
287
+ /** Get the current access token (or null if not authenticated) */
288
+ getAccessToken(): Promise<string | null>;
289
+ }
290
+ declare class SessionModule {
291
+ private client;
292
+ constructor(client: AuthHubClient);
293
+ /**
294
+ * Create a cookie-based session (login).
295
+ * Returns the user and Set-Cookie headers that must be forwarded to the browser.
296
+ *
297
+ * Usage in Next.js API route:
298
+ * ```ts
299
+ * const { user, setCookieHeaders } = await hub.session.login(email, password);
300
+ * const response = NextResponse.json({ success: true });
301
+ * for (const h of setCookieHeaders) response.headers.append("Set-Cookie", h);
302
+ * ```
303
+ */
304
+ login(email: string, password: string): Promise<SessionLoginResult>;
305
+ /**
306
+ * Validate an existing session by forwarding browser cookies.
307
+ * Returns the user if valid, null if session is expired/invalid.
308
+ *
309
+ * Usage in Next.js:
310
+ * ```ts
311
+ * const cookieHeader = request.headers.get("cookie") || "";
312
+ * const user = await hub.session.validate(cookieHeader);
313
+ * ```
314
+ */
315
+ validate(cookieHeader: string): Promise<User | null>;
316
+ /**
317
+ * Destroy a cookie-based session (logout).
318
+ * Returns Set-Cookie headers that clear the session cookies in the browser.
319
+ *
320
+ * Usage in Next.js API route:
321
+ * ```ts
322
+ * const cookieHeader = request.headers.get("cookie") || "";
323
+ * const setCookieHeaders = await hub.session.logout(cookieHeader);
324
+ * const response = NextResponse.json({ success: true });
325
+ * for (const h of setCookieHeaders) response.headers.append("Set-Cookie", h);
326
+ * ```
327
+ */
328
+ logout(cookieHeader: string): Promise<string[]>;
329
+ /**
330
+ * Change password for a user identified by their session cookies.
331
+ * Extracts the access token from the cookie header and uses it for JWT auth.
332
+ */
333
+ changePassword(cookieHeader: string, currentPassword: string, newPassword: string): Promise<MessageResponse>;
334
+ }
335
+ interface SessionLoginResult {
336
+ user: User;
337
+ setCookieHeaders: string[];
338
+ }
339
+ declare class DbModule {
340
+ private client;
341
+ constructor(client: AuthHubClient);
342
+ /** Insert a row into a table */
343
+ create<T = Record<string, unknown>>(options: DbCreateOptions): Promise<DbMutationResult<T>>;
344
+ /** Query rows from a table with filtering, selection, ordering, pagination */
345
+ read<T = Record<string, unknown>>(options: DbReadOptions): Promise<DbReadResult<T>>;
346
+ /** Update rows matching a where clause */
347
+ update<T = Record<string, unknown>>(options: DbUpdateOptions): Promise<DbMutationResult<T>>;
348
+ /** Delete rows matching a where clause */
349
+ delete<T = Record<string, unknown>>(options: DbDeleteOptions): Promise<DbMutationResult<T>>;
350
+ /** Find one row by column value */
351
+ findOne<T = Record<string, unknown>>(table: string, where: Record<string, unknown>): Promise<T | null>;
352
+ /** Find one row by id */
353
+ findById<T = Record<string, unknown>>(table: string, id: unknown): Promise<T | null>;
354
+ /** Count rows matching a where clause */
355
+ count(table: string, where?: Record<string, unknown>): Promise<number>;
356
+ }
357
+ declare class StorageModule {
358
+ private client;
359
+ constructor(client: AuthHubClient);
360
+ /** Create a storage bucket */
361
+ createBucket(options: CreateBucketOptions): Promise<Bucket>;
362
+ /** List all buckets */
363
+ listBuckets(): Promise<Bucket[]>;
364
+ /** Delete a bucket and all its contents */
365
+ deleteBucket(name: string): Promise<void>;
366
+ /** Upload a file to a bucket */
367
+ upload(options: UploadOptions): Promise<StorageObject>;
368
+ /** Download a file. Returns the raw Response for streaming support. */
369
+ download(bucket: string, key: string): Promise<Response>;
370
+ /** Download a file and return it as a Buffer (Node) or ArrayBuffer (browser) */
371
+ downloadBuffer(bucket: string, key: string): Promise<ArrayBuffer>;
372
+ /** Get the public URL for a file (only works for public buckets) */
373
+ getPublicUrl(bucket: string, key: string): string;
374
+ /** Delete a file from a bucket */
375
+ deleteObject(bucket: string, key: string): Promise<void>;
376
+ /** List objects in a bucket */
377
+ list(options: ListObjectsOptions): Promise<StorageListResult>;
378
+ }
379
+ declare class OAuthModule {
380
+ private client;
381
+ constructor(client: AuthHubClient);
382
+ /**
383
+ * Get the URL to redirect the user to for OAuth login.
384
+ *
385
+ * ```ts
386
+ * const url = hub.oauth.getAuthUrl("google", "/dashboard");
387
+ * window.location.href = url;
388
+ * ```
389
+ */
390
+ getAuthUrl(provider: OAuthProvider, redirectTo?: string): string;
391
+ /**
392
+ * Parse OAuth tokens from the URL hash fragment after a redirect callback.
393
+ * Returns null if no tokens are found in the hash.
394
+ *
395
+ * ```ts
396
+ * const result = hub.oauth.handleCallback();
397
+ * if (result) {
398
+ * console.log("Logged in via", result.provider, result.access_token);
399
+ * // Tokens are automatically stored
400
+ * }
401
+ * ```
402
+ */
403
+ handleCallback(hash?: string): Promise<OAuthHashParams | null>;
404
+ /**
405
+ * Convenience: redirect to OAuth provider login page.
406
+ * Only works in browser environments.
407
+ */
408
+ signInWithProvider(provider: OAuthProvider, redirectTo?: string): void;
409
+ }
410
+ declare class RealtimeClient {
411
+ private config;
412
+ private ws;
413
+ private listeners;
414
+ private connected;
415
+ private authenticated;
416
+ constructor(config: RealtimeConfig);
417
+ /**
418
+ * Connect to the realtime server and authenticate.
419
+ *
420
+ * ```ts
421
+ * const realtime = hub.realtime("ws://localhost:4000");
422
+ * await realtime.connect(accessToken);
423
+ * ```
424
+ */
425
+ connect(accessToken: string): Promise<void>;
426
+ /**
427
+ * Subscribe to changes on a table.
428
+ *
429
+ * ```ts
430
+ * realtime.on("table:users", (event, data) => {
431
+ * console.log(event); // "INSERT", "UPDATE", "DELETE"
432
+ * console.log(data); // { table, operation, id, timestamp }
433
+ * });
434
+ * ```
435
+ */
436
+ on(channel: string, handler: RealtimeMutationHandler): this;
437
+ /** Remove a specific handler from a channel */
438
+ off(channel: string, handler: RealtimeMutationHandler): this;
439
+ /**
440
+ * Subscribe to a table and send the subscribe message.
441
+ * Alias for `on()` that returns a Promise resolving when the server confirms.
442
+ */
443
+ subscribe(channel: string, handler: RealtimeMutationHandler): Promise<void>;
444
+ /** Unsubscribe from a channel (removes all handlers) */
445
+ unsubscribe(channel: string): void;
446
+ /** Close the WebSocket connection */
447
+ close(): void;
448
+ /** Check if connected and authenticated */
449
+ isConnected(): boolean;
450
+ }
451
+
452
+ declare class AuthHubError extends Error {
453
+ status: number;
454
+ code?: string;
455
+ constructor(data: AuthHubErrorData);
456
+ }
457
+
458
+ export { AuthHubClient, type AuthHubConfig, AuthHubError, type AuthHubErrorData, type AuthResponse, type Bucket, type CreateBucketOptions, type DbCreateOptions, type DbDeleteOptions, type DbMutationResult, type DbReadOptions, type DbReadResult, type DbUpdateOptions, type ListObjectsOptions, LocalStorageTokenStore, MemoryTokenStore, type MessageResponse, type OAuthHashParams, type OAuthProvider, type OrderBy, RealtimeClient, type RealtimeConfig, type RealtimeMessage, type RealtimeMutationHandler, type RegisterResponse, type SessionLoginResult$1 as SessionLoginResult, type SessionResponse, type StorageListResult, type StorageObject, TokenManager, type TokenPair, type TokenStore, type UploadOptions, type User, type WhereClause, type WhereOperator };