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