@fluxbase/sdk 0.0.1-rc.2 → 0.0.1-rc.20

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/dist/index.js CHANGED
@@ -114,6 +114,29 @@ var FluxbaseFetch = class {
114
114
  }
115
115
  };
116
116
 
117
+ // src/utils/error-handling.ts
118
+ async function wrapAsync(operation) {
119
+ try {
120
+ const data = await operation();
121
+ return { data, error: null };
122
+ } catch (error) {
123
+ return {
124
+ data: null,
125
+ error: error instanceof Error ? error : new Error(String(error))
126
+ };
127
+ }
128
+ }
129
+ async function wrapAsyncVoid(operation) {
130
+ try {
131
+ await operation();
132
+ return { error: null };
133
+ } catch (error) {
134
+ return {
135
+ error: error instanceof Error ? error : new Error(String(error))
136
+ };
137
+ }
138
+ }
139
+
117
140
  // src/auth.ts
118
141
  var AUTH_STORAGE_KEY = "fluxbase.auth.session";
119
142
  var FluxbaseAuth = class {
@@ -185,83 +208,107 @@ var FluxbaseAuth = class {
185
208
  * Returns AuthSession if successful, or SignInWith2FAResponse if 2FA is required
186
209
  */
187
210
  async signIn(credentials) {
188
- const response = await this.fetch.post(
189
- "/api/v1/auth/signin",
190
- credentials
191
- );
192
- if ("requires_2fa" in response && response.requires_2fa) {
193
- return response;
194
- }
195
- const authResponse = response;
196
- const session = {
197
- ...authResponse,
198
- expires_at: Date.now() + authResponse.expires_in * 1e3
199
- };
200
- this.setSession(session);
201
- return session;
211
+ return wrapAsync(async () => {
212
+ const response = await this.fetch.post("/api/v1/auth/signin", credentials);
213
+ if ("requires_2fa" in response && response.requires_2fa) {
214
+ return response;
215
+ }
216
+ const authResponse = response;
217
+ const session = {
218
+ ...authResponse,
219
+ expires_at: Date.now() + authResponse.expires_in * 1e3
220
+ };
221
+ this.setSession(session);
222
+ return session;
223
+ });
224
+ }
225
+ /**
226
+ * Sign in with email and password
227
+ * Alias for signIn() to maintain compatibility with common authentication patterns
228
+ * Returns AuthSession if successful, or SignInWith2FAResponse if 2FA is required
229
+ */
230
+ async signInWithPassword(credentials) {
231
+ return this.signIn(credentials);
202
232
  }
203
233
  /**
204
234
  * Sign up with email and password
205
235
  */
206
236
  async signUp(credentials) {
207
- const response = await this.fetch.post("/api/v1/auth/signup", credentials);
208
- const session = {
209
- ...response,
210
- expires_at: Date.now() + response.expires_in * 1e3
211
- };
212
- this.setSession(session);
213
- return session;
237
+ return wrapAsync(async () => {
238
+ const response = await this.fetch.post(
239
+ "/api/v1/auth/signup",
240
+ credentials
241
+ );
242
+ const session = {
243
+ ...response,
244
+ expires_at: Date.now() + response.expires_in * 1e3
245
+ };
246
+ this.setSession(session);
247
+ return { user: session.user, session };
248
+ });
214
249
  }
215
250
  /**
216
251
  * Sign out the current user
217
252
  */
218
253
  async signOut() {
219
- try {
220
- await this.fetch.post("/api/v1/auth/signout");
221
- } finally {
222
- this.clearSession();
223
- }
254
+ return wrapAsyncVoid(async () => {
255
+ try {
256
+ await this.fetch.post("/api/v1/auth/signout");
257
+ } finally {
258
+ this.clearSession();
259
+ }
260
+ });
224
261
  }
225
262
  /**
226
263
  * Refresh the access token
227
264
  */
228
265
  async refreshToken() {
229
- if (!this.session?.refresh_token) {
230
- throw new Error("No refresh token available");
231
- }
232
- const response = await this.fetch.post("/api/v1/auth/refresh", {
233
- refresh_token: this.session.refresh_token
266
+ return wrapAsync(async () => {
267
+ if (!this.session?.refresh_token) {
268
+ throw new Error("No refresh token available");
269
+ }
270
+ const response = await this.fetch.post(
271
+ "/api/v1/auth/refresh",
272
+ {
273
+ refresh_token: this.session.refresh_token
274
+ }
275
+ );
276
+ const session = {
277
+ ...response,
278
+ expires_at: Date.now() + response.expires_in * 1e3
279
+ };
280
+ this.setSession(session, "TOKEN_REFRESHED");
281
+ return { session };
234
282
  });
235
- const session = {
236
- ...response,
237
- expires_at: Date.now() + response.expires_in * 1e3
238
- };
239
- this.setSession(session, "TOKEN_REFRESHED");
240
- return session;
241
283
  }
242
284
  /**
243
285
  * Get the current user from the server
244
286
  */
245
287
  async getCurrentUser() {
246
- if (!this.session) {
247
- throw new Error("Not authenticated");
248
- }
249
- return await this.fetch.get("/api/v1/auth/user");
288
+ return wrapAsync(async () => {
289
+ if (!this.session) {
290
+ throw new Error("Not authenticated");
291
+ }
292
+ const user = await this.fetch.get("/api/v1/auth/user");
293
+ return { user };
294
+ });
250
295
  }
251
296
  /**
252
297
  * Update the current user
253
298
  */
254
299
  async updateUser(data) {
255
- if (!this.session) {
256
- throw new Error("Not authenticated");
257
- }
258
- const user = await this.fetch.patch("/api/v1/auth/user", data);
259
- if (this.session) {
260
- this.session.user = user;
261
- this.saveSession();
262
- this.emitAuthChange("USER_UPDATED", this.session);
263
- }
264
- return user;
300
+ return wrapAsync(async () => {
301
+ if (!this.session) {
302
+ throw new Error("Not authenticated");
303
+ }
304
+ const user = await this.fetch.patch("/api/v1/auth/user", data);
305
+ if (this.session) {
306
+ this.session.user = user;
307
+ this.saveSession();
308
+ this.emitAuthChange("USER_UPDATED", this.session);
309
+ }
310
+ return { user };
311
+ });
265
312
  }
266
313
  /**
267
314
  * Set the auth token manually
@@ -274,55 +321,75 @@ var FluxbaseAuth = class {
274
321
  * Returns TOTP secret and QR code URL
275
322
  */
276
323
  async setup2FA() {
277
- if (!this.session) {
278
- throw new Error("Not authenticated");
279
- }
280
- return await this.fetch.post("/api/v1/auth/2fa/setup");
324
+ return wrapAsync(async () => {
325
+ if (!this.session) {
326
+ throw new Error("Not authenticated");
327
+ }
328
+ return await this.fetch.post(
329
+ "/api/v1/auth/2fa/setup"
330
+ );
331
+ });
281
332
  }
282
333
  /**
283
334
  * Enable 2FA after verifying the TOTP code
284
335
  * Returns backup codes that should be saved by the user
285
336
  */
286
337
  async enable2FA(code) {
287
- if (!this.session) {
288
- throw new Error("Not authenticated");
289
- }
290
- return await this.fetch.post("/api/v1/auth/2fa/enable", { code });
338
+ return wrapAsync(async () => {
339
+ if (!this.session) {
340
+ throw new Error("Not authenticated");
341
+ }
342
+ return await this.fetch.post(
343
+ "/api/v1/auth/2fa/enable",
344
+ { code }
345
+ );
346
+ });
291
347
  }
292
348
  /**
293
349
  * Disable 2FA for the current user
294
350
  * Requires password confirmation
295
351
  */
296
352
  async disable2FA(password) {
297
- if (!this.session) {
298
- throw new Error("Not authenticated");
299
- }
300
- return await this.fetch.post(
301
- "/api/v1/auth/2fa/disable",
302
- { password }
303
- );
353
+ return wrapAsync(async () => {
354
+ if (!this.session) {
355
+ throw new Error("Not authenticated");
356
+ }
357
+ return await this.fetch.post(
358
+ "/api/v1/auth/2fa/disable",
359
+ { password }
360
+ );
361
+ });
304
362
  }
305
363
  /**
306
364
  * Check 2FA status for the current user
307
365
  */
308
366
  async get2FAStatus() {
309
- if (!this.session) {
310
- throw new Error("Not authenticated");
311
- }
312
- return await this.fetch.get("/api/v1/auth/2fa/status");
367
+ return wrapAsync(async () => {
368
+ if (!this.session) {
369
+ throw new Error("Not authenticated");
370
+ }
371
+ return await this.fetch.get(
372
+ "/api/v1/auth/2fa/status"
373
+ );
374
+ });
313
375
  }
314
376
  /**
315
377
  * Verify 2FA code during login
316
378
  * Call this after signIn returns requires_2fa: true
317
379
  */
318
380
  async verify2FA(request) {
319
- const response = await this.fetch.post("/api/v1/auth/2fa/verify", request);
320
- const session = {
321
- ...response,
322
- expires_at: Date.now() + response.expires_in * 1e3
323
- };
324
- this.setSession(session, "MFA_CHALLENGE_VERIFIED");
325
- return session;
381
+ return wrapAsync(async () => {
382
+ const response = await this.fetch.post(
383
+ "/api/v1/auth/2fa/verify",
384
+ request
385
+ );
386
+ const session = {
387
+ ...response,
388
+ expires_at: Date.now() + response.expires_in * 1e3
389
+ };
390
+ this.setSession(session, "MFA_CHALLENGE_VERIFIED");
391
+ return { user: session.user, session };
392
+ });
326
393
  }
327
394
  /**
328
395
  * Send password reset email
@@ -330,7 +397,20 @@ var FluxbaseAuth = class {
330
397
  * @param email - Email address to send reset link to
331
398
  */
332
399
  async sendPasswordReset(email) {
333
- return await this.fetch.post("/api/v1/auth/password/reset", { email });
400
+ return wrapAsync(async () => {
401
+ return await this.fetch.post(
402
+ "/api/v1/auth/password/reset",
403
+ { email }
404
+ );
405
+ });
406
+ }
407
+ /**
408
+ * Supabase-compatible alias for sendPasswordReset()
409
+ * @param email - Email address to send reset link to
410
+ * @param _options - Optional redirect configuration (currently not used)
411
+ */
412
+ async resetPasswordForEmail(email, _options) {
413
+ return this.sendPasswordReset(email);
334
414
  }
335
415
  /**
336
416
  * Verify password reset token
@@ -338,8 +418,13 @@ var FluxbaseAuth = class {
338
418
  * @param token - Password reset token to verify
339
419
  */
340
420
  async verifyResetToken(token) {
341
- return await this.fetch.post("/api/v1/auth/password/reset/verify", {
342
- token
421
+ return wrapAsync(async () => {
422
+ return await this.fetch.post(
423
+ "/api/v1/auth/password/reset/verify",
424
+ {
425
+ token
426
+ }
427
+ );
343
428
  });
344
429
  }
345
430
  /**
@@ -349,9 +434,14 @@ var FluxbaseAuth = class {
349
434
  * @param newPassword - New password to set
350
435
  */
351
436
  async resetPassword(token, newPassword) {
352
- return await this.fetch.post("/api/v1/auth/password/reset/confirm", {
353
- token,
354
- new_password: newPassword
437
+ return wrapAsync(async () => {
438
+ return await this.fetch.post(
439
+ "/api/v1/auth/password/reset/confirm",
440
+ {
441
+ token,
442
+ new_password: newPassword
443
+ }
444
+ );
355
445
  });
356
446
  }
357
447
  /**
@@ -360,9 +450,14 @@ var FluxbaseAuth = class {
360
450
  * @param options - Optional configuration for magic link
361
451
  */
362
452
  async sendMagicLink(email, options) {
363
- return await this.fetch.post("/api/v1/auth/magiclink", {
364
- email,
365
- redirect_to: options?.redirect_to
453
+ return wrapAsync(async () => {
454
+ return await this.fetch.post(
455
+ "/api/v1/auth/magiclink",
456
+ {
457
+ email,
458
+ redirect_to: options?.redirect_to
459
+ }
460
+ );
366
461
  });
367
462
  }
368
463
  /**
@@ -370,34 +465,47 @@ var FluxbaseAuth = class {
370
465
  * @param token - Magic link token from email
371
466
  */
372
467
  async verifyMagicLink(token) {
373
- const response = await this.fetch.post("/api/v1/auth/magiclink/verify", {
374
- token
468
+ return wrapAsync(async () => {
469
+ const response = await this.fetch.post(
470
+ "/api/v1/auth/magiclink/verify",
471
+ {
472
+ token
473
+ }
474
+ );
475
+ const session = {
476
+ ...response,
477
+ expires_at: Date.now() + response.expires_in * 1e3
478
+ };
479
+ this.setSession(session);
480
+ return { user: session.user, session };
375
481
  });
376
- const session = {
377
- ...response,
378
- expires_at: Date.now() + response.expires_in * 1e3
379
- };
380
- this.setSession(session);
381
- return session;
382
482
  }
383
483
  /**
384
484
  * Sign in anonymously
385
485
  * Creates a temporary anonymous user session
386
486
  */
387
487
  async signInAnonymously() {
388
- const response = await this.fetch.post("/api/v1/auth/signin/anonymous");
389
- const session = {
390
- ...response,
391
- expires_at: Date.now() + response.expires_in * 1e3
392
- };
393
- this.setSession(session);
394
- return session;
488
+ return wrapAsync(async () => {
489
+ const response = await this.fetch.post(
490
+ "/api/v1/auth/signin/anonymous"
491
+ );
492
+ const session = {
493
+ ...response,
494
+ expires_at: Date.now() + response.expires_in * 1e3
495
+ };
496
+ this.setSession(session);
497
+ return { user: session.user, session };
498
+ });
395
499
  }
396
500
  /**
397
501
  * Get list of enabled OAuth providers
398
502
  */
399
503
  async getOAuthProviders() {
400
- return await this.fetch.get("/api/v1/auth/oauth/providers");
504
+ return wrapAsync(async () => {
505
+ return await this.fetch.get(
506
+ "/api/v1/auth/oauth/providers"
507
+ );
508
+ });
401
509
  }
402
510
  /**
403
511
  * Get OAuth authorization URL for a provider
@@ -405,17 +513,19 @@ var FluxbaseAuth = class {
405
513
  * @param options - Optional OAuth configuration
406
514
  */
407
515
  async getOAuthUrl(provider, options) {
408
- const params = new URLSearchParams();
409
- if (options?.redirect_to) {
410
- params.append("redirect_to", options.redirect_to);
411
- }
412
- if (options?.scopes && options.scopes.length > 0) {
413
- params.append("scopes", options.scopes.join(","));
414
- }
415
- const queryString = params.toString();
416
- const url = queryString ? `/api/v1/auth/oauth/${provider}/authorize?${queryString}` : `/api/v1/auth/oauth/${provider}/authorize`;
417
- const response = await this.fetch.get(url);
418
- return response;
516
+ return wrapAsync(async () => {
517
+ const params = new URLSearchParams();
518
+ if (options?.redirect_to) {
519
+ params.append("redirect_to", options.redirect_to);
520
+ }
521
+ if (options?.scopes && options.scopes.length > 0) {
522
+ params.append("scopes", options.scopes.join(","));
523
+ }
524
+ const queryString = params.toString();
525
+ const url = queryString ? `/api/v1/auth/oauth/${provider}/authorize?${queryString}` : `/api/v1/auth/oauth/${provider}/authorize`;
526
+ const response = await this.fetch.get(url);
527
+ return response;
528
+ });
419
529
  }
420
530
  /**
421
531
  * Exchange OAuth authorization code for session
@@ -423,13 +533,18 @@ var FluxbaseAuth = class {
423
533
  * @param code - Authorization code from OAuth callback
424
534
  */
425
535
  async exchangeCodeForSession(code) {
426
- const response = await this.fetch.post("/api/v1/auth/oauth/callback", { code });
427
- const session = {
428
- ...response,
429
- expires_at: Date.now() + response.expires_in * 1e3
430
- };
431
- this.setSession(session);
432
- return session;
536
+ return wrapAsync(async () => {
537
+ const response = await this.fetch.post(
538
+ "/api/v1/auth/oauth/callback",
539
+ { code }
540
+ );
541
+ const session = {
542
+ ...response,
543
+ expires_at: Date.now() + response.expires_in * 1e3
544
+ };
545
+ this.setSession(session);
546
+ return { user: session.user, session };
547
+ });
433
548
  }
434
549
  /**
435
550
  * Convenience method to initiate OAuth sign-in
@@ -438,12 +553,21 @@ var FluxbaseAuth = class {
438
553
  * @param options - Optional OAuth configuration
439
554
  */
440
555
  async signInWithOAuth(provider, options) {
441
- const { url } = await this.getOAuthUrl(provider, options);
442
- if (typeof window !== "undefined") {
443
- window.location.href = url;
444
- } else {
445
- throw new Error("signInWithOAuth can only be called in a browser environment");
446
- }
556
+ return wrapAsync(async () => {
557
+ const result = await this.getOAuthUrl(provider, options);
558
+ if (result.error) {
559
+ throw result.error;
560
+ }
561
+ const url = result.data.url;
562
+ if (typeof window !== "undefined") {
563
+ window.location.href = url;
564
+ } else {
565
+ throw new Error(
566
+ "signInWithOAuth can only be called in a browser environment"
567
+ );
568
+ }
569
+ return { provider, url };
570
+ });
447
571
  }
448
572
  /**
449
573
  * Internal: Set the session and persist it
@@ -491,11 +615,12 @@ var FluxbaseAuth = class {
491
615
  const refreshAt = this.session.expires_at - 60 * 1e3;
492
616
  const delay = refreshAt - Date.now();
493
617
  if (delay > 0) {
494
- this.refreshTimer = setTimeout(() => {
495
- this.refreshToken().catch((err) => {
496
- console.error("Failed to refresh token:", err);
618
+ this.refreshTimer = setTimeout(async () => {
619
+ const result = await this.refreshToken();
620
+ if (result.error) {
621
+ console.error("Failed to refresh token:", result.error);
497
622
  this.clearSession();
498
- });
623
+ }
499
624
  }, delay);
500
625
  }
501
626
  }
@@ -560,22 +685,55 @@ var RealtimeChannel = class {
560
685
  }
561
686
  /**
562
687
  * Subscribe to the channel
688
+ * @param callback - Optional status callback (Supabase-compatible)
689
+ * @param _timeout - Optional timeout in milliseconds (currently unused)
563
690
  */
564
- subscribe() {
691
+ subscribe(callback, _timeout) {
565
692
  this.connect();
693
+ if (callback) {
694
+ const checkConnection = () => {
695
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
696
+ callback("SUBSCRIBED");
697
+ } else if (this.ws && this.ws.readyState === WebSocket.CLOSED) {
698
+ callback("CHANNEL_ERROR", new Error("Failed to connect"));
699
+ } else {
700
+ setTimeout(checkConnection, 100);
701
+ }
702
+ };
703
+ setTimeout(checkConnection, 100);
704
+ }
566
705
  return this;
567
706
  }
568
707
  /**
569
708
  * Unsubscribe from the channel
570
- */
571
- unsubscribe() {
572
- if (this.ws) {
573
- this.send({
574
- type: "unsubscribe",
575
- channel: this.channelName
576
- });
577
- this.disconnect();
578
- }
709
+ * @param timeout - Optional timeout in milliseconds
710
+ * @returns Promise resolving to status string (Supabase-compatible)
711
+ */
712
+ async unsubscribe(timeout) {
713
+ return new Promise((resolve) => {
714
+ if (this.ws) {
715
+ this.send({
716
+ type: "unsubscribe",
717
+ channel: this.channelName
718
+ });
719
+ const startTime = Date.now();
720
+ const maxWait = timeout || 5e3;
721
+ const checkDisconnect = () => {
722
+ if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
723
+ this.disconnect();
724
+ resolve("ok");
725
+ } else if (Date.now() - startTime > maxWait) {
726
+ this.disconnect();
727
+ resolve("timed out");
728
+ } else {
729
+ setTimeout(checkDisconnect, 100);
730
+ }
731
+ };
732
+ setTimeout(checkDisconnect, 100);
733
+ } else {
734
+ resolve("ok");
735
+ }
736
+ });
579
737
  }
580
738
  /**
581
739
  * Internal: Connect to WebSocket
@@ -664,13 +822,22 @@ var RealtimeChannel = class {
664
822
  * Internal: Handle broadcast message
665
823
  */
666
824
  handleBroadcast(payload) {
667
- const callbacks = this.callbacks.get(payload.type);
825
+ const supabasePayload = {
826
+ eventType: payload.type || payload.eventType,
827
+ schema: payload.schema,
828
+ table: payload.table,
829
+ commit_timestamp: payload.timestamp || payload.commit_timestamp || (/* @__PURE__ */ new Date()).toISOString(),
830
+ new: payload.new_record || payload.new || {},
831
+ old: payload.old_record || payload.old || {},
832
+ errors: payload.errors || null
833
+ };
834
+ const callbacks = this.callbacks.get(supabasePayload.eventType);
668
835
  if (callbacks) {
669
- callbacks.forEach((callback) => callback(payload));
836
+ callbacks.forEach((callback) => callback(supabasePayload));
670
837
  }
671
838
  const wildcardCallbacks = this.callbacks.get("*");
672
839
  if (wildcardCallbacks) {
673
- wildcardCallbacks.forEach((callback) => callback(payload));
840
+ wildcardCallbacks.forEach((callback) => callback(supabasePayload));
674
841
  }
675
842
  }
676
843
  /**
@@ -700,7 +867,9 @@ var RealtimeChannel = class {
700
867
  }
701
868
  this.reconnectAttempts++;
702
869
  const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
703
- console.log(`[Fluxbase Realtime] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
870
+ console.log(
871
+ `[Fluxbase Realtime] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`
872
+ );
704
873
  setTimeout(() => {
705
874
  this.connect();
706
875
  }, delay);
@@ -768,7 +937,7 @@ var StorageBucket = class {
768
937
  if (options?.upsert !== void 0) {
769
938
  formData.append("upsert", String(options.upsert));
770
939
  }
771
- const data = await this.fetch.request(
940
+ const response = await this.fetch.request(
772
941
  `/api/v1/storage/${this.bucketName}/${path}`,
773
942
  {
774
943
  method: "POST",
@@ -777,7 +946,14 @@ var StorageBucket = class {
777
946
  // Let browser set Content-Type for FormData
778
947
  }
779
948
  );
780
- return { data, error: null };
949
+ return {
950
+ data: {
951
+ id: response.id || response.key || path,
952
+ path,
953
+ fullPath: `${this.bucketName}/${path}`
954
+ },
955
+ error: null
956
+ };
781
957
  } catch (error) {
782
958
  return { data: null, error };
783
959
  }
@@ -805,13 +981,24 @@ var StorageBucket = class {
805
981
  }
806
982
  /**
807
983
  * List files in the bucket
808
- * @param options - List options (prefix, limit, offset)
984
+ * Supports both Supabase-style list(path, options) and Fluxbase-style list(options)
985
+ * @param pathOrOptions - The folder path or list options
986
+ * @param maybeOptions - List options when first param is a path
809
987
  */
810
- async list(options) {
988
+ async list(pathOrOptions, maybeOptions) {
811
989
  try {
812
990
  const params = new URLSearchParams();
813
- if (options?.prefix) {
814
- params.set("prefix", options.prefix);
991
+ let prefix;
992
+ let options;
993
+ if (typeof pathOrOptions === "string") {
994
+ prefix = pathOrOptions;
995
+ options = maybeOptions;
996
+ } else {
997
+ options = pathOrOptions;
998
+ prefix = options?.prefix;
999
+ }
1000
+ if (prefix) {
1001
+ params.set("prefix", prefix);
815
1002
  }
816
1003
  if (options?.limit) {
817
1004
  params.set("limit", String(options.limit));
@@ -821,8 +1008,17 @@ var StorageBucket = class {
821
1008
  }
822
1009
  const queryString = params.toString();
823
1010
  const path = `/api/v1/storage/${this.bucketName}${queryString ? `?${queryString}` : ""}`;
824
- const data = await this.fetch.get(path);
825
- return { data: data.objects || [], error: null };
1011
+ const response = await this.fetch.get(path);
1012
+ const files = (response.files || []).map((file) => ({
1013
+ name: file.key || file.name,
1014
+ id: file.id,
1015
+ bucket_id: file.bucket || this.bucketName,
1016
+ created_at: file.last_modified || file.created_at,
1017
+ updated_at: file.updated_at,
1018
+ last_accessed_at: file.last_accessed_at,
1019
+ metadata: file.metadata
1020
+ }));
1021
+ return { data: files, error: null };
826
1022
  } catch (error) {
827
1023
  return { data: null, error };
828
1024
  }
@@ -833,10 +1029,15 @@ var StorageBucket = class {
833
1029
  */
834
1030
  async remove(paths) {
835
1031
  try {
1032
+ const removedFiles = [];
836
1033
  for (const path of paths) {
837
1034
  await this.fetch.delete(`/api/v1/storage/${this.bucketName}/${path}`);
1035
+ removedFiles.push({
1036
+ name: path,
1037
+ bucket_id: this.bucketName
1038
+ });
838
1039
  }
839
- return { data: null, error: null };
1040
+ return { data: removedFiles, error: null };
840
1041
  } catch (error) {
841
1042
  return { data: null, error };
842
1043
  }
@@ -873,14 +1074,17 @@ var StorageBucket = class {
873
1074
  */
874
1075
  async move(fromPath, toPath) {
875
1076
  try {
876
- const data = await this.fetch.post(
1077
+ await this.fetch.post(
877
1078
  `/api/v1/storage/${this.bucketName}/move`,
878
1079
  {
879
1080
  from_path: fromPath,
880
1081
  to_path: toPath
881
1082
  }
882
1083
  );
883
- return { data, error: null };
1084
+ return {
1085
+ data: { message: "Successfully moved" },
1086
+ error: null
1087
+ };
884
1088
  } catch (error) {
885
1089
  return { data: null, error };
886
1090
  }
@@ -892,14 +1096,65 @@ var StorageBucket = class {
892
1096
  */
893
1097
  async copy(fromPath, toPath) {
894
1098
  try {
895
- const data = await this.fetch.post(
1099
+ await this.fetch.post(
896
1100
  `/api/v1/storage/${this.bucketName}/copy`,
897
1101
  {
898
1102
  from_path: fromPath,
899
1103
  to_path: toPath
900
1104
  }
901
1105
  );
902
- return { data, error: null };
1106
+ return {
1107
+ data: { path: toPath },
1108
+ error: null
1109
+ };
1110
+ } catch (error) {
1111
+ return { data: null, error };
1112
+ }
1113
+ }
1114
+ /**
1115
+ * Share a file with another user (RLS)
1116
+ * @param path - The file path
1117
+ * @param options - Share options (userId and permission)
1118
+ */
1119
+ async share(path, options) {
1120
+ try {
1121
+ await this.fetch.post(
1122
+ `/api/v1/storage/${this.bucketName}/${path}/share`,
1123
+ {
1124
+ user_id: options.userId,
1125
+ permission: options.permission
1126
+ }
1127
+ );
1128
+ return { data: null, error: null };
1129
+ } catch (error) {
1130
+ return { data: null, error };
1131
+ }
1132
+ }
1133
+ /**
1134
+ * Revoke file access from a user (RLS)
1135
+ * @param path - The file path
1136
+ * @param userId - The user ID to revoke access from
1137
+ */
1138
+ async revokeShare(path, userId) {
1139
+ try {
1140
+ await this.fetch.delete(
1141
+ `/api/v1/storage/${this.bucketName}/${path}/share/${userId}`
1142
+ );
1143
+ return { data: null, error: null };
1144
+ } catch (error) {
1145
+ return { data: null, error };
1146
+ }
1147
+ }
1148
+ /**
1149
+ * List users a file is shared with (RLS)
1150
+ * @param path - The file path
1151
+ */
1152
+ async listShares(path) {
1153
+ try {
1154
+ const data = await this.fetch.get(
1155
+ `/api/v1/storage/${this.bucketName}/${path}/shares`
1156
+ );
1157
+ return { data: data.shares || [], error: null };
903
1158
  } catch (error) {
904
1159
  return { data: null, error };
905
1160
  }
@@ -921,9 +1176,7 @@ var FluxbaseStorage = class {
921
1176
  */
922
1177
  async listBuckets() {
923
1178
  try {
924
- const data = await this.fetch.get(
925
- "/api/v1/storage/buckets"
926
- );
1179
+ const data = await this.fetch.get("/api/v1/storage/buckets");
927
1180
  return { data: data.buckets || [], error: null };
928
1181
  } catch (error) {
929
1182
  return { data: null, error };
@@ -936,7 +1189,7 @@ var FluxbaseStorage = class {
936
1189
  async createBucket(bucketName) {
937
1190
  try {
938
1191
  await this.fetch.post(`/api/v1/storage/buckets/${bucketName}`);
939
- return { data: null, error: null };
1192
+ return { data: { name: bucketName }, error: null };
940
1193
  } catch (error) {
941
1194
  return { data: null, error };
942
1195
  }
@@ -948,7 +1201,7 @@ var FluxbaseStorage = class {
948
1201
  async deleteBucket(bucketName) {
949
1202
  try {
950
1203
  await this.fetch.delete(`/api/v1/storage/buckets/${bucketName}`);
951
- return { data: null, error: null };
1204
+ return { data: { message: "Successfully deleted" }, error: null };
952
1205
  } catch (error) {
953
1206
  return { data: null, error };
954
1207
  }
@@ -965,250 +1218,931 @@ var FluxbaseStorage = class {
965
1218
  return { data: null, error: listError };
966
1219
  }
967
1220
  if (objects && objects.length > 0) {
968
- const paths = objects.map((obj) => obj.key);
1221
+ const paths = objects.map((obj) => obj.name);
969
1222
  const { error: removeError } = await bucket.remove(paths);
970
1223
  if (removeError) {
971
1224
  return { data: null, error: removeError };
972
1225
  }
973
1226
  }
1227
+ return { data: { message: "Successfully emptied" }, error: null };
1228
+ } catch (error) {
1229
+ return { data: null, error };
1230
+ }
1231
+ }
1232
+ /**
1233
+ * Update bucket settings (RLS - requires admin or service key)
1234
+ * @param bucketName - The name of the bucket
1235
+ * @param settings - Bucket settings to update
1236
+ */
1237
+ async updateBucketSettings(bucketName, settings) {
1238
+ try {
1239
+ await this.fetch.put(`/api/v1/storage/buckets/${bucketName}`, settings);
974
1240
  return { data: null, error: null };
975
1241
  } catch (error) {
976
1242
  return { data: null, error };
977
1243
  }
978
1244
  }
1245
+ /**
1246
+ * Get bucket details
1247
+ * @param bucketName - The name of the bucket
1248
+ */
1249
+ async getBucket(bucketName) {
1250
+ try {
1251
+ const data = await this.fetch.get(
1252
+ `/api/v1/storage/buckets/${bucketName}`
1253
+ );
1254
+ return { data, error: null };
1255
+ } catch (error) {
1256
+ return { data: null, error };
1257
+ }
1258
+ }
979
1259
  };
980
1260
 
981
- // src/settings.ts
982
- var SystemSettingsManager = class {
1261
+ // src/functions.ts
1262
+ var FluxbaseFunctions = class {
983
1263
  constructor(fetch2) {
984
1264
  this.fetch = fetch2;
985
1265
  }
986
1266
  /**
987
- * List all system settings
1267
+ * Invoke an edge function
1268
+ *
1269
+ * This method is fully compatible with Supabase's functions.invoke() API.
1270
+ *
1271
+ * @param functionName - The name of the function to invoke
1272
+ * @param options - Invocation options including body, headers, and HTTP method
1273
+ * @returns Promise resolving to { data, error } tuple
1274
+ *
1275
+ * @example
1276
+ * ```typescript
1277
+ * // Simple invocation
1278
+ * const { data, error } = await client.functions.invoke('hello', {
1279
+ * body: { name: 'World' }
1280
+ * })
1281
+ *
1282
+ * // With GET method
1283
+ * const { data, error } = await client.functions.invoke('get-data', {
1284
+ * method: 'GET'
1285
+ * })
1286
+ *
1287
+ * // With custom headers
1288
+ * const { data, error } = await client.functions.invoke('api-proxy', {
1289
+ * body: { query: 'search' },
1290
+ * headers: { 'Authorization': 'Bearer token' },
1291
+ * method: 'POST'
1292
+ * })
1293
+ * ```
1294
+ */
1295
+ async invoke(functionName, options) {
1296
+ try {
1297
+ const method = options?.method || "POST";
1298
+ const headers = options?.headers || {};
1299
+ const body = options?.body;
1300
+ const endpoint = `/api/v1/functions/${functionName}/invoke`;
1301
+ let response;
1302
+ switch (method) {
1303
+ case "GET":
1304
+ response = await this.fetch.get(endpoint, { headers });
1305
+ break;
1306
+ case "DELETE":
1307
+ response = await this.fetch.delete(endpoint, { headers });
1308
+ break;
1309
+ case "PUT":
1310
+ response = await this.fetch.put(endpoint, body, { headers });
1311
+ break;
1312
+ case "PATCH":
1313
+ response = await this.fetch.patch(endpoint, body, { headers });
1314
+ break;
1315
+ case "POST":
1316
+ default:
1317
+ response = await this.fetch.post(endpoint, body, { headers });
1318
+ break;
1319
+ }
1320
+ return { data: response, error: null };
1321
+ } catch (error) {
1322
+ return { data: null, error };
1323
+ }
1324
+ }
1325
+ /**
1326
+ * Create a new edge function
1327
+ *
1328
+ * @param request - Function configuration and code
1329
+ * @returns Promise resolving to { data, error } tuple with created function metadata
1330
+ *
1331
+ * @example
1332
+ * ```typescript
1333
+ * const { data, error } = await client.functions.create({
1334
+ * name: 'my-function',
1335
+ * code: 'export default async function handler(req) { return { hello: "world" } }',
1336
+ * enabled: true
1337
+ * })
1338
+ * ```
1339
+ */
1340
+ async create(request) {
1341
+ try {
1342
+ const data = await this.fetch.post("/api/v1/functions", request);
1343
+ return { data, error: null };
1344
+ } catch (error) {
1345
+ return { data: null, error };
1346
+ }
1347
+ }
1348
+ /**
1349
+ * List all edge functions
1350
+ *
1351
+ * @returns Promise resolving to { data, error } tuple with array of functions
1352
+ *
1353
+ * @example
1354
+ * ```typescript
1355
+ * const { data, error } = await client.functions.list()
1356
+ * if (data) {
1357
+ * console.log('Functions:', data.map(f => f.name))
1358
+ * }
1359
+ * ```
1360
+ */
1361
+ async list() {
1362
+ try {
1363
+ const data = await this.fetch.get("/api/v1/functions");
1364
+ return { data, error: null };
1365
+ } catch (error) {
1366
+ return { data: null, error };
1367
+ }
1368
+ }
1369
+ /**
1370
+ * Get details of a specific edge function
1371
+ *
1372
+ * @param name - Function name
1373
+ * @returns Promise resolving to { data, error } tuple with function metadata
1374
+ *
1375
+ * @example
1376
+ * ```typescript
1377
+ * const { data, error } = await client.functions.get('my-function')
1378
+ * if (data) {
1379
+ * console.log('Function version:', data.version)
1380
+ * }
1381
+ * ```
1382
+ */
1383
+ async get(name) {
1384
+ try {
1385
+ const data = await this.fetch.get(`/api/v1/functions/${name}`);
1386
+ return { data, error: null };
1387
+ } catch (error) {
1388
+ return { data: null, error };
1389
+ }
1390
+ }
1391
+ /**
1392
+ * Update an existing edge function
1393
+ *
1394
+ * @param name - Function name
1395
+ * @param updates - Fields to update
1396
+ * @returns Promise resolving to { data, error } tuple with updated function metadata
1397
+ *
1398
+ * @example
1399
+ * ```typescript
1400
+ * const { data, error } = await client.functions.update('my-function', {
1401
+ * enabled: false,
1402
+ * description: 'Updated description'
1403
+ * })
1404
+ * ```
1405
+ */
1406
+ async update(name, updates) {
1407
+ try {
1408
+ const data = await this.fetch.put(`/api/v1/functions/${name}`, updates);
1409
+ return { data, error: null };
1410
+ } catch (error) {
1411
+ return { data: null, error };
1412
+ }
1413
+ }
1414
+ /**
1415
+ * Delete an edge function
1416
+ *
1417
+ * @param name - Function name
1418
+ * @returns Promise resolving to { data, error } tuple
1419
+ *
1420
+ * @example
1421
+ * ```typescript
1422
+ * const { data, error } = await client.functions.delete('my-function')
1423
+ * ```
1424
+ */
1425
+ async delete(name) {
1426
+ try {
1427
+ await this.fetch.delete(`/api/v1/functions/${name}`);
1428
+ return { data: null, error: null };
1429
+ } catch (error) {
1430
+ return { data: null, error };
1431
+ }
1432
+ }
1433
+ /**
1434
+ * Get execution history for an edge function
1435
+ *
1436
+ * @param name - Function name
1437
+ * @param limit - Maximum number of executions to return (optional)
1438
+ * @returns Promise resolving to { data, error } tuple with execution records
1439
+ *
1440
+ * @example
1441
+ * ```typescript
1442
+ * const { data, error } = await client.functions.getExecutions('my-function', 10)
1443
+ * if (data) {
1444
+ * data.forEach(exec => {
1445
+ * console.log(`${exec.executed_at}: ${exec.status} (${exec.duration_ms}ms)`)
1446
+ * })
1447
+ * }
1448
+ * ```
1449
+ */
1450
+ async getExecutions(name, limit) {
1451
+ try {
1452
+ const params = limit ? `?limit=${limit}` : "";
1453
+ const data = await this.fetch.get(
1454
+ `/api/v1/functions/${name}/executions${params}`
1455
+ );
1456
+ return { data, error: null };
1457
+ } catch (error) {
1458
+ return { data: null, error };
1459
+ }
1460
+ }
1461
+ };
1462
+
1463
+ // src/settings.ts
1464
+ var SystemSettingsManager = class {
1465
+ constructor(fetch2) {
1466
+ this.fetch = fetch2;
1467
+ }
1468
+ /**
1469
+ * List all system settings
1470
+ *
1471
+ * @returns Promise resolving to ListSystemSettingsResponse
1472
+ *
1473
+ * @example
1474
+ * ```typescript
1475
+ * const response = await client.admin.settings.system.list()
1476
+ * console.log(response.settings)
1477
+ * ```
1478
+ */
1479
+ async list() {
1480
+ const settings = await this.fetch.get(
1481
+ "/api/v1/admin/system/settings"
1482
+ );
1483
+ return { settings: Array.isArray(settings) ? settings : [] };
1484
+ }
1485
+ /**
1486
+ * Get a specific system setting by key
1487
+ *
1488
+ * @param key - Setting key (e.g., 'app.auth.enable_signup')
1489
+ * @returns Promise resolving to SystemSetting
1490
+ *
1491
+ * @example
1492
+ * ```typescript
1493
+ * const setting = await client.admin.settings.system.get('app.auth.enable_signup')
1494
+ * console.log(setting.value)
1495
+ * ```
1496
+ */
1497
+ async get(key) {
1498
+ return await this.fetch.get(
1499
+ `/api/v1/admin/system/settings/${key}`
1500
+ );
1501
+ }
1502
+ /**
1503
+ * Update or create a system setting
1504
+ *
1505
+ * @param key - Setting key
1506
+ * @param request - Update request with value and optional description
1507
+ * @returns Promise resolving to SystemSetting
1508
+ *
1509
+ * @example
1510
+ * ```typescript
1511
+ * const updated = await client.admin.settings.system.update('app.auth.enable_signup', {
1512
+ * value: { value: true },
1513
+ * description: 'Enable user signup'
1514
+ * })
1515
+ * ```
1516
+ */
1517
+ async update(key, request) {
1518
+ return await this.fetch.put(
1519
+ `/api/v1/admin/system/settings/${key}`,
1520
+ request
1521
+ );
1522
+ }
1523
+ /**
1524
+ * Delete a system setting
1525
+ *
1526
+ * @param key - Setting key to delete
1527
+ * @returns Promise<void>
1528
+ *
1529
+ * @example
1530
+ * ```typescript
1531
+ * await client.admin.settings.system.delete('app.auth.enable_signup')
1532
+ * ```
1533
+ */
1534
+ async delete(key) {
1535
+ await this.fetch.delete(`/api/v1/admin/system/settings/${key}`);
1536
+ }
1537
+ };
1538
+ var AppSettingsManager = class {
1539
+ constructor(fetch2) {
1540
+ this.fetch = fetch2;
1541
+ }
1542
+ /**
1543
+ * Get all application settings
1544
+ *
1545
+ * Returns structured settings for authentication, features, email, and security.
1546
+ *
1547
+ * @returns Promise resolving to AppSettings
1548
+ *
1549
+ * @example
1550
+ * ```typescript
1551
+ * const settings = await client.admin.settings.app.get()
1552
+ *
1553
+ * console.log('Signup enabled:', settings.authentication.enable_signup)
1554
+ * console.log('Realtime enabled:', settings.features.enable_realtime)
1555
+ * console.log('Email provider:', settings.email.provider)
1556
+ * ```
1557
+ */
1558
+ async get() {
1559
+ return await this.fetch.get("/api/v1/admin/app/settings");
1560
+ }
1561
+ /**
1562
+ * Update application settings
1563
+ *
1564
+ * Supports partial updates - only provide the fields you want to change.
1565
+ *
1566
+ * @param request - Settings to update (partial update supported)
1567
+ * @returns Promise resolving to AppSettings - Updated settings
1568
+ *
1569
+ * @example
1570
+ * ```typescript
1571
+ * // Update authentication settings
1572
+ * const updated = await client.admin.settings.app.update({
1573
+ * authentication: {
1574
+ * enable_signup: true,
1575
+ * password_min_length: 12
1576
+ * }
1577
+ * })
1578
+ *
1579
+ * // Update multiple categories
1580
+ * await client.admin.settings.app.update({
1581
+ * authentication: { enable_signup: false },
1582
+ * features: { enable_realtime: true },
1583
+ * security: { enable_global_rate_limit: true }
1584
+ * })
1585
+ * ```
1586
+ */
1587
+ async update(request) {
1588
+ return await this.fetch.put(
1589
+ "/api/v1/admin/app/settings",
1590
+ request
1591
+ );
1592
+ }
1593
+ /**
1594
+ * Reset all application settings to defaults
1595
+ *
1596
+ * This will delete all custom settings and return to default values.
1597
+ *
1598
+ * @returns Promise resolving to AppSettings - Default settings
1599
+ *
1600
+ * @example
1601
+ * ```typescript
1602
+ * const defaults = await client.admin.settings.app.reset()
1603
+ * console.log('Settings reset to defaults:', defaults)
1604
+ * ```
1605
+ */
1606
+ async reset() {
1607
+ return await this.fetch.post(
1608
+ "/api/v1/admin/app/settings/reset",
1609
+ {}
1610
+ );
1611
+ }
1612
+ /**
1613
+ * Enable user signup
1614
+ *
1615
+ * Convenience method to enable user registration.
1616
+ *
1617
+ * @returns Promise resolving to AppSettings
1618
+ *
1619
+ * @example
1620
+ * ```typescript
1621
+ * await client.admin.settings.app.enableSignup()
1622
+ * ```
1623
+ */
1624
+ async enableSignup() {
1625
+ return await this.update({
1626
+ authentication: { enable_signup: true }
1627
+ });
1628
+ }
1629
+ /**
1630
+ * Disable user signup
1631
+ *
1632
+ * Convenience method to disable user registration.
1633
+ *
1634
+ * @returns Promise resolving to AppSettings
1635
+ *
1636
+ * @example
1637
+ * ```typescript
1638
+ * await client.admin.settings.app.disableSignup()
1639
+ * ```
1640
+ */
1641
+ async disableSignup() {
1642
+ return await this.update({
1643
+ authentication: { enable_signup: false }
1644
+ });
1645
+ }
1646
+ /**
1647
+ * Update password minimum length
1648
+ *
1649
+ * Convenience method to set password requirements.
1650
+ *
1651
+ * @param length - Minimum password length (8-128 characters)
1652
+ * @returns Promise resolving to AppSettings
1653
+ *
1654
+ * @example
1655
+ * ```typescript
1656
+ * await client.admin.settings.app.setPasswordMinLength(12)
1657
+ * ```
1658
+ */
1659
+ async setPasswordMinLength(length) {
1660
+ if (length < 8 || length > 128) {
1661
+ throw new Error(
1662
+ "Password minimum length must be between 8 and 128 characters"
1663
+ );
1664
+ }
1665
+ return await this.update({
1666
+ authentication: { password_min_length: length }
1667
+ });
1668
+ }
1669
+ /**
1670
+ * Enable or disable a feature
1671
+ *
1672
+ * Convenience method to toggle feature flags.
1673
+ *
1674
+ * @param feature - Feature name ('realtime' | 'storage' | 'functions')
1675
+ * @param enabled - Whether to enable or disable the feature
1676
+ * @returns Promise resolving to AppSettings
1677
+ *
1678
+ * @example
1679
+ * ```typescript
1680
+ * // Enable realtime
1681
+ * await client.admin.settings.app.setFeature('realtime', true)
1682
+ *
1683
+ * // Disable storage
1684
+ * await client.admin.settings.app.setFeature('storage', false)
1685
+ * ```
1686
+ */
1687
+ async setFeature(feature, enabled) {
1688
+ const featureKey = feature === "realtime" ? "enable_realtime" : feature === "storage" ? "enable_storage" : "enable_functions";
1689
+ return await this.update({
1690
+ features: { [featureKey]: enabled }
1691
+ });
1692
+ }
1693
+ /**
1694
+ * Enable or disable global rate limiting
1695
+ *
1696
+ * Convenience method to toggle global rate limiting.
1697
+ *
1698
+ * @param enabled - Whether to enable rate limiting
1699
+ * @returns Promise resolving to AppSettings
1700
+ *
1701
+ * @example
1702
+ * ```typescript
1703
+ * await client.admin.settings.app.setRateLimiting(true)
1704
+ * ```
1705
+ */
1706
+ async setRateLimiting(enabled) {
1707
+ return await this.update({
1708
+ security: { enable_global_rate_limit: enabled }
1709
+ });
1710
+ }
1711
+ /**
1712
+ * Configure SMTP email provider
1713
+ *
1714
+ * Convenience method to set up SMTP email delivery.
1715
+ *
1716
+ * @param config - SMTP configuration
1717
+ * @returns Promise resolving to AppSettings
1718
+ *
1719
+ * @example
1720
+ * ```typescript
1721
+ * await client.admin.settings.app.configureSMTP({
1722
+ * host: 'smtp.gmail.com',
1723
+ * port: 587,
1724
+ * username: 'your-email@gmail.com',
1725
+ * password: 'your-app-password',
1726
+ * use_tls: true,
1727
+ * from_address: 'noreply@yourapp.com',
1728
+ * from_name: 'Your App'
1729
+ * })
1730
+ * ```
1731
+ */
1732
+ async configureSMTP(config) {
1733
+ return await this.update({
1734
+ email: {
1735
+ enabled: true,
1736
+ provider: "smtp",
1737
+ from_address: config.from_address,
1738
+ from_name: config.from_name,
1739
+ reply_to_address: config.reply_to_address,
1740
+ smtp: {
1741
+ host: config.host,
1742
+ port: config.port,
1743
+ username: config.username,
1744
+ password: config.password,
1745
+ use_tls: config.use_tls
1746
+ }
1747
+ }
1748
+ });
1749
+ }
1750
+ /**
1751
+ * Configure SendGrid email provider
1752
+ *
1753
+ * Convenience method to set up SendGrid email delivery.
1754
+ *
1755
+ * @param apiKey - SendGrid API key
1756
+ * @param options - Optional from address, name, and reply-to
1757
+ * @returns Promise resolving to AppSettings
1758
+ *
1759
+ * @example
1760
+ * ```typescript
1761
+ * await client.admin.settings.app.configureSendGrid('SG.xxx', {
1762
+ * from_address: 'noreply@yourapp.com',
1763
+ * from_name: 'Your App'
1764
+ * })
1765
+ * ```
1766
+ */
1767
+ async configureSendGrid(apiKey, options) {
1768
+ return await this.update({
1769
+ email: {
1770
+ enabled: true,
1771
+ provider: "sendgrid",
1772
+ from_address: options?.from_address,
1773
+ from_name: options?.from_name,
1774
+ reply_to_address: options?.reply_to_address,
1775
+ sendgrid: {
1776
+ api_key: apiKey
1777
+ }
1778
+ }
1779
+ });
1780
+ }
1781
+ /**
1782
+ * Configure Mailgun email provider
1783
+ *
1784
+ * Convenience method to set up Mailgun email delivery.
1785
+ *
1786
+ * @param apiKey - Mailgun API key
1787
+ * @param domain - Mailgun domain
1788
+ * @param options - Optional EU region flag and email addresses
1789
+ * @returns Promise resolving to AppSettings
1790
+ *
1791
+ * @example
1792
+ * ```typescript
1793
+ * await client.admin.settings.app.configureMailgun('key-xxx', 'mg.yourapp.com', {
1794
+ * eu_region: false,
1795
+ * from_address: 'noreply@yourapp.com',
1796
+ * from_name: 'Your App'
1797
+ * })
1798
+ * ```
1799
+ */
1800
+ async configureMailgun(apiKey, domain, options) {
1801
+ return await this.update({
1802
+ email: {
1803
+ enabled: true,
1804
+ provider: "mailgun",
1805
+ from_address: options?.from_address,
1806
+ from_name: options?.from_name,
1807
+ reply_to_address: options?.reply_to_address,
1808
+ mailgun: {
1809
+ api_key: apiKey,
1810
+ domain,
1811
+ eu_region: options?.eu_region ?? false
1812
+ }
1813
+ }
1814
+ });
1815
+ }
1816
+ /**
1817
+ * Configure AWS SES email provider
1818
+ *
1819
+ * Convenience method to set up AWS SES email delivery.
1820
+ *
1821
+ * @param accessKeyId - AWS access key ID
1822
+ * @param secretAccessKey - AWS secret access key
1823
+ * @param region - AWS region (e.g., 'us-east-1')
1824
+ * @param options - Optional email addresses
1825
+ * @returns Promise resolving to AppSettings
1826
+ *
1827
+ * @example
1828
+ * ```typescript
1829
+ * await client.admin.settings.app.configureSES(
1830
+ * 'AKIAIOSFODNN7EXAMPLE',
1831
+ * 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
1832
+ * 'us-east-1',
1833
+ * {
1834
+ * from_address: 'noreply@yourapp.com',
1835
+ * from_name: 'Your App'
1836
+ * }
1837
+ * )
1838
+ * ```
1839
+ */
1840
+ async configureSES(accessKeyId, secretAccessKey, region, options) {
1841
+ return await this.update({
1842
+ email: {
1843
+ enabled: true,
1844
+ provider: "ses",
1845
+ from_address: options?.from_address,
1846
+ from_name: options?.from_name,
1847
+ reply_to_address: options?.reply_to_address,
1848
+ ses: {
1849
+ access_key_id: accessKeyId,
1850
+ secret_access_key: secretAccessKey,
1851
+ region
1852
+ }
1853
+ }
1854
+ });
1855
+ }
1856
+ /**
1857
+ * Enable or disable email functionality
988
1858
  *
989
- * @returns Promise resolving to ListSystemSettingsResponse
1859
+ * Convenience method to toggle email system on/off.
1860
+ *
1861
+ * @param enabled - Whether to enable email
1862
+ * @returns Promise resolving to AppSettings
990
1863
  *
991
1864
  * @example
992
1865
  * ```typescript
993
- * const response = await client.admin.settings.system.list()
994
- * console.log(response.settings)
1866
+ * await client.admin.settings.app.setEmailEnabled(true)
995
1867
  * ```
996
1868
  */
997
- async list() {
998
- const settings = await this.fetch.get("/api/v1/admin/system/settings");
999
- return { settings: Array.isArray(settings) ? settings : [] };
1869
+ async setEmailEnabled(enabled) {
1870
+ return await this.update({
1871
+ email: { enabled }
1872
+ });
1000
1873
  }
1001
1874
  /**
1002
- * Get a specific system setting by key
1875
+ * Configure password complexity requirements
1003
1876
  *
1004
- * @param key - Setting key (e.g., 'app.auth.enable_signup')
1005
- * @returns Promise resolving to SystemSetting
1877
+ * Convenience method to set password validation rules.
1878
+ *
1879
+ * @param requirements - Password complexity requirements
1880
+ * @returns Promise resolving to AppSettings
1006
1881
  *
1007
1882
  * @example
1008
1883
  * ```typescript
1009
- * const setting = await client.admin.settings.system.get('app.auth.enable_signup')
1010
- * console.log(setting.value)
1884
+ * await client.admin.settings.app.setPasswordComplexity({
1885
+ * min_length: 12,
1886
+ * require_uppercase: true,
1887
+ * require_lowercase: true,
1888
+ * require_number: true,
1889
+ * require_special: true
1890
+ * })
1011
1891
  * ```
1012
1892
  */
1013
- async get(key) {
1014
- return await this.fetch.get(`/api/v1/admin/system/settings/${key}`);
1893
+ async setPasswordComplexity(requirements) {
1894
+ return await this.update({
1895
+ authentication: {
1896
+ password_min_length: requirements.min_length,
1897
+ password_require_uppercase: requirements.require_uppercase,
1898
+ password_require_lowercase: requirements.require_lowercase,
1899
+ password_require_number: requirements.require_number,
1900
+ password_require_special: requirements.require_special
1901
+ }
1902
+ });
1015
1903
  }
1016
1904
  /**
1017
- * Update or create a system setting
1905
+ * Configure session settings
1018
1906
  *
1019
- * @param key - Setting key
1020
- * @param request - Update request with value and optional description
1021
- * @returns Promise resolving to SystemSetting
1907
+ * Convenience method to set session timeout and limits.
1908
+ *
1909
+ * @param timeoutMinutes - Session timeout in minutes (0 for no timeout)
1910
+ * @param maxSessionsPerUser - Maximum concurrent sessions per user (0 for unlimited)
1911
+ * @returns Promise resolving to AppSettings
1022
1912
  *
1023
1913
  * @example
1024
1914
  * ```typescript
1025
- * const updated = await client.admin.settings.system.update('app.auth.enable_signup', {
1026
- * value: { value: true },
1027
- * description: 'Enable user signup'
1028
- * })
1915
+ * // 30 minute sessions, max 3 devices per user
1916
+ * await client.admin.settings.app.setSessionSettings(30, 3)
1029
1917
  * ```
1030
1918
  */
1031
- async update(key, request) {
1032
- return await this.fetch.put(`/api/v1/admin/system/settings/${key}`, request);
1919
+ async setSessionSettings(timeoutMinutes, maxSessionsPerUser) {
1920
+ return await this.update({
1921
+ authentication: {
1922
+ session_timeout_minutes: timeoutMinutes,
1923
+ max_sessions_per_user: maxSessionsPerUser
1924
+ }
1925
+ });
1033
1926
  }
1034
1927
  /**
1035
- * Delete a system setting
1928
+ * Enable or disable email verification requirement
1036
1929
  *
1037
- * @param key - Setting key to delete
1038
- * @returns Promise<void>
1930
+ * Convenience method to require email verification for new signups.
1931
+ *
1932
+ * @param required - Whether to require email verification
1933
+ * @returns Promise resolving to AppSettings
1039
1934
  *
1040
1935
  * @example
1041
1936
  * ```typescript
1042
- * await client.admin.settings.system.delete('app.auth.enable_signup')
1937
+ * await client.admin.settings.app.setEmailVerificationRequired(true)
1043
1938
  * ```
1044
1939
  */
1045
- async delete(key) {
1046
- await this.fetch.delete(`/api/v1/admin/system/settings/${key}`);
1940
+ async setEmailVerificationRequired(required) {
1941
+ return await this.update({
1942
+ authentication: { require_email_verification: required }
1943
+ });
1047
1944
  }
1048
1945
  };
1049
- var AppSettingsManager = class {
1946
+ var CustomSettingsManager = class {
1050
1947
  constructor(fetch2) {
1051
1948
  this.fetch = fetch2;
1052
1949
  }
1053
1950
  /**
1054
- * Get all application settings
1055
- *
1056
- * Returns structured settings for authentication, features, email, and security.
1951
+ * Create a new custom setting
1057
1952
  *
1058
- * @returns Promise resolving to AppSettings
1953
+ * @param request - Custom setting creation request
1954
+ * @returns Promise resolving to CustomSetting
1059
1955
  *
1060
1956
  * @example
1061
1957
  * ```typescript
1062
- * const settings = await client.admin.settings.app.get()
1063
- *
1064
- * console.log('Signup enabled:', settings.authentication.enable_signup)
1065
- * console.log('Realtime enabled:', settings.features.enable_realtime)
1066
- * console.log('Email provider:', settings.email.provider)
1958
+ * const setting = await client.admin.settings.custom.create({
1959
+ * key: 'api.quotas',
1960
+ * value: { free: 1000, pro: 10000, enterprise: 100000 },
1961
+ * value_type: 'json',
1962
+ * description: 'API request quotas by tier',
1963
+ * metadata: { category: 'billing' }
1964
+ * })
1067
1965
  * ```
1068
1966
  */
1069
- async get() {
1070
- return await this.fetch.get("/api/v1/admin/app/settings");
1967
+ async create(request) {
1968
+ return await this.fetch.post(
1969
+ "/api/v1/admin/settings/custom",
1970
+ request
1971
+ );
1071
1972
  }
1072
1973
  /**
1073
- * Update application settings
1974
+ * List all custom settings
1074
1975
  *
1075
- * Supports partial updates - only provide the fields you want to change.
1976
+ * @returns Promise resolving to ListCustomSettingsResponse
1076
1977
  *
1077
- * @param request - Settings to update (partial update supported)
1078
- * @returns Promise resolving to AppSettings - Updated settings
1978
+ * @example
1979
+ * ```typescript
1980
+ * const response = await client.admin.settings.custom.list()
1981
+ * console.log(response.settings)
1982
+ * ```
1983
+ */
1984
+ async list() {
1985
+ const settings = await this.fetch.get(
1986
+ "/api/v1/admin/settings/custom"
1987
+ );
1988
+ return { settings: Array.isArray(settings) ? settings : [] };
1989
+ }
1990
+ /**
1991
+ * Get a specific custom setting by key
1992
+ *
1993
+ * @param key - Setting key (e.g., 'feature.dark_mode')
1994
+ * @returns Promise resolving to CustomSetting
1079
1995
  *
1080
1996
  * @example
1081
1997
  * ```typescript
1082
- * // Update authentication settings
1083
- * const updated = await client.admin.settings.app.update({
1084
- * authentication: {
1085
- * enable_signup: true,
1086
- * password_min_length: 12
1087
- * }
1088
- * })
1998
+ * const setting = await client.admin.settings.custom.get('feature.dark_mode')
1999
+ * console.log(setting.value)
2000
+ * ```
2001
+ */
2002
+ async get(key) {
2003
+ return await this.fetch.get(
2004
+ `/api/v1/admin/settings/custom/${key}`
2005
+ );
2006
+ }
2007
+ /**
2008
+ * Update an existing custom setting
1089
2009
  *
1090
- * // Update multiple categories
1091
- * await client.admin.settings.app.update({
1092
- * authentication: { enable_signup: false },
1093
- * features: { enable_realtime: true },
1094
- * security: { enable_global_rate_limit: true }
2010
+ * @param key - Setting key
2011
+ * @param request - Update request with new values
2012
+ * @returns Promise resolving to CustomSetting
2013
+ *
2014
+ * @example
2015
+ * ```typescript
2016
+ * const updated = await client.admin.settings.custom.update('feature.dark_mode', {
2017
+ * value: { enabled: false },
2018
+ * description: 'Updated description'
1095
2019
  * })
1096
2020
  * ```
1097
2021
  */
1098
- async update(request) {
1099
- return await this.fetch.put("/api/v1/admin/app/settings", request);
2022
+ async update(key, request) {
2023
+ return await this.fetch.put(
2024
+ `/api/v1/admin/settings/custom/${key}`,
2025
+ request
2026
+ );
1100
2027
  }
1101
2028
  /**
1102
- * Reset all application settings to defaults
1103
- *
1104
- * This will delete all custom settings and return to default values.
2029
+ * Delete a custom setting
1105
2030
  *
1106
- * @returns Promise resolving to AppSettings - Default settings
2031
+ * @param key - Setting key to delete
2032
+ * @returns Promise<void>
1107
2033
  *
1108
2034
  * @example
1109
2035
  * ```typescript
1110
- * const defaults = await client.admin.settings.app.reset()
1111
- * console.log('Settings reset to defaults:', defaults)
2036
+ * await client.admin.settings.custom.delete('feature.dark_mode')
1112
2037
  * ```
1113
2038
  */
1114
- async reset() {
1115
- return await this.fetch.post("/api/v1/admin/app/settings/reset", {});
2039
+ async delete(key) {
2040
+ await this.fetch.delete(`/api/v1/admin/settings/custom/${key}`);
2041
+ }
2042
+ };
2043
+ var EmailTemplateManager = class {
2044
+ constructor(fetch2) {
2045
+ this.fetch = fetch2;
1116
2046
  }
1117
2047
  /**
1118
- * Enable user signup
1119
- *
1120
- * Convenience method to enable user registration.
2048
+ * List all email templates
1121
2049
  *
1122
- * @returns Promise resolving to AppSettings
2050
+ * @returns Promise resolving to ListEmailTemplatesResponse
1123
2051
  *
1124
2052
  * @example
1125
2053
  * ```typescript
1126
- * await client.admin.settings.app.enableSignup()
2054
+ * const response = await client.admin.emailTemplates.list()
2055
+ * console.log(response.templates)
1127
2056
  * ```
1128
2057
  */
1129
- async enableSignup() {
1130
- return await this.update({
1131
- authentication: { enable_signup: true }
1132
- });
2058
+ async list() {
2059
+ const templates = await this.fetch.get(
2060
+ "/api/v1/admin/email/templates"
2061
+ );
2062
+ return { templates: Array.isArray(templates) ? templates : [] };
1133
2063
  }
1134
2064
  /**
1135
- * Disable user signup
1136
- *
1137
- * Convenience method to disable user registration.
2065
+ * Get a specific email template by type
1138
2066
  *
1139
- * @returns Promise resolving to AppSettings
2067
+ * @param type - Template type (magic_link | verify_email | reset_password | invite_user)
2068
+ * @returns Promise resolving to EmailTemplate
1140
2069
  *
1141
2070
  * @example
1142
2071
  * ```typescript
1143
- * await client.admin.settings.app.disableSignup()
2072
+ * const template = await client.admin.emailTemplates.get('magic_link')
2073
+ * console.log(template.subject)
2074
+ * console.log(template.html_body)
1144
2075
  * ```
1145
2076
  */
1146
- async disableSignup() {
1147
- return await this.update({
1148
- authentication: { enable_signup: false }
1149
- });
2077
+ async get(type) {
2078
+ return await this.fetch.get(
2079
+ `/api/v1/admin/email/templates/${type}`
2080
+ );
1150
2081
  }
1151
2082
  /**
1152
- * Update password minimum length
2083
+ * Update an email template
1153
2084
  *
1154
- * Convenience method to set password requirements.
2085
+ * Available template variables:
2086
+ * - magic_link: `{{.MagicLink}}`, `{{.AppName}}`, `{{.ExpiryMinutes}}`
2087
+ * - verify_email: `{{.VerificationLink}}`, `{{.AppName}}`
2088
+ * - reset_password: `{{.ResetLink}}`, `{{.AppName}}`, `{{.ExpiryMinutes}}`
2089
+ * - invite_user: `{{.InviteLink}}`, `{{.AppName}}`, `{{.InviterName}}`
1155
2090
  *
1156
- * @param length - Minimum password length (8-128 characters)
1157
- * @returns Promise resolving to AppSettings
2091
+ * @param type - Template type to update
2092
+ * @param request - Update request with subject, html_body, and optional text_body
2093
+ * @returns Promise resolving to EmailTemplate
1158
2094
  *
1159
2095
  * @example
1160
2096
  * ```typescript
1161
- * await client.admin.settings.app.setPasswordMinLength(12)
2097
+ * const updated = await client.admin.emailTemplates.update('magic_link', {
2098
+ * subject: 'Your Magic Link - Sign in to ' + '{{.AppName}}',
2099
+ * html_body: '<html><body><h1>Welcome!</h1><a href="' + '{{.MagicLink}}' + '">Sign In</a></body></html>',
2100
+ * text_body: 'Click here to sign in: ' + '{{.MagicLink}}'
2101
+ * })
1162
2102
  * ```
1163
2103
  */
1164
- async setPasswordMinLength(length) {
1165
- if (length < 8 || length > 128) {
1166
- throw new Error("Password minimum length must be between 8 and 128 characters");
1167
- }
1168
- return await this.update({
1169
- authentication: { password_min_length: length }
1170
- });
2104
+ async update(type, request) {
2105
+ return await this.fetch.put(
2106
+ `/api/v1/admin/email/templates/${type}`,
2107
+ request
2108
+ );
1171
2109
  }
1172
2110
  /**
1173
- * Enable or disable a feature
2111
+ * Reset an email template to default
1174
2112
  *
1175
- * Convenience method to toggle feature flags.
2113
+ * Removes any customizations and restores the template to its original state.
1176
2114
  *
1177
- * @param feature - Feature name ('realtime' | 'storage' | 'functions')
1178
- * @param enabled - Whether to enable or disable the feature
1179
- * @returns Promise resolving to AppSettings
2115
+ * @param type - Template type to reset
2116
+ * @returns Promise resolving to EmailTemplate - The default template
1180
2117
  *
1181
2118
  * @example
1182
2119
  * ```typescript
1183
- * // Enable realtime
1184
- * await client.admin.settings.app.setFeature('realtime', true)
1185
- *
1186
- * // Disable storage
1187
- * await client.admin.settings.app.setFeature('storage', false)
2120
+ * const defaultTemplate = await client.admin.emailTemplates.reset('magic_link')
1188
2121
  * ```
1189
2122
  */
1190
- async setFeature(feature, enabled) {
1191
- const featureKey = feature === "realtime" ? "enable_realtime" : feature === "storage" ? "enable_storage" : "enable_functions";
1192
- return await this.update({
1193
- features: { [featureKey]: enabled }
1194
- });
2123
+ async reset(type) {
2124
+ return await this.fetch.post(
2125
+ `/api/v1/admin/email/templates/${type}/reset`,
2126
+ {}
2127
+ );
1195
2128
  }
1196
2129
  /**
1197
- * Enable or disable global rate limiting
2130
+ * Send a test email using the template
1198
2131
  *
1199
- * Convenience method to toggle global rate limiting.
2132
+ * Useful for previewing template changes before deploying to production.
1200
2133
  *
1201
- * @param enabled - Whether to enable rate limiting
1202
- * @returns Promise resolving to AppSettings
2134
+ * @param type - Template type to test
2135
+ * @param recipientEmail - Email address to send test to
2136
+ * @returns Promise<void>
1203
2137
  *
1204
2138
  * @example
1205
2139
  * ```typescript
1206
- * await client.admin.settings.app.setRateLimiting(true)
2140
+ * await client.admin.emailTemplates.test('magic_link', 'test@example.com')
1207
2141
  * ```
1208
2142
  */
1209
- async setRateLimiting(enabled) {
1210
- return await this.update({
1211
- security: { enable_global_rate_limit: enabled }
2143
+ async test(type, recipientEmail) {
2144
+ await this.fetch.post(`/api/v1/admin/email/templates/${type}/test`, {
2145
+ recipient_email: recipientEmail
1212
2146
  });
1213
2147
  }
1214
2148
  };
@@ -1216,6 +2150,7 @@ var FluxbaseSettings = class {
1216
2150
  constructor(fetch2) {
1217
2151
  this.system = new SystemSettingsManager(fetch2);
1218
2152
  this.app = new AppSettingsManager(fetch2);
2153
+ this.custom = new CustomSettingsManager(fetch2);
1219
2154
  }
1220
2155
  };
1221
2156
 
@@ -2238,6 +3173,7 @@ var FluxbaseAdmin = class {
2238
3173
  this.oauth = new FluxbaseOAuth(fetch2);
2239
3174
  this.impersonation = new ImpersonationManager(fetch2);
2240
3175
  this.management = new FluxbaseManagement(fetch2);
3176
+ this.emailTemplates = new EmailTemplateManager(fetch2);
2241
3177
  }
2242
3178
  /**
2243
3179
  * Set admin authentication token
@@ -2276,9 +3212,11 @@ var FluxbaseAdmin = class {
2276
3212
  * ```
2277
3213
  */
2278
3214
  async getSetupStatus() {
2279
- return await this.fetch.get(
2280
- "/api/v1/admin/setup/status"
2281
- );
3215
+ return wrapAsync(async () => {
3216
+ return await this.fetch.get(
3217
+ "/api/v1/admin/setup/status"
3218
+ );
3219
+ });
2282
3220
  }
2283
3221
  /**
2284
3222
  * Perform initial admin setup
@@ -2304,12 +3242,14 @@ var FluxbaseAdmin = class {
2304
3242
  * ```
2305
3243
  */
2306
3244
  async setup(request) {
2307
- const response = await this.fetch.post(
2308
- "/api/v1/admin/setup",
2309
- request
2310
- );
2311
- this.setToken(response.access_token);
2312
- return response;
3245
+ return wrapAsync(async () => {
3246
+ const response = await this.fetch.post(
3247
+ "/api/v1/admin/setup",
3248
+ request
3249
+ );
3250
+ this.setToken(response.access_token);
3251
+ return response;
3252
+ });
2313
3253
  }
2314
3254
  /**
2315
3255
  * Admin login
@@ -2332,12 +3272,14 @@ var FluxbaseAdmin = class {
2332
3272
  * ```
2333
3273
  */
2334
3274
  async login(request) {
2335
- const response = await this.fetch.post(
2336
- "/api/v1/admin/login",
2337
- request
2338
- );
2339
- this.setToken(response.access_token);
2340
- return response;
3275
+ return wrapAsync(async () => {
3276
+ const response = await this.fetch.post(
3277
+ "/api/v1/admin/login",
3278
+ request
3279
+ );
3280
+ this.setToken(response.access_token);
3281
+ return response;
3282
+ });
2341
3283
  }
2342
3284
  /**
2343
3285
  * Refresh admin access token
@@ -2356,12 +3298,14 @@ var FluxbaseAdmin = class {
2356
3298
  * ```
2357
3299
  */
2358
3300
  async refreshToken(request) {
2359
- const response = await this.fetch.post(
2360
- "/api/v1/admin/refresh",
2361
- request
2362
- );
2363
- this.setToken(response.access_token);
2364
- return response;
3301
+ return wrapAsync(async () => {
3302
+ const response = await this.fetch.post(
3303
+ "/api/v1/admin/refresh",
3304
+ request
3305
+ );
3306
+ this.setToken(response.access_token);
3307
+ return response;
3308
+ });
2365
3309
  }
2366
3310
  /**
2367
3311
  * Admin logout
@@ -2375,8 +3319,10 @@ var FluxbaseAdmin = class {
2375
3319
  * ```
2376
3320
  */
2377
3321
  async logout() {
2378
- await this.fetch.post("/api/v1/admin/logout", {});
2379
- this.clearToken();
3322
+ return wrapAsyncVoid(async () => {
3323
+ await this.fetch.post("/api/v1/admin/logout", {});
3324
+ this.clearToken();
3325
+ });
2380
3326
  }
2381
3327
  /**
2382
3328
  * Get current admin user information
@@ -2391,7 +3337,9 @@ var FluxbaseAdmin = class {
2391
3337
  * ```
2392
3338
  */
2393
3339
  async me() {
2394
- return await this.fetch.get("/api/v1/admin/me");
3340
+ return wrapAsync(async () => {
3341
+ return await this.fetch.get("/api/v1/admin/me");
3342
+ });
2395
3343
  }
2396
3344
  // ============================================================================
2397
3345
  // User Management
@@ -2417,22 +3365,24 @@ var FluxbaseAdmin = class {
2417
3365
  * ```
2418
3366
  */
2419
3367
  async listUsers(options = {}) {
2420
- const params = new URLSearchParams();
2421
- if (options.exclude_admins !== void 0) {
2422
- params.append("exclude_admins", String(options.exclude_admins));
2423
- }
2424
- if (options.search) {
2425
- params.append("search", options.search);
2426
- }
2427
- if (options.limit !== void 0) {
2428
- params.append("limit", String(options.limit));
2429
- }
2430
- if (options.type) {
2431
- params.append("type", options.type);
2432
- }
2433
- const queryString = params.toString();
2434
- const url = queryString ? `/api/v1/admin/users?${queryString}` : "/api/v1/admin/users";
2435
- return await this.fetch.get(url);
3368
+ return wrapAsync(async () => {
3369
+ const params = new URLSearchParams();
3370
+ if (options.exclude_admins !== void 0) {
3371
+ params.append("exclude_admins", String(options.exclude_admins));
3372
+ }
3373
+ if (options.search) {
3374
+ params.append("search", options.search);
3375
+ }
3376
+ if (options.limit !== void 0) {
3377
+ params.append("limit", String(options.limit));
3378
+ }
3379
+ if (options.type) {
3380
+ params.append("type", options.type);
3381
+ }
3382
+ const queryString = params.toString();
3383
+ const url = queryString ? `/api/v1/admin/users?${queryString}` : "/api/v1/admin/users";
3384
+ return await this.fetch.get(url);
3385
+ });
2436
3386
  }
2437
3387
  /**
2438
3388
  * Get a user by ID
@@ -2455,8 +3405,10 @@ var FluxbaseAdmin = class {
2455
3405
  * ```
2456
3406
  */
2457
3407
  async getUserById(userId, type = "app") {
2458
- const url = `/api/v1/admin/users/${userId}?type=${type}`;
2459
- return await this.fetch.get(url);
3408
+ return wrapAsync(async () => {
3409
+ const url = `/api/v1/admin/users/${userId}?type=${type}`;
3410
+ return await this.fetch.get(url);
3411
+ });
2460
3412
  }
2461
3413
  /**
2462
3414
  * Invite a new user
@@ -2480,8 +3432,10 @@ var FluxbaseAdmin = class {
2480
3432
  * ```
2481
3433
  */
2482
3434
  async inviteUser(request, type = "app") {
2483
- const url = `/api/v1/admin/users/invite?type=${type}`;
2484
- return await this.fetch.post(url, request);
3435
+ return wrapAsync(async () => {
3436
+ const url = `/api/v1/admin/users/invite?type=${type}`;
3437
+ return await this.fetch.post(url, request);
3438
+ });
2485
3439
  }
2486
3440
  /**
2487
3441
  * Delete a user
@@ -2499,8 +3453,10 @@ var FluxbaseAdmin = class {
2499
3453
  * ```
2500
3454
  */
2501
3455
  async deleteUser(userId, type = "app") {
2502
- const url = `/api/v1/admin/users/${userId}?type=${type}`;
2503
- return await this.fetch.delete(url);
3456
+ return wrapAsync(async () => {
3457
+ const url = `/api/v1/admin/users/${userId}?type=${type}`;
3458
+ return await this.fetch.delete(url);
3459
+ });
2504
3460
  }
2505
3461
  /**
2506
3462
  * Update user role
@@ -2519,8 +3475,10 @@ var FluxbaseAdmin = class {
2519
3475
  * ```
2520
3476
  */
2521
3477
  async updateUserRole(userId, role, type = "app") {
2522
- const url = `/api/v1/admin/users/${userId}/role?type=${type}`;
2523
- return await this.fetch.patch(url, { role });
3478
+ return wrapAsync(async () => {
3479
+ const url = `/api/v1/admin/users/${userId}/role?type=${type}`;
3480
+ return await this.fetch.patch(url, { role });
3481
+ });
2524
3482
  }
2525
3483
  /**
2526
3484
  * Reset user password
@@ -2538,8 +3496,10 @@ var FluxbaseAdmin = class {
2538
3496
  * ```
2539
3497
  */
2540
3498
  async resetUserPassword(userId, type = "app") {
2541
- const url = `/api/v1/admin/users/${userId}/reset-password?type=${type}`;
2542
- return await this.fetch.post(url, {});
3499
+ return wrapAsync(async () => {
3500
+ const url = `/api/v1/admin/users/${userId}/reset-password?type=${type}`;
3501
+ return await this.fetch.post(url, {});
3502
+ });
2543
3503
  }
2544
3504
  };
2545
3505
 
@@ -3097,24 +4057,47 @@ var QueryBuilder = class {
3097
4057
  var FluxbaseClient = class {
3098
4058
  /**
3099
4059
  * Create a new Fluxbase client instance
3100
- * @param options - Client configuration options
4060
+ *
4061
+ * @param fluxbaseUrl - The URL of your Fluxbase instance
4062
+ * @param fluxbaseKey - The anon key (JWT token with "anon" role). Generate using scripts/generate-keys.sh
4063
+ * @param options - Additional client configuration options
4064
+ *
4065
+ * @example
4066
+ * ```typescript
4067
+ * const client = new FluxbaseClient(
4068
+ * 'http://localhost:8080',
4069
+ * 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', // Anon JWT token
4070
+ * { timeout: 30000 }
4071
+ * )
4072
+ * ```
3101
4073
  */
3102
- constructor(options) {
3103
- this.fetch = new FluxbaseFetch(options.url, {
3104
- headers: options.headers,
3105
- timeout: options.timeout,
3106
- debug: options.debug
4074
+ constructor(fluxbaseUrl, fluxbaseKey, options) {
4075
+ this.fluxbaseUrl = fluxbaseUrl;
4076
+ this.fluxbaseKey = fluxbaseKey;
4077
+ const headers = {
4078
+ "apikey": fluxbaseKey,
4079
+ "Authorization": `Bearer ${fluxbaseKey}`,
4080
+ ...options?.headers
4081
+ };
4082
+ this.fetch = new FluxbaseFetch(fluxbaseUrl, {
4083
+ headers,
4084
+ timeout: options?.timeout,
4085
+ debug: options?.debug
3107
4086
  });
3108
4087
  this.auth = new FluxbaseAuth(
3109
4088
  this.fetch,
3110
- options.auth?.autoRefresh ?? true,
3111
- options.auth?.persist ?? true
4089
+ options?.auth?.autoRefresh ?? true,
4090
+ options?.auth?.persist ?? true
3112
4091
  );
3113
- if (options.auth?.token) {
4092
+ if (options?.auth?.token) {
3114
4093
  this.fetch.setAuthToken(options.auth.token);
3115
4094
  }
3116
- this.realtime = new FluxbaseRealtime(options.url, options.auth?.token || null);
4095
+ this.realtime = new FluxbaseRealtime(
4096
+ fluxbaseUrl,
4097
+ options?.auth?.token || null
4098
+ );
3117
4099
  this.storage = new FluxbaseStorage(this.fetch);
4100
+ this.functions = new FluxbaseFunctions(this.fetch);
3118
4101
  this.admin = new FluxbaseAdmin(this.fetch);
3119
4102
  this.management = new FluxbaseManagement(this.fetch);
3120
4103
  this.setupAuthSync();
@@ -3169,7 +4152,10 @@ var FluxbaseClient = class {
3169
4152
  */
3170
4153
  async rpc(functionName, params) {
3171
4154
  try {
3172
- const data = await this.fetch.post(`/api/v1/rpc/${functionName}`, params || {});
4155
+ const data = await this.fetch.post(
4156
+ `/api/v1/rpc/${functionName}`,
4157
+ params || {}
4158
+ );
3173
4159
  return { data, error: null };
3174
4160
  } catch (error) {
3175
4161
  return { data: null, error };
@@ -3209,6 +4195,36 @@ var FluxbaseClient = class {
3209
4195
  this.fetch.setAuthToken(token);
3210
4196
  this.realtime.setToken(token);
3211
4197
  }
4198
+ /**
4199
+ * Create or get a realtime channel (Supabase-compatible alias)
4200
+ *
4201
+ * This is a convenience method that delegates to client.realtime.channel().
4202
+ * Both patterns work identically:
4203
+ * - client.channel('room-1') - Supabase-style
4204
+ * - client.realtime.channel('room-1') - Fluxbase-style
4205
+ *
4206
+ * @param name - Channel name
4207
+ * @returns RealtimeChannel instance
4208
+ *
4209
+ * @example
4210
+ * ```typescript
4211
+ * // Supabase-compatible usage
4212
+ * const channel = client.channel('room-1')
4213
+ * .on('postgres_changes', {
4214
+ * event: '*',
4215
+ * schema: 'public',
4216
+ * table: 'messages'
4217
+ * }, (payload) => {
4218
+ * console.log('Change:', payload)
4219
+ * })
4220
+ * .subscribe()
4221
+ * ```
4222
+ *
4223
+ * @category Realtime
4224
+ */
4225
+ channel(name) {
4226
+ return this.realtime.channel(name);
4227
+ }
3212
4228
  /**
3213
4229
  * Get the internal HTTP client
3214
4230
  *
@@ -3228,10 +4244,14 @@ var FluxbaseClient = class {
3228
4244
  return this.fetch;
3229
4245
  }
3230
4246
  };
3231
- function createClient(options) {
3232
- return new FluxbaseClient(options);
4247
+ function createClient(fluxbaseUrl, fluxbaseKey, options) {
4248
+ return new FluxbaseClient(
4249
+ fluxbaseUrl,
4250
+ fluxbaseKey,
4251
+ options
4252
+ );
3233
4253
  }
3234
4254
 
3235
- export { APIKeysManager, AppSettingsManager, AuthSettingsManager, DDLManager, FluxbaseAdmin, FluxbaseAuth, FluxbaseClient, FluxbaseFetch, FluxbaseManagement, FluxbaseOAuth, FluxbaseRealtime, FluxbaseSettings, FluxbaseStorage, ImpersonationManager, InvitationsManager, OAuthProviderManager, QueryBuilder, RealtimeChannel, StorageBucket, SystemSettingsManager, WebhooksManager, createClient };
4255
+ export { APIKeysManager, AppSettingsManager, AuthSettingsManager, DDLManager, EmailTemplateManager, FluxbaseAdmin, FluxbaseAuth, FluxbaseClient, FluxbaseFetch, FluxbaseFunctions, FluxbaseManagement, FluxbaseOAuth, FluxbaseRealtime, FluxbaseSettings, FluxbaseStorage, ImpersonationManager, InvitationsManager, OAuthProviderManager, QueryBuilder, RealtimeChannel, StorageBucket, SystemSettingsManager, WebhooksManager, createClient };
3236
4256
  //# sourceMappingURL=index.js.map
3237
4257
  //# sourceMappingURL=index.js.map