@e-techsolutions/e-baas-sdk 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,7 +52,8 @@ localStorage.setItem("ebaas_session", JSON.stringify(session));
52
52
  localStorage.setItem("ebaas_user", JSON.stringify(user));
53
53
 
54
54
  // 4. Now you can use database operations normally
55
- const { data: users, error } = await ebaas.from("users").select("*");
55
+ const query = ebaas.from("users").select("*");
56
+ const { data, error } = await query.execute();
56
57
 
57
58
  if (error) {
58
59
  console.error("Error fetching users:", error);
@@ -187,45 +188,50 @@ const restoreSession = () => {
187
188
 
188
189
  ```typescript
189
190
  // Select data
190
- const { data: users, error } = await ebaas.from("users").select("*");
191
+ const query = ebaas.from("users").select("*");
192
+ const { data, error } = await query.execute();
191
193
 
192
194
  if (error) {
193
195
  console.error("Error fetching users:", error);
194
196
  } else {
195
- console.log("Users found:", users.length);
197
+ console.log("Users found:", data.length);
196
198
  }
197
199
 
198
200
  // Select specific fields for better performance
199
- const { data, error } = await ebaas
201
+ const query = ebaas
200
202
  .from("users")
201
203
  .select("id, name, email")
202
204
  .eq("status", "active")
203
205
  .order("created_at", { ascending: false })
204
206
  .limit(10);
207
+ const { data, error } = await query.execute();
205
208
 
206
209
  // Insert data
207
- const { data: newUser, error: insertError } = await ebaas.from("users").insert({
210
+ const query = ebaas.from("users").insert({
208
211
  name: "John Doe",
209
212
  email: "john@example.com",
210
213
  });
214
+ const { data, error } = await query.execute();
211
215
 
212
- if (insertError) {
213
- console.error("Error creating user:", insertError);
216
+ if (error) {
217
+ console.error("Error creating user:", error);
214
218
  } else {
215
- console.log("User created successfully:", newUser);
219
+ console.log("User created successfully:", data);
216
220
  }
217
221
 
218
222
  // Update data
219
- const { data: updated, error: updateError } = await ebaas.from("users").update({ name: "John Smith" }).eq("id", 123);
223
+ const query = ebaas.from("users").update({ name: "John Smith" }).eq("id", 123);
224
+ const { data, error } = await query.execute();
220
225
 
221
- if (updateError) {
222
- console.error("Error updating user:", updateError);
226
+ if (error) {
227
+ console.error("Error updating user:", error);
223
228
  } else {
224
- console.log("User updated successfully:", updated);
229
+ console.log("User updated successfully:", data);
225
230
  }
226
231
 
227
232
  // Delete data
228
- const { data, error } = await ebaas.from("users").delete().eq("id", 123);
233
+ const query = ebaas.from("users").delete().eq("id", 123);
234
+ const { data, error } = await query.execute();
229
235
 
230
236
  if (error) {
231
237
  console.error("Error deleting user:", error);
@@ -234,9 +240,10 @@ if (error) {
234
240
  }
235
241
 
236
242
  // RPC (stored procedures)
237
- const { data, error } = await ebaas.rpc("get_user_stats", {
243
+ const query = ebaas.rpc("get_user_stats", {
238
244
  user_id: 123,
239
245
  });
246
+ const { data, error } = await query.execute();
240
247
  ```
241
248
 
242
249
  ### Custom Database
@@ -390,7 +397,8 @@ const ebaas = createClient(
390
397
  import { EBaaSError } from "@e-techsolutions/e-baas-sdk";
391
398
 
392
399
  try {
393
- const { data } = await ebaas.from("users").select("*");
400
+ const query = ebaas.from("users").select("*");
401
+ const { data, error } = await query.execute();
394
402
  } catch (error) {
395
403
  if (error instanceof EBaaSError) {
396
404
  console.error("E-BaaS Error:", error.message);
@@ -408,10 +416,12 @@ E-BaaS implements strict validation for DELETE and UPDATE operations, requiring
408
416
 
409
417
  ```typescript
410
418
  // ✅ CORRECT: DELETE with specific filter
411
- const { data, error } = await ebaas.from("users").delete().eq("id", 123);
419
+ const query = ebaas.from("users").delete().eq("id", 123);
420
+ const { data, error } = await query.execute();
412
421
 
413
422
  // ❌ ERROR: DELETE without filters (returns "Security violation")
414
- const { data, error } = await ebaas.from("users").delete(); // Fails with security error
423
+ const query = ebaas.from("users").delete();
424
+ const { data, error } = await query.execute(); // Fails with security error
415
425
  ```
416
426
 
417
427
  ### Secure DELETE Operations with Required Filters
@@ -420,7 +430,8 @@ Always use the SDK with proper filters for safe DELETE operations:
420
430
 
421
431
  ```typescript
422
432
  // DELETE using SDK with required filter
423
- const { data, error } = await ebaas.from("users").delete().eq("id", userId);
433
+ const query = ebaas.from("users").delete().eq("id", userId);
434
+ const { data, error } = await query.execute();
424
435
 
425
436
  if (error) {
426
437
  console.error("Error deleting user:", error);
@@ -429,6 +440,201 @@ if (error) {
429
440
  }
430
441
  ```
431
442
 
443
+ ## Refresh Token Management
444
+
445
+ ### Automatic Token Refresh (Default)
446
+
447
+ The E-BaaS SDK automatically manages refresh tokens for workspace users, ensuring seamless authentication without manual intervention:
448
+
449
+ ```typescript
450
+ const ebaas = createClient(EBAAS_URL, EBAAS_KEY, {
451
+ database: {
452
+ workspaceId: WORKSPACE_ID,
453
+ },
454
+ auth: {
455
+ autoRefreshToken: true, // Default: true - automatic refresh enabled
456
+ persistSession: true, // Default: true - session persistence
457
+ },
458
+ });
459
+ ```
460
+
461
+ ### How Automatic Refresh Works
462
+
463
+ 1. **Login Phase**: When a user logs in, they receive both an access token and a refresh token
464
+ 2. **Background Monitoring**: The SDK monitors token expiration automatically
465
+ 3. **Seamless Refresh**: Before expiration, the SDK calls `/auth/v1/sdk/refresh` to get new tokens
466
+ 4. **Token Rotation**: Old refresh tokens are invalidated for security (refresh token rotation)
467
+ 5. **Continued Operation**: All database operations continue without interruption
468
+
469
+ ### Manual Refresh Token Management
470
+
471
+ For advanced use cases, you can disable automatic refresh and manage tokens manually:
472
+
473
+ ```typescript
474
+ const ebaas = createClient(EBAAS_URL, EBAAS_KEY, {
475
+ database: {
476
+ workspaceId: WORKSPACE_ID,
477
+ },
478
+ auth: {
479
+ autoRefreshToken: false, // Disable automatic refresh
480
+ },
481
+ });
482
+
483
+ // Manual refresh when needed
484
+ const refreshTokens = async () => {
485
+ try {
486
+ const query = ebaas.auth.refreshSession();
487
+ const { data, error } = await query.execute();
488
+
489
+ if (error) {
490
+ console.error('Failed to refresh token:', error);
491
+ // Redirect to login page
492
+ return;
493
+ }
494
+
495
+ // Update session in SDK
496
+ ebaas.auth.setSession(data.session);
497
+
498
+ // Update localStorage
499
+ localStorage.setItem('ebaas_session', JSON.stringify(data.session));
500
+
501
+ console.log('✅ Tokens refreshed successfully');
502
+ } catch (error) {
503
+ console.error('Token refresh error:', error);
504
+ // Handle refresh failure - redirect to login
505
+ }
506
+ };
507
+ ```
508
+
509
+ ### React Hook for Token Management
510
+
511
+ Here's a custom React hook for handling token refresh and expiration:
512
+
513
+ ```typescript
514
+ import { useEffect, useCallback } from 'react';
515
+ import { ebaas } from './ebaas-client';
516
+
517
+ export const useTokenRefresh = () => {
518
+ const checkTokenExpiration = useCallback(async () => {
519
+ const session = ebaas.auth.getSession();
520
+
521
+ if (!session?.expires_at) return;
522
+
523
+ const expiresAt = new Date(session.expires_at);
524
+ const now = new Date();
525
+ const timeToExpiry = expiresAt.getTime() - now.getTime();
526
+
527
+ // Refresh if token expires in less than 5 minutes
528
+ if (timeToExpiry < 5 * 60 * 1000) {
529
+ try {
530
+ const query = ebaas.auth.refreshSession();
531
+ const { data, error } = await query.execute();
532
+
533
+ if (error) {
534
+ console.error('Token refresh failed:', error);
535
+ // Redirect to login
536
+ window.location.href = '/login';
537
+ return;
538
+ }
539
+
540
+ // Update session
541
+ ebaas.auth.setSession(data.session);
542
+ localStorage.setItem('ebaas_session', JSON.stringify(data.session));
543
+
544
+ console.log('✅ Token refreshed proactively');
545
+ } catch (error) {
546
+ console.error('Token refresh error:', error);
547
+ // Handle error - redirect to login
548
+ window.location.href = '/login';
549
+ }
550
+ }
551
+ }, []);
552
+
553
+ useEffect(() => {
554
+ // Check immediately
555
+ checkTokenExpiration();
556
+
557
+ // Check every 2 minutes
558
+ const interval = setInterval(checkTokenExpiration, 2 * 60 * 1000);
559
+
560
+ return () => clearInterval(interval);
561
+ }, [checkTokenExpiration]);
562
+ };
563
+
564
+ // Usage in your main App component
565
+ const App = () => {
566
+ useTokenRefresh(); // Add this hook to your main App
567
+
568
+ return (
569
+ <div>
570
+ {/* Your app content */}
571
+ </div>
572
+ );
573
+ };
574
+ ```
575
+
576
+ ### Token Refresh Error Handling
577
+
578
+ ```typescript
579
+ const handleDatabaseOperation = async () => {
580
+ try {
581
+ const query = ebaas.from('users').select('*');
582
+ const { data, error } = await query.execute();
583
+
584
+ if (error) {
585
+ // Check if error is due to token expiration
586
+ if (error.status === 401 || error.message?.includes('token')) {
587
+ console.log('Token expired, attempting refresh...');
588
+
589
+ const { session, error } = await ebaas.auth.refreshSession();
590
+
591
+ if (error) {
592
+ // Refresh failed - redirect to login
593
+ console.error('Token refresh failed:', error);
594
+ window.location.href = '/login';
595
+ return;
596
+ }
597
+
598
+ // Update session and retry operation
599
+ ebaas.auth.setSession(session);
600
+ const { data, error } = await query.execute();
601
+
602
+ if (!error) {
603
+ console.log('✅ Operation successful after token refresh');
604
+ return data;
605
+ }
606
+ }
607
+
608
+ console.error('Database operation failed:', error);
609
+ }
610
+
611
+ return data;
612
+ } catch (error) {
613
+ console.error('Unexpected error:', error);
614
+ }
615
+ };
616
+ ```
617
+
618
+ ### Security Benefits
619
+
620
+ - **Token Rotation**: Each refresh generates new tokens and invalidates old ones
621
+ - **Short-lived Access Tokens**: Access tokens have shorter lifespans for security
622
+ - **Automatic Cleanup**: Expired and revoked tokens are automatically cleaned up
623
+ - **Session Tracking**: Each session is tracked with IP address and user agent
624
+ - **Workspace Isolation**: Refresh tokens are isolated per workspace for multi-tenancy
625
+
626
+ ### Configuration Options
627
+
628
+ ```typescript
629
+ const ebaas = createClient(EBAAS_URL, EBAAS_KEY, {
630
+ auth: {
631
+ autoRefreshToken: true, // Enable/disable automatic refresh
632
+ persistSession: true, // Persist session in localStorage
633
+ detectSessionInUrl: true, // Detect session from URL params
634
+ },
635
+ });
636
+ ```
637
+
432
638
  ## TypeScript Support
433
639
 
434
640
  The SDK is built with TypeScript and provides full type safety:
@@ -441,7 +647,8 @@ interface User {
441
647
  created_at: string;
442
648
  }
443
649
 
444
- const { data, error } = await ebaas.from<User>("users").select("*");
650
+ const query = ebaas.from<User>("users").select("*");
651
+ const { data, error } = await query.execute();
445
652
 
446
653
  // data is now typed as User[] | null
447
654
  ```