@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 +226 -19
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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:",
|
|
197
|
+
console.log("Users found:", data.length);
|
|
196
198
|
}
|
|
197
199
|
|
|
198
200
|
// Select specific fields for better performance
|
|
199
|
-
const
|
|
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
|
|
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 (
|
|
213
|
-
console.error("Error creating user:",
|
|
216
|
+
if (error) {
|
|
217
|
+
console.error("Error creating user:", error);
|
|
214
218
|
} else {
|
|
215
|
-
console.log("User created successfully:",
|
|
219
|
+
console.log("User created successfully:", data);
|
|
216
220
|
}
|
|
217
221
|
|
|
218
222
|
// Update data
|
|
219
|
-
const
|
|
223
|
+
const query = ebaas.from("users").update({ name: "John Smith" }).eq("id", 123);
|
|
224
|
+
const { data, error } = await query.execute();
|
|
220
225
|
|
|
221
|
-
if (
|
|
222
|
-
console.error("Error updating user:",
|
|
226
|
+
if (error) {
|
|
227
|
+
console.error("Error updating user:", error);
|
|
223
228
|
} else {
|
|
224
|
-
console.log("User updated successfully:",
|
|
229
|
+
console.log("User updated successfully:", data);
|
|
225
230
|
}
|
|
226
231
|
|
|
227
232
|
// Delete data
|
|
228
|
-
const
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
```
|