@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 +1371 -349
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1296 -293
- package/dist/index.d.ts +1296 -293
- package/dist/index.js +1370 -350
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
189
|
-
"/api/v1/auth/signin",
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
this.session
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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
|
|
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
|
|
342
|
-
|
|
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
|
|
353
|
-
|
|
354
|
-
|
|
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
|
|
364
|
-
|
|
365
|
-
|
|
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
|
-
|
|
374
|
-
|
|
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
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
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
|
|
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
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
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
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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()
|
|
496
|
-
|
|
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
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
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
|
|
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(
|
|
836
|
+
callbacks.forEach((callback) => callback(supabasePayload));
|
|
670
837
|
}
|
|
671
838
|
const wildcardCallbacks = this.callbacks.get("*");
|
|
672
839
|
if (wildcardCallbacks) {
|
|
673
|
-
wildcardCallbacks.forEach((callback) => callback(
|
|
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(
|
|
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
|
|
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 {
|
|
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
|
-
*
|
|
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(
|
|
988
|
+
async list(pathOrOptions, maybeOptions) {
|
|
811
989
|
try {
|
|
812
990
|
const params = new URLSearchParams();
|
|
813
|
-
|
|
814
|
-
|
|
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
|
|
825
|
-
|
|
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:
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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 {
|
|
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:
|
|
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:
|
|
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.
|
|
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/
|
|
982
|
-
var
|
|
1261
|
+
// src/functions.ts
|
|
1262
|
+
var FluxbaseFunctions = class {
|
|
983
1263
|
constructor(fetch2) {
|
|
984
1264
|
this.fetch = fetch2;
|
|
985
1265
|
}
|
|
986
1266
|
/**
|
|
987
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
994
|
-
* console.log(response.settings)
|
|
1866
|
+
* await client.admin.settings.app.setEmailEnabled(true)
|
|
995
1867
|
* ```
|
|
996
1868
|
*/
|
|
997
|
-
async
|
|
998
|
-
|
|
999
|
-
|
|
1869
|
+
async setEmailEnabled(enabled) {
|
|
1870
|
+
return await this.update({
|
|
1871
|
+
email: { enabled }
|
|
1872
|
+
});
|
|
1000
1873
|
}
|
|
1001
1874
|
/**
|
|
1002
|
-
*
|
|
1875
|
+
* Configure password complexity requirements
|
|
1003
1876
|
*
|
|
1004
|
-
*
|
|
1005
|
-
*
|
|
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
|
-
*
|
|
1010
|
-
*
|
|
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
|
|
1014
|
-
return await this.
|
|
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
|
-
*
|
|
1905
|
+
* Configure session settings
|
|
1018
1906
|
*
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
1021
|
-
* @
|
|
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
|
-
*
|
|
1026
|
-
*
|
|
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
|
|
1032
|
-
return await this.
|
|
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
|
-
*
|
|
1928
|
+
* Enable or disable email verification requirement
|
|
1036
1929
|
*
|
|
1037
|
-
*
|
|
1038
|
-
*
|
|
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.
|
|
1937
|
+
* await client.admin.settings.app.setEmailVerificationRequired(true)
|
|
1043
1938
|
* ```
|
|
1044
1939
|
*/
|
|
1045
|
-
async
|
|
1046
|
-
await this.
|
|
1940
|
+
async setEmailVerificationRequired(required) {
|
|
1941
|
+
return await this.update({
|
|
1942
|
+
authentication: { require_email_verification: required }
|
|
1943
|
+
});
|
|
1047
1944
|
}
|
|
1048
1945
|
};
|
|
1049
|
-
var
|
|
1946
|
+
var CustomSettingsManager = class {
|
|
1050
1947
|
constructor(fetch2) {
|
|
1051
1948
|
this.fetch = fetch2;
|
|
1052
1949
|
}
|
|
1053
1950
|
/**
|
|
1054
|
-
*
|
|
1055
|
-
*
|
|
1056
|
-
* Returns structured settings for authentication, features, email, and security.
|
|
1951
|
+
* Create a new custom setting
|
|
1057
1952
|
*
|
|
1058
|
-
* @
|
|
1953
|
+
* @param request - Custom setting creation request
|
|
1954
|
+
* @returns Promise resolving to CustomSetting
|
|
1059
1955
|
*
|
|
1060
1956
|
* @example
|
|
1061
1957
|
* ```typescript
|
|
1062
|
-
* const
|
|
1063
|
-
*
|
|
1064
|
-
*
|
|
1065
|
-
*
|
|
1066
|
-
*
|
|
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
|
|
1070
|
-
return await this.fetch.
|
|
1967
|
+
async create(request) {
|
|
1968
|
+
return await this.fetch.post(
|
|
1969
|
+
"/api/v1/admin/settings/custom",
|
|
1970
|
+
request
|
|
1971
|
+
);
|
|
1071
1972
|
}
|
|
1072
1973
|
/**
|
|
1073
|
-
*
|
|
1974
|
+
* List all custom settings
|
|
1074
1975
|
*
|
|
1075
|
-
*
|
|
1976
|
+
* @returns Promise resolving to ListCustomSettingsResponse
|
|
1076
1977
|
*
|
|
1077
|
-
* @
|
|
1078
|
-
*
|
|
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
|
-
*
|
|
1083
|
-
*
|
|
1084
|
-
*
|
|
1085
|
-
|
|
1086
|
-
|
|
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
|
-
*
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
1093
|
-
*
|
|
1094
|
-
*
|
|
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(
|
|
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
|
-
*
|
|
1103
|
-
*
|
|
1104
|
-
* This will delete all custom settings and return to default values.
|
|
2029
|
+
* Delete a custom setting
|
|
1105
2030
|
*
|
|
1106
|
-
* @
|
|
2031
|
+
* @param key - Setting key to delete
|
|
2032
|
+
* @returns Promise<void>
|
|
1107
2033
|
*
|
|
1108
2034
|
* @example
|
|
1109
2035
|
* ```typescript
|
|
1110
|
-
*
|
|
1111
|
-
* console.log('Settings reset to defaults:', defaults)
|
|
2036
|
+
* await client.admin.settings.custom.delete('feature.dark_mode')
|
|
1112
2037
|
* ```
|
|
1113
2038
|
*/
|
|
1114
|
-
async
|
|
1115
|
-
|
|
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
|
-
*
|
|
1119
|
-
*
|
|
1120
|
-
* Convenience method to enable user registration.
|
|
2048
|
+
* List all email templates
|
|
1121
2049
|
*
|
|
1122
|
-
* @returns Promise resolving to
|
|
2050
|
+
* @returns Promise resolving to ListEmailTemplatesResponse
|
|
1123
2051
|
*
|
|
1124
2052
|
* @example
|
|
1125
2053
|
* ```typescript
|
|
1126
|
-
* await client.admin.
|
|
2054
|
+
* const response = await client.admin.emailTemplates.list()
|
|
2055
|
+
* console.log(response.templates)
|
|
1127
2056
|
* ```
|
|
1128
2057
|
*/
|
|
1129
|
-
async
|
|
1130
|
-
|
|
1131
|
-
|
|
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
|
-
*
|
|
1136
|
-
*
|
|
1137
|
-
* Convenience method to disable user registration.
|
|
2065
|
+
* Get a specific email template by type
|
|
1138
2066
|
*
|
|
1139
|
-
* @
|
|
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.
|
|
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
|
|
1147
|
-
return await this.
|
|
1148
|
-
|
|
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
|
|
2083
|
+
* Update an email template
|
|
1153
2084
|
*
|
|
1154
|
-
*
|
|
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
|
|
1157
|
-
* @
|
|
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.
|
|
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
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
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
|
-
*
|
|
2111
|
+
* Reset an email template to default
|
|
1174
2112
|
*
|
|
1175
|
-
*
|
|
2113
|
+
* Removes any customizations and restores the template to its original state.
|
|
1176
2114
|
*
|
|
1177
|
-
* @param
|
|
1178
|
-
* @
|
|
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
|
-
*
|
|
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
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
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
|
-
*
|
|
2130
|
+
* Send a test email using the template
|
|
1198
2131
|
*
|
|
1199
|
-
*
|
|
2132
|
+
* Useful for previewing template changes before deploying to production.
|
|
1200
2133
|
*
|
|
1201
|
-
* @param
|
|
1202
|
-
* @
|
|
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.
|
|
2140
|
+
* await client.admin.emailTemplates.test('magic_link', 'test@example.com')
|
|
1207
2141
|
* ```
|
|
1208
2142
|
*/
|
|
1209
|
-
async
|
|
1210
|
-
|
|
1211
|
-
|
|
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
|
|
2280
|
-
|
|
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
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
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
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
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
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
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
|
-
|
|
2379
|
-
|
|
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
|
|
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
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
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
|
-
|
|
2459
|
-
|
|
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
|
-
|
|
2484
|
-
|
|
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
|
-
|
|
2503
|
-
|
|
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
|
-
|
|
2523
|
-
|
|
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
|
-
|
|
2542
|
-
|
|
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
|
-
*
|
|
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.
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
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
|
|
3111
|
-
options
|
|
4089
|
+
options?.auth?.autoRefresh ?? true,
|
|
4090
|
+
options?.auth?.persist ?? true
|
|
3112
4091
|
);
|
|
3113
|
-
if (options
|
|
4092
|
+
if (options?.auth?.token) {
|
|
3114
4093
|
this.fetch.setAuthToken(options.auth.token);
|
|
3115
4094
|
}
|
|
3116
|
-
this.realtime = new FluxbaseRealtime(
|
|
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(
|
|
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(
|
|
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
|