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