@urbackend/sdk 0.2.7 → 0.3.0

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.d.ts CHANGED
@@ -105,9 +105,17 @@ interface CollectionSchema {
105
105
  name: string;
106
106
  model: SchemaField[];
107
107
  }
108
+ /**
109
+ * Mail payload contract:
110
+ * - Template mode: provide `templateId` or `templateName` (with optional `variables`).
111
+ * - Direct mode: provide `subject` and at least one of `text` or `html`.
112
+ */
108
113
  interface SendMailPayload {
109
114
  to: string | string[];
110
- subject: string;
115
+ variables?: Record<string, unknown>;
116
+ templateId?: string;
117
+ templateName?: string;
118
+ subject?: string;
111
119
  text?: string;
112
120
  html?: string;
113
121
  }
@@ -129,161 +137,1071 @@ interface ApiResponse<T> {
129
137
  message?: string;
130
138
  }
131
139
 
140
+ /**
141
+ * Module for authentication and user management in urBackend
142
+ *
143
+ * @class AuthModule
144
+ * @description Provides complete authentication functionality including signup, login,
145
+ * profile management, password operations, email verification, social authentication,
146
+ * and session management. Manages session tokens automatically.
147
+ *
148
+ * @example
149
+ * // Initialize the auth module
150
+ * const client = new UrBackendClient({ apiKey: 'pk_live_xxx', secretKey: 'sk_live_xxx' });
151
+ * const auth = new AuthModule(client);
152
+ *
153
+ * // Sign up a new user
154
+ * const user = await auth.signUp({
155
+ * email: 'user@example.com',
156
+ * password: 'securePassword123',
157
+ * name: 'John Doe'
158
+ * });
159
+ *
160
+ * @example
161
+ * // Log in and manage session
162
+ * const session = await auth.login({
163
+ * email: 'user@example.com',
164
+ * password: 'securePassword123'
165
+ * });
166
+ * console.log('Access token:', session.accessToken);
167
+ *
168
+ * // Get current user profile
169
+ * const profile = await auth.me();
170
+ * console.log('Welcome:', profile.name);
171
+ */
132
172
  declare class AuthModule {
133
173
  private client;
134
174
  private sessionToken?;
175
+ /**
176
+ * Creates an instance of AuthModule
177
+ *
178
+ * @param {UrBackendClient} client - The urBackend client instance
179
+ *
180
+ * @example
181
+ * const client = new UrBackendClient({ apiKey: 'pk_live_xxx' });
182
+ * const auth = new AuthModule(client);
183
+ */
135
184
  constructor(client: UrBackendClient);
136
185
  /**
137
- * Create a new user account
186
+ * Creates a new user account
187
+ *
188
+ * @param {SignUpPayload} payload - User registration data
189
+ * @param {string} payload.email - User's email address
190
+ * @param {string} payload.password - User's password
191
+ * @param {string} payload.name - User's full name
192
+ * @returns {Promise<AuthUser>} Promise resolving to the created user object
193
+ *
194
+ * @throws {AuthError} If email already exists
195
+ * @throws {AuthError} If password does not meet requirements
196
+ * @throws {AuthError} If validation fails
197
+ *
198
+ * @example
199
+ * // Sign up a new user
200
+ * const user = await auth.signUp({
201
+ * email: 'john@example.com',
202
+ * password: 'StrongP@ss123',
203
+ * name: 'John Doe'
204
+ * });
205
+ * console.log('User created:', user._id);
206
+ *
207
+ * @example
208
+ * // Sign up with error handling
209
+ * try {
210
+ * const user = await auth.signUp({
211
+ * email: 'existing@email.com',
212
+ * password: 'weak',
213
+ * name: 'Test'
214
+ * });
215
+ * } catch (error) {
216
+ * if (error.message.includes('email')) {
217
+ * console.log('Email already registered');
218
+ * } else if (error.message.includes('password')) {
219
+ * console.log('Password too weak');
220
+ * }
221
+ * }
138
222
  */
139
223
  signUp(payload: SignUpPayload): Promise<AuthUser>;
140
224
  /**
141
- * Log in an existing user and store the session token
225
+ * Authenticates an existing user and stores the session token
226
+ *
227
+ * @param {LoginPayload} payload - User login credentials
228
+ * @param {string} payload.email - User's email address
229
+ * @param {string} payload.password - User's password
230
+ * @returns {Promise<AuthResponse>} Promise resolving to authentication response with tokens
231
+ *
232
+ * @throws {AuthError} If credentials are invalid
233
+ * @throws {AuthError} If account is locked or not verified
234
+ *
235
+ * @example
236
+ * // Log in a user
237
+ * const response = await auth.login({
238
+ * email: 'john@example.com',
239
+ * password: 'StrongP@ss123'
240
+ * });
241
+ * console.log('Access token:', response.accessToken);
242
+ *
243
+ * @example
244
+ * // Login with error handling
245
+ * try {
246
+ * const { accessToken, user } = await auth.login({
247
+ * email: 'user@example.com',
248
+ * password: 'wrongpassword'
249
+ * });
250
+ * } catch (error) {
251
+ * if (error.status === 401) {
252
+ * console.log('Invalid email or password');
253
+ * }
254
+ * }
142
255
  */
143
256
  login(payload: LoginPayload): Promise<AuthResponse>;
144
257
  /**
145
- * Get the current authenticated user's profile
258
+ * Retrieves the current authenticated user's profile
259
+ *
260
+ * @param {string} [token] - Optional authentication token (overrides stored token)
261
+ * @returns {Promise<AuthUser>} Promise resolving to the authenticated user's profile
262
+ *
263
+ * @throws {AuthError} If no authentication token is provided
264
+ * @throws {AuthError} If token is invalid or expired
265
+ *
266
+ * @example
267
+ * // Get current user profile (uses stored token from login)
268
+ * const user = await auth.me();
269
+ * console.log(`Hello ${user.name}, your email is ${user.email}`);
270
+ *
271
+ * @example
272
+ * // Get profile with custom token
273
+ * const user = await auth.me(customToken);
274
+ *
275
+ * @example
276
+ * // Get profile with error handling
277
+ * try {
278
+ * const user = await auth.me();
279
+ * console.log('Authenticated as:', user.email);
280
+ * } catch (error) {
281
+ * if (error.status === 401) {
282
+ * console.log('Please log in again');
283
+ * }
284
+ * }
146
285
  */
147
286
  me(token?: string): Promise<AuthUser>;
148
287
  /**
149
- * Update the current authenticated user's profile
288
+ * Updates the current authenticated user's profile
289
+ *
290
+ * @param {UpdateProfilePayload} payload - Profile data to update
291
+ * @param {string} [payload.name] - Updated name
292
+ * @param {string} [payload.email] - Updated email (may require re-verification)
293
+ * @param {string} [token] - Optional authentication token (overrides stored token)
294
+ * @returns {Promise<{ message: string }>} Promise resolving to success message
295
+ *
296
+ * @throws {AuthError} If no authentication token is provided
297
+ * @throws {AuthError} If token is invalid or expired
298
+ * @throws {AuthError} If email is already taken
299
+ *
300
+ * @example
301
+ * // Update user's name
302
+ * const result = await auth.updateProfile({ name: 'Jane Smith' });
303
+ * console.log(result.message);
304
+ *
305
+ * @example
306
+ * // Update multiple fields
307
+ * const result = await auth.updateProfile({
308
+ * name: 'Jane Doe',
309
+ * email: 'jane@newemail.com'
310
+ * });
311
+ *
312
+ * @example
313
+ * // Update with error handling
314
+ * try {
315
+ * await auth.updateProfile({ email: 'taken@email.com' });
316
+ * } catch (error) {
317
+ * console.log('Email already in use');
318
+ * }
150
319
  */
151
320
  updateProfile(payload: UpdateProfilePayload, token?: string): Promise<{
152
321
  message: string;
153
322
  }>;
154
323
  /**
155
- * Change the current authenticated user's password
324
+ * Changes the current authenticated user's password
325
+ *
326
+ * @param {ChangePasswordPayload} payload - Password change data
327
+ * @param {string} payload.currentPassword - User's current password
328
+ * @param {string} payload.newPassword - Desired new password
329
+ * @param {string} [token] - Optional authentication token (overrides stored token)
330
+ * @returns {Promise<{ message: string }>} Promise resolving to success message
331
+ *
332
+ * @throws {AuthError} If no authentication token is provided
333
+ * @throws {AuthError} If current password is incorrect
334
+ * @throws {AuthError} If new password does not meet requirements
335
+ *
336
+ * @example
337
+ * // Change password
338
+ * const result = await auth.changePassword({
339
+ * currentPassword: 'oldPassword123',
340
+ * newPassword: 'newStrongP@ss456'
341
+ * });
342
+ * console.log(result.message);
343
+ *
344
+ * @example
345
+ * // Change password with error handling
346
+ * try {
347
+ * await auth.changePassword({
348
+ * currentPassword: 'wrong',
349
+ * newPassword: 'newPassword123'
350
+ * });
351
+ * } catch (error) {
352
+ * if (error.message.includes('current password')) {
353
+ * console.log('Current password is incorrect');
354
+ * }
355
+ * }
156
356
  */
157
357
  changePassword(payload: ChangePasswordPayload, token?: string): Promise<{
158
358
  message: string;
159
359
  }>;
160
360
  /**
161
- * Verify user email with OTP
361
+ * Verifies user's email address using OTP
362
+ *
363
+ * @param {VerifyEmailPayload} payload - Email verification data
364
+ * @param {string} payload.email - User's email address
365
+ * @param {string} payload.otp - One-time password sent to email
366
+ * @returns {Promise<{ message: string }>} Promise resolving to success message
367
+ *
368
+ * @throws {AuthError} If OTP is invalid or expired
369
+ * @throws {AuthError} If email is not found
370
+ *
371
+ * @example
372
+ * // Verify email with OTP
373
+ * const result = await auth.verifyEmail({
374
+ * email: 'user@example.com',
375
+ * otp: '123456'
376
+ * });
377
+ * console.log('Email verified:', result.message);
378
+ *
379
+ * @example
380
+ * // Verify with error handling
381
+ * try {
382
+ * await auth.verifyEmail({ email: 'user@example.com', otp: '000000' });
383
+ * } catch (error) {
384
+ * console.log('Invalid OTP. Please try again.');
385
+ * }
162
386
  */
163
387
  verifyEmail(payload: VerifyEmailPayload): Promise<{
164
388
  message: string;
165
389
  }>;
166
390
  /**
167
- * Resend verification OTP
391
+ * Resends verification OTP to user's email
392
+ *
393
+ * @param {ResendOtpPayload} payload - Resend OTP request data
394
+ * @param {string} payload.email - User's email address
395
+ * @returns {Promise<{ message: string }>} Promise resolving to success message
396
+ *
397
+ * @throws {AuthError} If email is not found
398
+ * @throws {AuthError} If too many attempts
399
+ *
400
+ * @example
401
+ * // Resend verification OTP
402
+ * const result = await auth.resendVerificationOtp({
403
+ * email: 'user@example.com'
404
+ * });
405
+ * console.log('OTP resent:', result.message);
168
406
  */
169
407
  resendVerificationOtp(payload: ResendOtpPayload): Promise<{
170
408
  message: string;
171
409
  }>;
172
410
  /**
173
- * Request password reset OTP
411
+ * Requests a password reset OTP to be sent to user's email
412
+ *
413
+ * @param {RequestPasswordResetPayload} payload - Password reset request data
414
+ * @param {string} payload.email - User's email address
415
+ * @returns {Promise<{ message: string }>} Promise resolving to success message
416
+ *
417
+ * @throws {AuthError} If email is not found
418
+ * @throws {AuthError} If too many attempts
419
+ *
420
+ * @example
421
+ * // Request password reset
422
+ * const result = await auth.requestPasswordReset({
423
+ * email: 'user@example.com'
424
+ * });
425
+ * console.log('Reset OTP sent:', result.message);
174
426
  */
175
427
  requestPasswordReset(payload: RequestPasswordResetPayload): Promise<{
176
428
  message: string;
177
429
  }>;
178
430
  /**
179
- * Reset user password with OTP
431
+ * Resets user's password using OTP
432
+ *
433
+ * @param {ResetPasswordPayload} payload - Password reset data
434
+ * @param {string} payload.email - User's email address
435
+ * @param {string} payload.otp - One-time password sent via email
436
+ * @param {string} payload.newPassword - Desired new password
437
+ * @returns {Promise<{ message: string }>} Promise resolving to success message
438
+ *
439
+ * @throws {AuthError} If OTP is invalid or expired
440
+ * @throws {AuthError} If email is not found
441
+ * @throws {AuthError} If new password does not meet requirements
442
+ *
443
+ * @example
444
+ * // Reset password with OTP
445
+ * const result = await auth.resetPassword({
446
+ * email: 'user@example.com',
447
+ * otp: '123456',
448
+ * newPassword: 'NewStrongP@ss789'
449
+ * });
450
+ * console.log('Password reset:', result.message);
451
+ *
452
+ * @example
453
+ * // Reset password with error handling
454
+ * try {
455
+ * await auth.resetPassword({
456
+ * email: 'user@example.com',
457
+ * otp: 'wrong',
458
+ * newPassword: 'newPass123'
459
+ * });
460
+ * } catch (error) {
461
+ * console.log('Invalid OTP. Please request a new one.');
462
+ * }
180
463
  */
181
464
  resetPassword(payload: ResetPasswordPayload): Promise<{
182
465
  message: string;
183
466
  }>;
184
467
  /**
185
- * Get public-safe profile by username
468
+ * Retrieves a public-safe user profile by username
469
+ *
470
+ * @param {string} username - Username of the user to fetch
471
+ * @returns {Promise<AuthUser>} Promise resolving to public user profile (sensitive fields omitted)
472
+ *
473
+ * @throws {AuthError} If user with given username does not exist
474
+ *
475
+ * @example
476
+ * // Get public profile
477
+ * const profile = await auth.publicProfile('john_doe');
478
+ * console.log(`${profile.name} joined on ${profile.createdAt}`);
479
+ *
480
+ * @example
481
+ * // Display user profile on a public page
482
+ * try {
483
+ * const user = await auth.publicProfile('username');
484
+ * // Show user info (no email or private data)
485
+ * } catch (error) {
486
+ * console.log('User not found');
487
+ * }
186
488
  */
187
489
  publicProfile(username: string): Promise<AuthUser>;
188
490
  /**
189
- * Refresh the access token
190
- * @param refreshToken Optional refresh token for header mode. If omitted, uses cookie mode.
491
+ * Refreshes the access token using refresh token or cookie
492
+ *
493
+ * @param {string} [refreshToken] - Optional refresh token for header mode. If omitted, uses cookie mode.
494
+ * @returns {Promise<AuthResponse>} Promise resolving to new authentication response with fresh tokens
495
+ *
496
+ * @throws {AuthError} If refresh token is invalid or expired
497
+ *
498
+ * @example
499
+ * // Refresh token using cookie (if configured)
500
+ * const newTokens = await auth.refreshToken();
501
+ * console.log('New access token:', newTokens.accessToken);
502
+ *
503
+ * @example
504
+ * // Refresh token using explicit refresh token
505
+ * const newTokens = await auth.refreshToken(storedRefreshToken);
506
+ *
507
+ * @example
508
+ * // Auto-refresh before API calls
509
+ * try {
510
+ * await auth.me();
511
+ * } catch (error) {
512
+ * if (error.status === 401) {
513
+ * await auth.refreshToken();
514
+ * // Retry the original request
515
+ * }
516
+ * }
191
517
  */
192
518
  refreshToken(refreshToken?: string): Promise<AuthResponse>;
193
519
  /**
194
- * Returns the start URL for social authentication.
195
- * Redirect the user's browser to this URL to begin the flow.
520
+ * Returns the start URL for social authentication
521
+ *
522
+ * @param {('github' | 'google')} provider - The social authentication provider
523
+ * @returns {string} URL to redirect the user's browser to begin the OAuth flow
524
+ *
525
+ * @example
526
+ * // Redirect user to social login page
527
+ * const githubUrl = auth.socialStart('github');
528
+ * window.location.href = githubUrl;
529
+ *
530
+ * @example
531
+ * // For Node.js backend
532
+ * const googleUrl = auth.socialStart('google');
533
+ * res.redirect(googleUrl);
196
534
  */
197
535
  socialStart(provider: 'github' | 'google'): string;
198
536
  /**
199
- * Exchange social auth rtCode for a refresh token
537
+ * Exchanges social authentication rtCode for a refresh token
538
+ *
539
+ * @param {SocialExchangePayload} payload - Social exchange data
540
+ * @param {string} payload.rtCode - Return code from social provider
541
+ * @param {string} payload.provider - Social provider ('github' or 'google')
542
+ * @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response
543
+ *
544
+ * @throws {AuthError} If rtCode is invalid or expired
545
+ * @throws {AuthError} If social provider fails
546
+ *
547
+ * @example
548
+ * // After user returns from social login
549
+ * const rtCode = new URLSearchParams(window.location.search).get('rtCode');
550
+ * if (rtCode) {
551
+ * const response = await auth.socialExchange({
552
+ * rtCode: rtCode,
553
+ * provider: 'github'
554
+ * });
555
+ * console.log('Social login successful:', response.accessToken);
556
+ * }
200
557
  */
201
558
  socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse>;
202
559
  /**
203
- * Revoke the current session and clear local state
560
+ * Revokes the current session and clears local state
561
+ *
562
+ * @param {string} [token] - Optional authentication token (overrides stored token)
563
+ * @returns {Promise<{ success: boolean; message: string }>} Promise resolving to logout status
564
+ *
565
+ * @example
566
+ * // Log out current user
567
+ * const result = await auth.logout();
568
+ * console.log(result.message);
569
+ * // User is now logged out, session token is cleared
570
+ *
571
+ * @example
572
+ * // Log out with custom token
573
+ * const result = await auth.logout(customToken);
574
+ *
575
+ * @example
576
+ * // Logout after API calls
577
+ * try {
578
+ * await auth.logout();
579
+ * // Redirect to login page
580
+ * window.location.href = '/login';
581
+ * } catch (error) {
582
+ * console.log('Logout failed, but local session cleared');
583
+ * }
204
584
  */
205
585
  logout(token?: string): Promise<{
206
586
  success: boolean;
207
587
  message: string;
208
588
  }>;
209
589
  /**
210
- * Manually set the session token (e.g. after social auth exchange)
590
+ * Manually sets the session token (e.g., after social authentication exchange)
591
+ *
592
+ * @param {string} token - The session/access token to store
593
+ *
594
+ * @example
595
+ * // After successful social exchange
596
+ * const response = await auth.socialExchange({ rtCode, provider: 'github' });
597
+ * auth.setToken(response.accessToken);
598
+ *
599
+ * @example
600
+ * // Restore session from localStorage
601
+ * const savedToken = localStorage.getItem('authToken');
602
+ * if (savedToken) {
603
+ * auth.setToken(savedToken);
604
+ * const user = await auth.me();
605
+ * }
211
606
  */
212
607
  setToken(token: string): void;
213
608
  /**
214
- * Get the current stored session token
609
+ * Gets the current stored session token
610
+ *
611
+ * @returns {string | undefined} The current session token, if any
612
+ *
613
+ * @example
614
+ * // Get token for custom API calls
615
+ * const token = auth.getToken();
616
+ * if (token) {
617
+ * // Use token in custom API request
618
+ * fetch('/api/custom', { headers: { Authorization: `Bearer ${token}` } });
619
+ * }
620
+ *
621
+ * @example
622
+ * // Save token to localStorage for persistence
623
+ * const token = auth.getToken();
624
+ * if (token) {
625
+ * localStorage.setItem('authToken', token);
626
+ * }
215
627
  */
216
628
  getToken(): string | undefined;
217
629
  }
218
630
 
631
+ /**
632
+ * Module for database operations in urBackend
633
+ *
634
+ * @class DatabaseModule
635
+ * @description Provides CRUD (Create, Read, Update, Delete) operations for collections.
636
+ * Supports filtering, pagination, sorting, population, and expansion of related data.
637
+ *
638
+ * @example
639
+ * // Initialize the database module
640
+ * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });
641
+ * const db = new DatabaseModule(client);
642
+ *
643
+ * // Get all users
644
+ * const users = await db.getAll('users');
645
+ * console.log(users);
646
+ *
647
+ * @example
648
+ * // Insert a new document
649
+ * const newUser = await db.insert('users', {
650
+ * name: 'John Doe',
651
+ * email: 'john@example.com'
652
+ * });
653
+ * console.log('Created:', newUser._id);
654
+ */
219
655
  declare class DatabaseModule {
220
656
  private client;
657
+ /**
658
+ * Creates an instance of DatabaseModule
659
+ *
660
+ * @param {UrBackendClient} client - The authenticated urBackend client instance
661
+ *
662
+ * @example
663
+ * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });
664
+ * const db = new DatabaseModule(client);
665
+ */
221
666
  constructor(client: UrBackendClient);
222
667
  /**
223
- * Fetch all documents from a collection with optional query parameters
668
+ * Fetches all documents from a collection with optional query parameters
669
+ *
670
+ * @template T - The document type (extends DocumentData)
671
+ * @param {string} collection - Name of the collection to query
672
+ * @param {QueryParams} [params={}] - Optional query parameters for filtering, sorting, pagination
673
+ * @returns {Promise<T[]>} Promise resolving to an array of documents (empty array if none found)
674
+ *
675
+ * @throws {Error} If collection name is invalid
676
+ * @throws {Error} If authentication fails
677
+ * @throws {Error} If query parameters are malformed
678
+ *
679
+ * @example
680
+ * // Get all users
681
+ * const users = await db.getAll('users');
682
+ *
683
+ * @example
684
+ * // Get users with filters and pagination
685
+ * const activeUsers = await db.getAll('users', {
686
+ * filter: { status: 'active' },
687
+ * limit: 10,
688
+ * skip: 0,
689
+ * sort: '-createdAt'
690
+ * });
691
+ *
692
+ * @example
693
+ * // Get users with populated relations
694
+ * const usersWithPosts = await db.getAll('users', {
695
+ * populate: ['posts'],
696
+ * expand: ['profile']
697
+ * });
224
698
  */
225
699
  getAll<T extends DocumentData>(collection: string, params?: QueryParams): Promise<T[]>;
226
700
  /**
227
- * Fetch a single document by its ID
701
+ * Counts documents in a collection with optional filters
702
+ *
703
+ * @param {string} collection - Name of the collection to count
704
+ * @param {Omit<QueryParams, 'count'>} [params={}] - Optional filter parameters
705
+ * @returns {Promise<number>} Promise resolving to the total count of matching documents
706
+ *
707
+ * @throws {Error} If collection name is invalid
708
+ * @throws {Error} If authentication fails
709
+ *
710
+ * @example
711
+ * // Count all users
712
+ * const totalUsers = await db.count('users');
713
+ * console.log(`Total users: ${totalUsers}`);
714
+ *
715
+ * @example
716
+ * // Count users with filter
717
+ * const activeUsers = await db.count('users', {
718
+ * filter: { status: 'active' }
719
+ * });
720
+ *
721
+ * @example
722
+ * // Count for pagination
723
+ * const total = await db.count('products', {
724
+ * filter: { category: 'electronics' }
725
+ * });
726
+ * const totalPages = Math.ceil(total / 10);
727
+ */
728
+ count(collection: string, params?: Omit<QueryParams, 'count'>): Promise<number>;
729
+ /**
730
+ * Fetches a single document by its ID
731
+ *
732
+ * @template T - The document type (extends DocumentData)
733
+ * @param {string} collection - Name of the collection
734
+ * @param {string} id - Unique identifier of the document
735
+ * @param {Object} [options={}] - Optional parameters
736
+ * @param {string|string[]} [options.populate] - Fields to populate with related data
737
+ * @param {string|string[]} [options.expand] - Fields to expand with nested data
738
+ * @returns {Promise<T>} Promise resolving to the document
739
+ *
740
+ * @throws {NotFoundError} If document with given ID does not exist
741
+ * @throws {Error} If collection name or ID is invalid
742
+ * @throws {Error} If authentication fails
743
+ *
744
+ * @example
745
+ * // Get user by ID
746
+ * const user = await db.getOne('users', 'user_123');
747
+ * console.log(user.name);
748
+ *
749
+ * @example
750
+ * // Get user with populated posts
751
+ * const userWithPosts = await db.getOne('users', 'user_123', {
752
+ * populate: ['posts', 'comments']
753
+ * });
754
+ *
755
+ * @example
756
+ * // Get with error handling
757
+ * try {
758
+ * const user = await db.getOne('users', 'non_existent_id');
759
+ * } catch (error) {
760
+ * if (error instanceof NotFoundError) {
761
+ * console.log('User not found');
762
+ * }
763
+ * }
228
764
  */
229
765
  getOne<T extends DocumentData>(collection: string, id: string, options?: {
230
766
  populate?: string | string[];
231
767
  expand?: string | string[];
232
768
  }): Promise<T>;
233
769
  /**
234
- * Insert a new document into a collection
770
+ * Inserts a new document into a collection
771
+ *
772
+ * @template T - The document type (extends DocumentData)
773
+ * @param {string} collection - Name of the collection
774
+ * @param {InsertPayload} data - Document data to insert
775
+ * @param {string} [token] - Optional authentication token (overrides client default)
776
+ * @returns {Promise<T>} Promise resolving to the created document with generated ID
777
+ *
778
+ * @throws {Error} If collection name is invalid
779
+ * @throws {Error} If data validation fails
780
+ * @throws {Error} If authentication fails
781
+ * @throws {Error} If unique constraint violation occurs
782
+ *
783
+ * @example
784
+ * // Insert a new user
785
+ * const newUser = await db.insert('users', {
786
+ * name: 'John Doe',
787
+ * email: 'john@example.com',
788
+ * age: 25
789
+ * });
790
+ * console.log('User created:', newUser._id);
791
+ *
792
+ * @example
793
+ * // Insert with custom token
794
+ * const result = await db.insert('posts', {
795
+ * title: 'My Post',
796
+ * content: 'Hello World'
797
+ * }, customAuthToken);
798
+ *
799
+ * @example
800
+ * // Insert with error handling
801
+ * try {
802
+ * const user = await db.insert('users', { email: 'existing@email.com' });
803
+ * } catch (error) {
804
+ * if (error.message.includes('duplicate')) {
805
+ * console.log('Email already exists');
806
+ * }
807
+ * }
235
808
  */
236
809
  insert<T extends DocumentData>(collection: string, data: InsertPayload, token?: string): Promise<T>;
237
810
  /**
238
- * Update an existing document by its ID (Full replacement)
811
+ * Updates an existing document by its ID (full replacement)
812
+ *
813
+ * @template T - The document type (extends DocumentData)
814
+ * @param {string} collection - Name of the collection
815
+ * @param {string} id - Unique identifier of the document
816
+ * @param {UpdatePayload} data - Complete document data for replacement
817
+ * @param {string} [token] - Optional authentication token (overrides client default)
818
+ * @returns {Promise<T>} Promise resolving to the updated document
819
+ *
820
+ * @throws {NotFoundError} If document with given ID does not exist
821
+ * @throws {Error} If collection name or ID is invalid
822
+ * @throws {Error} If data validation fails
823
+ * @throws {Error} If authentication fails
824
+ *
825
+ * @example
826
+ * // Full update of a user
827
+ * const updatedUser = await db.update('users', 'user_123', {
828
+ * name: 'Jane Doe',
829
+ * email: 'jane@example.com',
830
+ * age: 26
831
+ * });
832
+ *
833
+ * @example
834
+ * // Update with error handling
835
+ * try {
836
+ * const result = await db.update('users', 'user_123', updatedData);
837
+ * console.log('Update successful:', result);
838
+ * } catch (error) {
839
+ * if (error instanceof NotFoundError) {
840
+ * console.log('User not found');
841
+ * }
842
+ * }
239
843
  */
240
844
  update<T extends DocumentData>(collection: string, id: string, data: UpdatePayload, token?: string): Promise<T>;
241
845
  /**
242
- * Partially update an existing document by its ID
846
+ * Partially updates an existing document by its ID (only provided fields)
847
+ *
848
+ * @template T - The document type (extends DocumentData)
849
+ * @param {string} collection - Name of the collection
850
+ * @param {string} id - Unique identifier of the document
851
+ * @param {PatchPayload} data - Partial data to update
852
+ * @param {string} [token] - Optional authentication token (overrides client default)
853
+ * @returns {Promise<T>} Promise resolving to the updated document
854
+ *
855
+ * @throws {NotFoundError} If document with given ID does not exist
856
+ * @throws {Error} If collection name or ID is invalid
857
+ * @throws {Error} If data validation fails
858
+ * @throws {Error} If authentication fails
859
+ *
860
+ * @example
861
+ * // Partial update - only update age
862
+ * const updatedUser = await db.patch('users', 'user_123', {
863
+ * age: 26
864
+ * });
865
+ *
866
+ * @example
867
+ * // Add a new field to document
868
+ * const result = await db.patch('users', 'user_123', {
869
+ * lastLogin: new Date().toISOString()
870
+ * });
871
+ *
872
+ * @example
873
+ * // Partial update with error handling
874
+ * try {
875
+ * const result = await db.patch('products', 'prod_123', {
876
+ * price: 29.99
877
+ * });
878
+ * console.log('Price updated:', result);
879
+ * } catch (error) {
880
+ * console.error('Update failed:', error.message);
881
+ * }
243
882
  */
244
883
  patch<T extends DocumentData>(collection: string, id: string, data: PatchPayload, token?: string): Promise<T>;
245
884
  /**
246
- * Delete a document by its ID
885
+ * Deletes a document by its ID
886
+ *
887
+ * @param {string} collection - Name of the collection
888
+ * @param {string} id - Unique identifier of the document to delete
889
+ * @param {string} [token] - Optional authentication token (overrides client default)
890
+ * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status
891
+ *
892
+ * @throws {Error} If collection name or ID is invalid
893
+ * @throws {Error} If authentication fails
894
+ * @throws {Error} If user lacks permission to delete
895
+ *
896
+ * @example
897
+ * // Delete a user
898
+ * const result = await db.delete('users', 'user_123');
899
+ * if (result.deleted) {
900
+ * console.log('User deleted successfully');
901
+ * }
902
+ *
903
+ * @example
904
+ * // Delete with error handling
905
+ * try {
906
+ * const { deleted } = await db.delete('posts', 'post_456');
907
+ * if (deleted) {
908
+ * console.log('Post removed');
909
+ * }
910
+ * } catch (error) {
911
+ * console.error('Deletion failed:', error.message);
912
+ * }
913
+ *
914
+ * @example
915
+ * // Delete after checking existence
916
+ * const exists = await db.getOne('users', 'user_123').catch(() => null);
917
+ * if (exists) {
918
+ * await db.delete('users', 'user_123');
919
+ * console.log('User deleted');
920
+ * }
247
921
  */
248
922
  delete(collection: string, id: string, token?: string): Promise<{
249
923
  deleted: boolean;
250
924
  }>;
251
925
  /**
252
926
  * Internal helper to build query string from QueryParams
927
+ *
928
+ * @param {QueryParams} params - Query parameters to convert
929
+ * @returns {string} URL query string (starting with '?' if parameters exist, otherwise empty)
930
+ *
931
+ * @internal
932
+ * @private
933
+ *
934
+ * @example
935
+ * // Returns "?limit=10&sort=-createdAt"
936
+ * buildQueryString({ limit: 10, sort: '-createdAt' })
937
+ *
938
+ * @example
939
+ * // Returns "?status=active&age=25"
940
+ * buildQueryString({ filter: { status: 'active', age: 25 } })
253
941
  */
254
942
  private buildQueryString;
255
943
  }
256
944
 
945
+ /**
946
+ * Module for handling file storage operations in urBackend
947
+ *
948
+ * @class StorageModule
949
+ * @description Provides methods to upload and delete files in the urBackend storage system.
950
+ * Supports both browser (File/Blob) and Node.js (Buffer) environments.
951
+ *
952
+ * @example
953
+ * // Initialize the storage module
954
+ * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });
955
+ * const storage = new StorageModule(client);
956
+ *
957
+ * // Upload a file (Browser)
958
+ * const fileInput = document.getElementById('fileInput');
959
+ * const result = await storage.upload(fileInput.files[0], 'my-file.pdf');
960
+ * console.log(result.url);
961
+ *
962
+ * @example
963
+ * // Upload a file (Node.js)
964
+ * const fs = require('fs');
965
+ * const buffer = fs.readFileSync('./document.pdf');
966
+ * const result = await storage.upload(buffer, 'document.pdf');
967
+ */
257
968
  declare class StorageModule {
258
969
  private client;
970
+ /**
971
+ * Creates an instance of StorageModule
972
+ *
973
+ * @param {UrBackendClient} client - The authenticated urBackend client instance
974
+ *
975
+ * @example
976
+ * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });
977
+ * const storage = new StorageModule(client);
978
+ */
259
979
  constructor(client: UrBackendClient);
260
980
  /**
261
- * Upload a file to storage
981
+ * Uploads a file to the urBackend storage
982
+ *
983
+ * @param {unknown} file - The file to upload. Supports:
984
+ * - Browser: File, Blob
985
+ * - Node.js: Buffer
986
+ * @param {string} [filename] - Optional custom filename for the uploaded file
987
+ * @returns {Promise<UploadResponse>} Promise resolving to upload details including URL and file ID
988
+ *
989
+ * @throws {Error} If file is invalid or missing
990
+ * @throws {Error} If file size exceeds limits
991
+ * @throws {Error} If authentication fails
992
+ * @throws {Error} If storage quota is exceeded
993
+ *
994
+ * @example
995
+ * // Browser: Upload from file input
996
+ * const fileInput = document.querySelector('input[type="file"]');
997
+ * const file = fileInput.files[0];
998
+ * const result = await storage.upload(file, 'custom-name.pdf');
999
+ * console.log('File URL:', result.url);
1000
+ *
1001
+ * @example
1002
+ * // Node.js: Upload Buffer
1003
+ * const fs = require('fs');
1004
+ * const buffer = fs.readFileSync('./image.png');
1005
+ * const result = await storage.upload(buffer, 'image.png');
1006
+ * console.log('Uploaded:', result.fileId);
1007
+ *
1008
+ * @example
1009
+ * // Upload without custom filename (uses original name)
1010
+ * const result = await storage.upload(file);
1011
+ *
1012
+ * @example
1013
+ * // Upload with error handling
1014
+ * try {
1015
+ * const result = await storage.upload(file, 'document.pdf');
1016
+ * console.log('Upload successful:', result.url);
1017
+ * } catch (error) {
1018
+ * console.error('Upload failed:', error.message);
1019
+ * // Handle error: retry, show user message, etc.
1020
+ * }
262
1021
  */
263
1022
  upload(file: unknown, filename?: string): Promise<UploadResponse>;
264
1023
  /**
265
- * Delete a file from storage by its path
1024
+ * Deletes a file from storage by its path
1025
+ *
1026
+ * @param {string} path - The file path or URL of the file to delete
1027
+ * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status
1028
+ *
1029
+ * @throws {Error} If path is empty or invalid
1030
+ * @throws {Error} If file does not exist
1031
+ * @throws {Error} If authentication fails
1032
+ * @throws {Error} If user lacks permission to delete the file
1033
+ *
1034
+ * @example
1035
+ * // Delete a file by path
1036
+ * const result = await storage.deleteFile('uploads/document.pdf');
1037
+ * if (result.deleted) {
1038
+ * console.log('File deleted successfully');
1039
+ * }
1040
+ *
1041
+ * @example
1042
+ * // Delete with error handling
1043
+ * try {
1044
+ * const result = await storage.deleteFile('uploads/old-file.jpg');
1045
+ * console.log('Deleted:', result.deleted);
1046
+ * } catch (error) {
1047
+ * console.error('Deletion failed:', error.message);
1048
+ * }
1049
+ *
1050
+ * @example
1051
+ * // Delete after upload
1052
+ * const uploadResult = await storage.upload(file, 'temp-file.pdf');
1053
+ * console.log('Uploaded:', uploadResult.url);
1054
+ *
1055
+ * // Later, delete the file
1056
+ * await storage.deleteFile('temp-file.pdf');
1057
+ * console.log('File cleaned up');
266
1058
  */
267
1059
  deleteFile(path: string): Promise<{
268
1060
  deleted: boolean;
269
1061
  }>;
270
1062
  }
271
1063
 
1064
+ /**
1065
+ * Module for managing database schemas in urBackend
1066
+ *
1067
+ * @class SchemaModule
1068
+ * @description Provides methods to fetch and manage collection schema definitions.
1069
+ * Schemas define the structure, validation rules, and data types for collections.
1070
+ *
1071
+ * @example
1072
+ * // Initialize the schema module
1073
+ * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });
1074
+ * const schema = new SchemaModule(client);
1075
+ *
1076
+ * // Get schema for a collection
1077
+ * const collectionSchema = await schema.getSchema('users');
1078
+ * console.log(collectionSchema.fields);
1079
+ */
272
1080
  declare class SchemaModule {
273
1081
  private client;
1082
+ /**
1083
+ * Creates an instance of SchemaModule
1084
+ *
1085
+ * @param {UrBackendClient} client - The authenticated urBackend client instance
1086
+ *
1087
+ * @example
1088
+ * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });
1089
+ * const schema = new SchemaModule(client);
1090
+ */
274
1091
  constructor(client: UrBackendClient);
275
1092
  /**
276
- * Fetch the schema definition for a collection
1093
+ * Fetches the schema definition for a specific collection
1094
+ *
1095
+ * @param {string} collection - Name of the collection to fetch schema for
1096
+ * @returns {Promise<CollectionSchema>} Promise resolving to the collection schema definition
1097
+ *
1098
+ * @throws {Error} If collection name is empty or contains only whitespace
1099
+ * @throws {Error} If collection does not exist
1100
+ * @throws {Error} If authentication fails
1101
+ *
1102
+ * @example
1103
+ * // Get schema for users collection
1104
+ * const userSchema = await schema.getSchema('users');
1105
+ * console.log(userSchema.fields);
1106
+ *
1107
+ * @example
1108
+ * // Get schema for products collection with error handling
1109
+ * try {
1110
+ * const productSchema = await schema.getSchema('products');
1111
+ * console.log('Schema fields:', Object.keys(productSchema.fields));
1112
+ * } catch (error) {
1113
+ * console.error('Failed to fetch schema:', error.message);
1114
+ * }
1115
+ *
1116
+ * @example
1117
+ * // Validate collection name before fetching
1118
+ * const collectionName = 'my_collection';
1119
+ * if (collectionName.trim()) {
1120
+ * const schemaDef = await schema.getSchema(collectionName);
1121
+ * // Use schema definition
1122
+ * }
277
1123
  */
278
1124
  getSchema(collection: string): Promise<CollectionSchema>;
279
1125
  }
280
1126
 
1127
+ /**
1128
+ * Module for handling email operations in urBackend
1129
+ *
1130
+ * @class MailModule
1131
+ * @description Provides methods to send emails using the urBackend mail service.
1132
+ * Requires a Secret Key (sk_live_...) and should be called from a server environment.
1133
+ *
1134
+ * @example
1135
+ * // Initialize the mail module
1136
+ * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });
1137
+ * const mail = new MailModule(client);
1138
+ *
1139
+ * // Send an email
1140
+ * const result = await mail.send({
1141
+ * to: 'user@example.com',
1142
+ * subject: 'Welcome!',
1143
+ * html: '<h1>Hello World</h1>'
1144
+ * });
1145
+ */
281
1146
  declare class MailModule {
282
1147
  private client;
1148
+ /**
1149
+ * Creates an instance of MailModule
1150
+ *
1151
+ * @param {UrBackendClient} client - The authenticated urBackend client instance
1152
+ *
1153
+ * @example
1154
+ * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });
1155
+ * const mail = new MailModule(client);
1156
+ */
283
1157
  constructor(client: UrBackendClient);
284
1158
  /**
285
- * Send an email using the urBackend mail service.
286
- * Note: This requires a Secret Key (sk_live_...) and should be called from a server environment.
1159
+ * Sends an email using the urBackend mail service
1160
+ *
1161
+ * @param {SendMailPayload} payload - The email content and configuration
1162
+ * @param {string} payload.to - Recipient email address
1163
+ * @param {string} payload.subject - Email subject line
1164
+ * @param {string} payload.html - HTML content of the email
1165
+ * @param {string} [payload.from] - Optional sender email address (defaults to configured sender)
1166
+ * @param {string[]} [payload.cc] - Optional CC recipient email addresses
1167
+ * @param {string[]} [payload.bcc] - Optional BCC recipient email addresses
1168
+ * @returns {Promise<SendMailResponse>} Promise resolving to email sending status and message ID
1169
+ *
1170
+ * @throws {Error} If secret key is missing or invalid
1171
+ * @throws {Error} If email validation fails
1172
+ * @throws {Error} If rate limit is exceeded
1173
+ *
1174
+ * @example
1175
+ * // Send a basic email
1176
+ * const result = await mail.send({
1177
+ * to: 'user@example.com',
1178
+ * subject: 'Welcome to urBackend',
1179
+ * html: '<h1>Welcome!</h1><p>Thanks for joining.</p>'
1180
+ * });
1181
+ * console.log(result.messageId);
1182
+ *
1183
+ * @example
1184
+ * // Send an email with CC and custom sender
1185
+ * const result = await mail.send({
1186
+ * from: 'noreply@myapp.com',
1187
+ * to: 'user@example.com',
1188
+ * cc: ['admin@example.com'],
1189
+ * subject: 'Important Update',
1190
+ * html: '<p>Your account has been updated.</p>'
1191
+ * });
1192
+ *
1193
+ * @example
1194
+ * // Send email with error handling
1195
+ * try {
1196
+ * const result = await mail.send({
1197
+ * to: 'user@example.com',
1198
+ * subject: 'Test',
1199
+ * html: '<p>Test email</p>'
1200
+ * });
1201
+ * console.log('Email sent:', result);
1202
+ * } catch (error) {
1203
+ * console.error('Failed to send email:', error);
1204
+ * }
287
1205
  */
288
1206
  send(payload: SendMailPayload): Promise<SendMailResponse>;
289
1207
  }