@urbackend/sdk 0.4.1 → 0.4.2
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 +41 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -8
- package/dist/index.d.ts +9 -8
- package/dist/index.mjs +41 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -84,8 +84,34 @@ async function parseApiError(response) {
|
|
|
84
84
|
let data;
|
|
85
85
|
try {
|
|
86
86
|
data = await response.json();
|
|
87
|
-
if (typeof data === "object" && data !== null
|
|
88
|
-
|
|
87
|
+
if (typeof data === "object" && data !== null) {
|
|
88
|
+
const errData = data;
|
|
89
|
+
if ("error" in errData) {
|
|
90
|
+
let candidate = "";
|
|
91
|
+
if (typeof errData.error === "string") {
|
|
92
|
+
candidate = errData.error;
|
|
93
|
+
} else if (Array.isArray(errData.error) && errData.error.length > 0) {
|
|
94
|
+
candidate = errData.error.map((e) => {
|
|
95
|
+
if (typeof e === "object" && e !== null && "message" in e) {
|
|
96
|
+
return String(e.message);
|
|
97
|
+
}
|
|
98
|
+
return String(e);
|
|
99
|
+
}).join(", ");
|
|
100
|
+
} else {
|
|
101
|
+
candidate = JSON.stringify(errData.error);
|
|
102
|
+
}
|
|
103
|
+
if (candidate && candidate.trim().length > 0 && candidate !== "[]" && candidate !== "null") {
|
|
104
|
+
message = candidate;
|
|
105
|
+
} else if ("message" in errData) {
|
|
106
|
+
message = typeof errData.message === "string" ? errData.message : JSON.stringify(errData.message);
|
|
107
|
+
}
|
|
108
|
+
} else if ("message" in errData) {
|
|
109
|
+
if (typeof errData.message === "string") {
|
|
110
|
+
message = errData.message;
|
|
111
|
+
} else {
|
|
112
|
+
message = JSON.stringify(errData.message);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
89
115
|
}
|
|
90
116
|
} catch {
|
|
91
117
|
message = response.statusText || message;
|
|
@@ -538,8 +564,8 @@ var AuthModule = class {
|
|
|
538
564
|
* Exchanges social authentication rtCode for a refresh token
|
|
539
565
|
*
|
|
540
566
|
* @param {SocialExchangePayload} payload - Social exchange data
|
|
567
|
+
* @param {string} payload.token - Access token fragment from social provider
|
|
541
568
|
* @param {string} payload.rtCode - Return code from social provider
|
|
542
|
-
* @param {string} payload.provider - Social provider ('github' or 'google')
|
|
543
569
|
* @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response
|
|
544
570
|
*
|
|
545
571
|
* @throws {AuthError} If rtCode is invalid or expired
|
|
@@ -547,13 +573,14 @@ var AuthModule = class {
|
|
|
547
573
|
*
|
|
548
574
|
* @example
|
|
549
575
|
* // After user returns from social login
|
|
550
|
-
* const
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
*
|
|
555
|
-
* });
|
|
556
|
-
* console.log('
|
|
576
|
+
* const urlParams = new URLSearchParams(window.location.search);
|
|
577
|
+
* const hashParams = new URLSearchParams(window.location.hash.substring(1));
|
|
578
|
+
* const rtCode = urlParams.get('rtCode');
|
|
579
|
+
* const token = hashParams.get('token');
|
|
580
|
+
* if (rtCode && token) {
|
|
581
|
+
* const response = await auth.socialExchange({ token, rtCode });
|
|
582
|
+
* console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);
|
|
583
|
+
* await auth.refreshToken();
|
|
557
584
|
* }
|
|
558
585
|
*/
|
|
559
586
|
async socialExchange(payload) {
|
|
@@ -1274,6 +1301,9 @@ var MailModule = class {
|
|
|
1274
1301
|
// src/client.ts
|
|
1275
1302
|
var UrBackendClient = class {
|
|
1276
1303
|
constructor(config) {
|
|
1304
|
+
if (!config.apiKey) {
|
|
1305
|
+
throw new Error("urbackend-sdk: apiKey is required to initialize the client.");
|
|
1306
|
+
}
|
|
1277
1307
|
this.apiKey = config.apiKey;
|
|
1278
1308
|
this.baseUrl = config.baseUrl || "https://api.ub.bitbros.in";
|
|
1279
1309
|
this.headers = config.headers || {};
|
|
@@ -1326,7 +1356,7 @@ var UrBackendClient = class {
|
|
|
1326
1356
|
const url = `${this.baseUrl}${path}`;
|
|
1327
1357
|
const headers = {
|
|
1328
1358
|
"x-api-key": this.apiKey,
|
|
1329
|
-
"User-Agent": `urbackend-sdk-js/0.4.
|
|
1359
|
+
"User-Agent": `urbackend-sdk-js/0.4.2`,
|
|
1330
1360
|
...this.headers
|
|
1331
1361
|
};
|
|
1332
1362
|
if (options.token) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/modules/auth.ts","../src/modules/database.ts","../src/modules/storage.ts","../src/modules/schema.ts","../src/modules/mail.ts","../src/client.ts"],"sourcesContent":["import { UrBackendClient } from './client';\r\nimport { UrBackendConfig } from './types';\r\nimport { AuthModule } from './modules/auth';\r\nimport { DatabaseModule } from './modules/database';\r\nimport { StorageModule } from './modules/storage';\r\nimport { SchemaModule } from './modules/schema';\r\nimport { MailModule } from './modules/mail';\r\n\r\nexport * from './types';\r\nexport * from './errors';\r\nexport { UrBackendClient, AuthModule, DatabaseModule, StorageModule, SchemaModule, MailModule };\r\n\r\n/**\r\n * Factory function to create a new urBackend client\r\n */\r\nexport default function urBackend(config: UrBackendConfig): UrBackendClient {\r\n return new UrBackendClient(config);\r\n}\r\n","export class UrBackendError extends Error {\r\n constructor(\r\n public message: string,\r\n public statusCode: number,\r\n public endpoint: string,\r\n ) {\r\n super(message);\r\n this.name = 'UrBackendError';\r\n }\r\n}\r\n\r\nexport class AuthError extends UrBackendError {\r\n constructor(message: string, statusCode: number, endpoint: string) {\r\n super(message, statusCode, endpoint);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\nexport class NotFoundError extends UrBackendError {\r\n constructor(message: string, endpoint: string) {\r\n super(message, 404, endpoint);\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\nexport class RateLimitError extends UrBackendError {\r\n public retryAfter?: number;\r\n\r\n constructor(message: string, endpoint: string, retryAfter?: number) {\r\n super(message, 429, endpoint);\r\n this.name = 'RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class StorageError extends UrBackendError {\r\n constructor(message: string, statusCode: number, endpoint: string) {\r\n super(message, statusCode, endpoint);\r\n this.name = 'StorageError';\r\n }\r\n}\r\n\r\nexport class ValidationError extends UrBackendError {\r\n constructor(message: string, endpoint: string) {\r\n super(message, 400, endpoint);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n\r\nexport async function parseApiError(response: Response): Promise<UrBackendError> {\r\n const endpoint = new URL(response.url).pathname;\r\n let message = 'An unexpected error occurred';\r\n let data: unknown;\r\n\r\n try {\r\n data = await response.json();\r\n if (typeof data === 'object' && data !== null && 'message' in data) {\r\n message = (data as { message: string }).message || message;\r\n }\r\n } catch {\r\n // If not JSON, use status text\r\n message = response.statusText || message;\r\n }\r\n\r\n const status = response.status;\r\n\r\n if (status === 401 || status === 403) {\r\n return new AuthError(message, status, endpoint);\r\n }\r\n\r\n if (status === 404) {\r\n return new NotFoundError(message, endpoint);\r\n }\r\n\r\n if (status === 429) {\r\n const retryAfter = response.headers.get('Retry-After');\r\n return new RateLimitError(message, endpoint, retryAfter ? parseInt(retryAfter, 10) : undefined);\r\n }\r\n\r\n if (status === 400) {\r\n return new ValidationError(message, endpoint);\r\n }\r\n\r\n // Default for 5xx or other 4xx\r\n if (endpoint.includes('/api/storage')) {\r\n return new StorageError(message, status, endpoint);\r\n }\r\n\r\n return new UrBackendError(message, status, endpoint);\r\n}\r\n","import { UrBackendClient } from '../client';\r\nimport {\r\n AuthUser,\r\n AuthResponse,\r\n SignUpPayload,\r\n LoginPayload,\r\n UpdateProfilePayload,\r\n ChangePasswordPayload,\r\n VerifyEmailPayload,\r\n ResendOtpPayload,\r\n RequestPasswordResetPayload,\r\n ResetPasswordPayload,\r\n SocialExchangePayload,\r\n SocialExchangeResponse,\r\n RequestOptions,\r\n} from '../types';\r\nimport { AuthError } from '../errors';\r\n\r\n/**\r\n * Module for authentication and user management in urBackend\r\n * \r\n * @class AuthModule\r\n * @description Provides complete authentication functionality including signup, login,\r\n * profile management, password operations, email verification, social authentication,\r\n * and session management. Manages session tokens automatically.\r\n * \r\n * @example\r\n * // Initialize the auth module\r\n * const client = new UrBackendClient({ apiKey: 'pk_live_xxx', secretKey: 'sk_live_xxx' });\r\n * const auth = new AuthModule(client);\r\n * \r\n * // Sign up a new user\r\n * const user = await auth.signUp({\r\n * email: 'user@example.com',\r\n * password: 'securePassword123',\r\n * name: 'John Doe'\r\n * });\r\n * \r\n * @example\r\n * // Log in and manage session\r\n * const session = await auth.login({\r\n * email: 'user@example.com',\r\n * password: 'securePassword123'\r\n * });\r\n * console.log('Access token:', session.accessToken);\r\n * \r\n * // Get current user profile\r\n * const profile = await auth.me();\r\n * console.log('Welcome:', profile.name);\r\n */\r\nexport class AuthModule {\r\n private sessionToken?: string;\r\n\r\n /**\r\n * Creates an instance of AuthModule\r\n * \r\n * @param {UrBackendClient} client - The urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ apiKey: 'pk_live_xxx' });\r\n * const auth = new AuthModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Creates a new user account\r\n * \r\n * @param {SignUpPayload} payload - User registration data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.password - User's password\r\n * @param {string} payload.name - User's full name\r\n * @returns {Promise<AuthUser>} Promise resolving to the created user object\r\n * \r\n * @throws {AuthError} If email already exists\r\n * @throws {AuthError} If password does not meet requirements\r\n * @throws {AuthError} If validation fails\r\n * \r\n * @example\r\n * // Sign up a new user\r\n * const user = await auth.signUp({\r\n * email: 'john@example.com',\r\n * password: 'StrongP@ss123',\r\n * name: 'John Doe'\r\n * });\r\n * console.log('User created:', user._id);\r\n * \r\n * @example\r\n * // Sign up with error handling\r\n * try {\r\n * const user = await auth.signUp({\r\n * email: 'existing@email.com',\r\n * password: 'weak',\r\n * name: 'Test'\r\n * });\r\n * } catch (error) {\r\n * if (error.message.includes('email')) {\r\n * console.log('Email already registered');\r\n * } else if (error.message.includes('password')) {\r\n * console.log('Password too weak');\r\n * }\r\n * }\r\n */\r\n public async signUp(payload: SignUpPayload): Promise<AuthUser> {\r\n return this.client.request<AuthUser>('POST', '/api/userAuth/signup', { body: payload });\r\n }\r\n\r\n /**\r\n * Authenticates an existing user and stores the session token\r\n * \r\n * @param {LoginPayload} payload - User login credentials\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.password - User's password\r\n * @returns {Promise<AuthResponse>} Promise resolving to authentication response with tokens\r\n * \r\n * @throws {AuthError} If credentials are invalid\r\n * @throws {AuthError} If account is locked or not verified\r\n * \r\n * @example\r\n * // Log in a user\r\n * const response = await auth.login({\r\n * email: 'john@example.com',\r\n * password: 'StrongP@ss123'\r\n * });\r\n * console.log('Access token:', response.accessToken);\r\n * \r\n * @example\r\n * // Login with error handling\r\n * try {\r\n * const { accessToken, user } = await auth.login({\r\n * email: 'user@example.com',\r\n * password: 'wrongpassword'\r\n * });\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * console.log('Invalid email or password');\r\n * }\r\n * }\r\n */\r\n public async login(payload: LoginPayload): Promise<AuthResponse> {\r\n const response = await this.client.request<AuthResponse>('POST', '/api/userAuth/login', {\r\n body: payload,\r\n });\r\n\r\n this.sessionToken = response.accessToken || response.token;\r\n\r\n if (!response.accessToken && response.token) {\r\n console.warn(\r\n 'urbackend-sdk: The server returned \"token\" which is deprecated. Please update your backend to return \"accessToken\".',\r\n );\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Retrieves the current authenticated user's profile\r\n * \r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<AuthUser>} Promise resolving to the authenticated user's profile\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If token is invalid or expired\r\n * \r\n * @example\r\n * // Get current user profile (uses stored token from login)\r\n * const user = await auth.me();\r\n * console.log(`Hello ${user.name}, your email is ${user.email}`);\r\n * \r\n * @example\r\n * // Get profile with custom token\r\n * const user = await auth.me(customToken);\r\n * \r\n * @example\r\n * // Get profile with error handling\r\n * try {\r\n * const user = await auth.me();\r\n * console.log('Authenticated as:', user.email);\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * console.log('Please log in again');\r\n * }\r\n * }\r\n */\r\n public async me(token?: string): Promise<AuthUser> {\r\n const activeToken = token || this.sessionToken;\r\n\r\n if (!activeToken) {\r\n throw new AuthError(\r\n 'Authentication token is required for /me endpoint',\r\n 401,\r\n '/api/userAuth/me',\r\n );\r\n }\r\n\r\n return this.client.request<AuthUser>('GET', '/api/userAuth/me', { token: activeToken });\r\n }\r\n\r\n /**\r\n * Updates the current authenticated user's profile\r\n * \r\n * @param {UpdateProfilePayload} payload - Profile data to update\r\n * @param {string} [payload.name] - Updated name\r\n * @param {string} [payload.email] - Updated email (may require re-verification)\r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If token is invalid or expired\r\n * @throws {AuthError} If email is already taken\r\n * \r\n * @example\r\n * // Update user's name\r\n * const result = await auth.updateProfile({ name: 'Jane Smith' });\r\n * console.log(result.message);\r\n * \r\n * @example\r\n * // Update multiple fields\r\n * const result = await auth.updateProfile({\r\n * name: 'Jane Doe',\r\n * email: 'jane@newemail.com'\r\n * });\r\n * \r\n * @example\r\n * // Update with error handling\r\n * try {\r\n * await auth.updateProfile({ email: 'taken@email.com' });\r\n * } catch (error) {\r\n * console.log('Email already in use');\r\n * }\r\n */\r\n public async updateProfile(payload: UpdateProfilePayload, token?: string): Promise<{ message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n if (!activeToken) {\r\n throw new AuthError('Authentication token is required to update profile', 401, '/api/userAuth/update-profile');\r\n }\r\n return this.client.request<{ message: string }>('PUT', '/api/userAuth/update-profile', {\r\n body: payload,\r\n token: activeToken,\r\n });\r\n }\r\n\r\n /**\r\n * Changes the current authenticated user's password\r\n * \r\n * @param {ChangePasswordPayload} payload - Password change data\r\n * @param {string} payload.currentPassword - User's current password\r\n * @param {string} payload.newPassword - Desired new password\r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If current password is incorrect\r\n * @throws {AuthError} If new password does not meet requirements\r\n * \r\n * @example\r\n * // Change password\r\n * const result = await auth.changePassword({\r\n * currentPassword: 'oldPassword123',\r\n * newPassword: 'newStrongP@ss456'\r\n * });\r\n * console.log(result.message);\r\n * \r\n * @example\r\n * // Change password with error handling\r\n * try {\r\n * await auth.changePassword({\r\n * currentPassword: 'wrong',\r\n * newPassword: 'newPassword123'\r\n * });\r\n * } catch (error) {\r\n * if (error.message.includes('current password')) {\r\n * console.log('Current password is incorrect');\r\n * }\r\n * }\r\n */\r\n public async changePassword(payload: ChangePasswordPayload, token?: string): Promise<{ message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n if (!activeToken) {\r\n throw new AuthError('Authentication token is required to change password', 401, '/api/userAuth/change-password');\r\n }\r\n return this.client.request<{ message: string }>('PUT', '/api/userAuth/change-password', {\r\n body: payload,\r\n token: activeToken,\r\n });\r\n }\r\n\r\n /**\r\n * Verifies user's email address using OTP\r\n * \r\n * @param {VerifyEmailPayload} payload - Email verification data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.otp - One-time password sent to email\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If OTP is invalid or expired\r\n * @throws {AuthError} If email is not found\r\n * \r\n * @example\r\n * // Verify email with OTP\r\n * const result = await auth.verifyEmail({\r\n * email: 'user@example.com',\r\n * otp: '123456'\r\n * });\r\n * console.log('Email verified:', result.message);\r\n * \r\n * @example\r\n * // Verify with error handling\r\n * try {\r\n * await auth.verifyEmail({ email: 'user@example.com', otp: '000000' });\r\n * } catch (error) {\r\n * console.log('Invalid OTP. Please try again.');\r\n * }\r\n */\r\n public async verifyEmail(payload: VerifyEmailPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/verify-email', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Resends verification OTP to user's email\r\n * \r\n * @param {ResendOtpPayload} payload - Resend OTP request data\r\n * @param {string} payload.email - User's email address\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If too many attempts\r\n * \r\n * @example\r\n * // Resend verification OTP\r\n * const result = await auth.resendVerificationOtp({\r\n * email: 'user@example.com'\r\n * });\r\n * console.log('OTP resent:', result.message);\r\n */\r\n public async resendVerificationOtp(payload: ResendOtpPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/resend-verification-otp', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Requests a password reset OTP to be sent to user's email\r\n * \r\n * @param {RequestPasswordResetPayload} payload - Password reset request data\r\n * @param {string} payload.email - User's email address\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If too many attempts\r\n * \r\n * @example\r\n * // Request password reset\r\n * const result = await auth.requestPasswordReset({\r\n * email: 'user@example.com'\r\n * });\r\n * console.log('Reset OTP sent:', result.message);\r\n */\r\n public async requestPasswordReset(payload: RequestPasswordResetPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/request-password-reset', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Resets user's password using OTP\r\n * \r\n * @param {ResetPasswordPayload} payload - Password reset data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.otp - One-time password sent via email\r\n * @param {string} payload.newPassword - Desired new password\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If OTP is invalid or expired\r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If new password does not meet requirements\r\n * \r\n * @example\r\n * // Reset password with OTP\r\n * const result = await auth.resetPassword({\r\n * email: 'user@example.com',\r\n * otp: '123456',\r\n * newPassword: 'NewStrongP@ss789'\r\n * });\r\n * console.log('Password reset:', result.message);\r\n * \r\n * @example\r\n * // Reset password with error handling\r\n * try {\r\n * await auth.resetPassword({\r\n * email: 'user@example.com',\r\n * otp: 'wrong',\r\n * newPassword: 'newPass123'\r\n * });\r\n * } catch (error) {\r\n * console.log('Invalid OTP. Please request a new one.');\r\n * }\r\n */\r\n public async resetPassword(payload: ResetPasswordPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/reset-password', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Retrieves a public-safe user profile by username\r\n * \r\n * @param {string} username - Username of the user to fetch\r\n * @returns {Promise<AuthUser>} Promise resolving to public user profile (sensitive fields omitted)\r\n * \r\n * @throws {AuthError} If user with given username does not exist\r\n * \r\n * @example\r\n * // Get public profile\r\n * const profile = await auth.publicProfile('john_doe');\r\n * console.log(`${profile.name} joined on ${profile.createdAt}`);\r\n * \r\n * @example\r\n * // Display user profile on a public page\r\n * try {\r\n * const user = await auth.publicProfile('username');\r\n * // Show user info (no email or private data)\r\n * } catch (error) {\r\n * console.log('User not found');\r\n * }\r\n */\r\n public async publicProfile(username: string): Promise<AuthUser> {\r\n return this.client.request<AuthUser>('GET', `/api/userAuth/public/${username}`);\r\n }\r\n\r\n /**\r\n * Refreshes the access token using refresh token or cookie\r\n * \r\n * @param {string} [refreshToken] - Optional refresh token for header mode. If omitted, uses cookie mode.\r\n * @returns {Promise<AuthResponse>} Promise resolving to new authentication response with fresh tokens\r\n * \r\n * @throws {AuthError} If refresh token is invalid or expired\r\n * \r\n * @example\r\n * // Refresh token using cookie (if configured)\r\n * const newTokens = await auth.refreshToken();\r\n * console.log('New access token:', newTokens.accessToken);\r\n * \r\n * @example\r\n * // Refresh token using explicit refresh token\r\n * const newTokens = await auth.refreshToken(storedRefreshToken);\r\n * \r\n * @example\r\n * // Auto-refresh before API calls\r\n * try {\r\n * await auth.me();\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * await auth.refreshToken();\r\n * // Retry the original request\r\n * }\r\n * }\r\n */\r\n public async refreshToken(refreshToken?: string): Promise<AuthResponse> {\r\n const options: RequestOptions = {};\r\n if (refreshToken) {\r\n options.headers = { 'x-refresh-token': refreshToken, 'x-refresh-token-mode': 'header' };\r\n } else {\r\n options.credentials = 'include';\r\n }\r\n\r\n const response = await this.client.request<AuthResponse>('POST', '/api/userAuth/refresh-token', options);\r\n this.sessionToken = response.accessToken || response.token;\r\n return response;\r\n }\r\n\r\n /**\r\n * Returns the start URL for social authentication\r\n * \r\n * @param {('github' | 'google')} provider - The social authentication provider\r\n * @returns {string} URL to redirect the user's browser to begin the OAuth flow\r\n * \r\n * @example\r\n * // Redirect user to social login page\r\n * const githubUrl = auth.socialStart('github');\r\n * window.location.href = githubUrl;\r\n * \r\n * @example\r\n * // For Node.js backend\r\n * const googleUrl = auth.socialStart('google');\r\n * res.redirect(googleUrl);\r\n */\r\n public socialStart(provider: 'github' | 'google'): string {\r\n return `${this.client.getBaseUrl()}/api/userAuth/social/${provider}/start?key=${this.client.getApiKey()}`;\r\n }\r\n\r\n /**\r\n * Exchanges social authentication rtCode for a refresh token\r\n * \r\n * @param {SocialExchangePayload} payload - Social exchange data\r\n * @param {string} payload.rtCode - Return code from social provider\r\n * @param {string} payload.provider - Social provider ('github' or 'google')\r\n * @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response\r\n * \r\n * @throws {AuthError} If rtCode is invalid or expired\r\n * @throws {AuthError} If social provider fails\r\n * \r\n * @example\r\n * // After user returns from social login\r\n * const rtCode = new URLSearchParams(window.location.search).get('rtCode');\r\n * if (rtCode) {\r\n * const response = await auth.socialExchange({\r\n * rtCode: rtCode,\r\n * provider: 'github'\r\n * });\r\n * console.log('Social login successful:', response.accessToken);\r\n * }\r\n */\r\n public async socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse> {\r\n return this.client.request<SocialExchangeResponse>('POST', '/api/userAuth/social/exchange', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Revokes the current session and clears local state\r\n * \r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ success: boolean; message: string }>} Promise resolving to logout status\r\n * \r\n * @example\r\n * // Log out current user\r\n * const result = await auth.logout();\r\n * console.log(result.message);\r\n * // User is now logged out, session token is cleared\r\n * \r\n * @example\r\n * // Log out with custom token\r\n * const result = await auth.logout(customToken);\r\n * \r\n * @example\r\n * // Logout after API calls\r\n * try {\r\n * await auth.logout();\r\n * // Redirect to login page\r\n * window.location.href = '/login';\r\n * } catch (error) {\r\n * console.log('Logout failed, but local session cleared');\r\n * }\r\n */\r\n public async logout(token?: string): Promise<{ success: boolean; message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n let result = { success: true, message: 'Logged out locally' };\r\n\r\n if (activeToken) {\r\n try {\r\n result = await this.client.request<{ success: boolean; message: string }>(\r\n 'POST',\r\n '/api/userAuth/logout',\r\n { token: activeToken, credentials: 'include' },\r\n );\r\n } catch (e) {\r\n // Silently fail if server logout fails, we still want to clear local state\r\n console.warn('urbackend-sdk: Server logout failed', e);\r\n }\r\n }\r\n\r\n this.sessionToken = undefined;\r\n return result;\r\n }\r\n\r\n /**\r\n * Manually sets the session token (e.g., after social authentication exchange)\r\n * \r\n * @param {string} token - The session/access token to store\r\n * \r\n * @example\r\n * // After successful social exchange\r\n * const response = await auth.socialExchange({ rtCode, provider: 'github' });\r\n * auth.setToken(response.accessToken);\r\n * \r\n * @example\r\n * // Restore session from localStorage\r\n * const savedToken = localStorage.getItem('authToken');\r\n * if (savedToken) {\r\n * auth.setToken(savedToken);\r\n * const user = await auth.me();\r\n * }\r\n */\r\n public setToken(token: string): void {\r\n this.sessionToken = token;\r\n }\r\n\r\n /**\r\n * Gets the current stored session token\r\n * \r\n * @returns {string | undefined} The current session token, if any\r\n * \r\n * @example\r\n * // Get token for custom API calls\r\n * const token = auth.getToken();\r\n * if (token) {\r\n * // Use token in custom API request\r\n * fetch('/api/custom', { headers: { Authorization: `Bearer ${token}` } });\r\n * }\r\n * \r\n * @example\r\n * // Save token to localStorage for persistence\r\n * const token = auth.getToken();\r\n * if (token) {\r\n * localStorage.setItem('authToken', token);\r\n * }\r\n */\r\n public getToken(): string | undefined {\r\n return this.sessionToken;\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { DocumentData, InsertPayload, UpdatePayload, PatchPayload, QueryParams } from '../types';\r\nimport { NotFoundError } from '../errors';\r\n\r\n/**\r\n * Module for database operations in urBackend\r\n * \r\n * @class DatabaseModule\r\n * @description Provides CRUD (Create, Read, Update, Delete) operations for collections.\r\n * Supports filtering, pagination, sorting, population, and expansion of related data.\r\n * \r\n * @example\r\n * // Initialize the database module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const db = new DatabaseModule(client);\r\n * \r\n * // Get all users\r\n * const users = await db.getAll('users');\r\n * console.log(users);\r\n * \r\n * @example\r\n * // Insert a new document\r\n * const newUser = await db.insert('users', {\r\n * name: 'John Doe',\r\n * email: 'john@example.com'\r\n * });\r\n * console.log('Created:', newUser._id);\r\n */\r\nexport class DatabaseModule {\r\n /**\r\n * Creates an instance of DatabaseModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const db = new DatabaseModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Fetches all documents from a collection with optional query parameters\r\n * \r\n * @template T - The document type (extends DocumentData)\n * @param {string} collection - Name of the collection to query\n * @param {QueryParams} [params={}] - Optional query parameters for filtering, sorting, pagination\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<T[]>} Promise resolving to an array of documents (empty array if none found)\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If query parameters are malformed\r\n * \r\n * @example\r\n * // Get all users\r\n * const users = await db.getAll('users');\r\n * \r\n * @example\r\n * // Get users with filters and pagination\r\n * const activeUsers = await db.getAll('users', {\r\n * filter: { status: 'active' },\r\n * limit: 10,\r\n * skip: 0,\r\n * sort: '-createdAt'\r\n * });\r\n * \r\n * @example\r\n * // Get users with populated relations\r\n * const usersWithPosts = await db.getAll('users', {\r\n * populate: ['posts'],\r\n * expand: ['profile']\r\n * });\r\n */\r\n public async getAll<T extends DocumentData>(\n collection: string,\n params: QueryParams = {},\n token?: string\n ): Promise<T[]> {\n const queryString = this.buildQueryString(params);\n const path = `/api/data/${collection}${queryString}`;\n \n try {\n const result = await this.client.request<T[] | { items?: T[] }>('GET', path, { token });\n\n if (Array.isArray(result)) {\n return result;\n }\n\n if (result && typeof result === 'object' && Array.isArray(result.items)) {\n return result.items;\n }\n\n return [] as T[];\n } catch (e) {\n if (e instanceof NotFoundError) {\n return [] as T[];\n }\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Counts documents in a collection with optional filters\r\n * \r\n * @param {string} collection - Name of the collection to count\n * @param {Omit<QueryParams, 'count'>} [params={}] - Optional filter parameters\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<number>} Promise resolving to the total count of matching documents\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Count all users\r\n * const totalUsers = await db.count('users');\r\n * console.log(`Total users: ${totalUsers}`);\r\n * \r\n * @example\r\n * // Count users with filter\r\n * const activeUsers = await db.count('users', {\r\n * filter: { status: 'active' }\r\n * });\r\n * \r\n * @example\r\n * // Count for pagination\r\n * const total = await db.count('products', {\r\n * filter: { category: 'electronics' }\r\n * });\r\n * const totalPages = Math.ceil(total / 10);\r\n */\r\n public async count(\n collection: string,\n params: Omit<QueryParams, 'count'> = {},\n token?: string\n ): Promise<number> {\n const queryString = this.buildQueryString({ ...params, count: 'true' });\n const path = `/api/data/${collection}${queryString}`;\n const result = await this.client.request<{ count: number }>('GET', path, { token });\n return result.count;\n }\n\r\n /**\r\n * Fetches a single document by its ID\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {Object} [options={}] - Optional parameters\n * @param {string|string[]} [options.populate] - Fields to populate with related data\n * @param {string|string[]} [options.expand] - Fields to expand with nested data\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<T>} Promise resolving to the document\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Get user by ID\r\n * const user = await db.getOne('users', 'user_123');\r\n * console.log(user.name);\r\n * \r\n * @example\r\n * // Get user with populated posts\r\n * const userWithPosts = await db.getOne('users', 'user_123', {\r\n * populate: ['posts', 'comments']\r\n * });\r\n * \r\n * @example\r\n * // Get with error handling\r\n * try {\r\n * const user = await db.getOne('users', 'non_existent_id');\r\n * } catch (error) {\r\n * if (error instanceof NotFoundError) {\r\n * console.log('User not found');\r\n * }\r\n * }\r\n */\r\n public async getOne<T extends DocumentData>(\n collection: string, \n id: string, \n options: { populate?: string | string[]; expand?: string | string[] } = {},\n token?: string\n ): Promise<T> {\n const queryString = this.buildQueryString(options);\n return this.client.request<T>('GET', `/api/data/${collection}/${id}${queryString}`, { token });\n }\n\r\n /**\r\n * Inserts a new document into a collection\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {InsertPayload} data - Document data to insert\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the created document with generated ID\r\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If unique constraint violation occurs\r\n * \r\n * @example\r\n * // Insert a new user\r\n * const newUser = await db.insert('users', {\r\n * name: 'John Doe',\r\n * email: 'john@example.com',\r\n * age: 25\r\n * });\r\n * console.log('User created:', newUser._id);\r\n * \r\n * @example\r\n * // Insert with custom token\r\n * const result = await db.insert('posts', {\r\n * title: 'My Post',\r\n * content: 'Hello World'\r\n * }, customAuthToken);\r\n * \r\n * @example\r\n * // Insert with error handling\r\n * try {\r\n * const user = await db.insert('users', { email: 'existing@email.com' });\r\n * } catch (error) {\r\n * if (error.message.includes('duplicate')) {\r\n * console.log('Email already exists');\r\n * }\r\n * }\r\n */\r\n public async insert<T extends DocumentData>(\r\n collection: string, \r\n data: InsertPayload, \r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('POST', `/api/data/${collection}`, { \r\n body: data,\r\n token \r\n });\r\n }\r\n\r\n /**\r\n * Updates an existing document by its ID (full replacement)\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {UpdatePayload} data - Complete document data for replacement\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the updated document\r\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Full update of a user\r\n * const updatedUser = await db.update('users', 'user_123', {\r\n * name: 'Jane Doe',\r\n * email: 'jane@example.com',\r\n * age: 26\r\n * });\r\n * \r\n * @example\r\n * // Update with error handling\r\n * try {\r\n * const result = await db.update('users', 'user_123', updatedData);\r\n * console.log('Update successful:', result);\r\n * } catch (error) {\r\n * if (error instanceof NotFoundError) {\r\n * console.log('User not found');\r\n * }\r\n * }\r\n */\r\n public async update<T extends DocumentData>(\r\n collection: string,\r\n id: string,\r\n data: UpdatePayload,\r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('PUT', `/api/data/${collection}/${id}`, { \r\n body: data,\r\n token\r\n });\r\n }\r\n\r\n /**\r\n * Partially updates an existing document by its ID (only provided fields)\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {PatchPayload} data - Partial data to update\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the updated document\r\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Partial update - only update age\r\n * const updatedUser = await db.patch('users', 'user_123', {\r\n * age: 26\r\n * });\r\n * \r\n * @example\r\n * // Add a new field to document\r\n * const result = await db.patch('users', 'user_123', {\r\n * lastLogin: new Date().toISOString()\r\n * });\r\n * \r\n * @example\r\n * // Partial update with error handling\r\n * try {\r\n * const result = await db.patch('products', 'prod_123', {\r\n * price: 29.99\r\n * });\r\n * console.log('Price updated:', result);\r\n * } catch (error) {\r\n * console.error('Update failed:', error.message);\r\n * }\r\n */\r\n public async patch<T extends DocumentData>(\r\n collection: string,\r\n id: string,\r\n data: PatchPayload,\r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('PATCH', `/api/data/${collection}/${id}`, { \r\n body: data,\r\n token\r\n });\r\n }\r\n\r\n /**\r\n * Deletes a document by its ID\r\n * \r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document to delete\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status\r\n * \r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If user lacks permission to delete\r\n * \r\n * @example\r\n * // Delete a user\r\n * const result = await db.delete('users', 'user_123');\r\n * if (result.deleted) {\r\n * console.log('User deleted successfully');\r\n * }\r\n * \r\n * @example\r\n * // Delete with error handling\r\n * try {\r\n * const { deleted } = await db.delete('posts', 'post_456');\r\n * if (deleted) {\r\n * console.log('Post removed');\r\n * }\r\n * } catch (error) {\r\n * console.error('Deletion failed:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Delete after checking existence\r\n * const exists = await db.getOne('users', 'user_123').catch(() => null);\r\n * if (exists) {\r\n * await db.delete('users', 'user_123');\r\n * console.log('User deleted');\r\n * }\r\n */\r\n public async delete(collection: string, id: string, token?: string): Promise<{ deleted: boolean }> {\r\n const result = await this.client.request<{ message?: string; id?: string } | null>(\r\n 'DELETE',\r\n `/api/data/${collection}/${id}`,\r\n { token },\r\n );\r\n\r\n const deleted =\r\n typeof result === 'object' &&\r\n result !== null &&\r\n (result.id === id || result.message === 'Document deleted');\r\n\r\n return { deleted };\r\n }\r\n\r\n /**\r\n * Internal helper to build query string from QueryParams\r\n * \r\n * @param {QueryParams} params - Query parameters to convert\r\n * @returns {string} URL query string (starting with '?' if parameters exist, otherwise empty)\r\n * \r\n * @internal\r\n * @private\r\n * \r\n * @example\r\n * // Returns \"?limit=10&sort=-createdAt\"\r\n * buildQueryString({ limit: 10, sort: '-createdAt' })\r\n * \r\n * @example\r\n * // Returns \"?status=active&age=25\"\r\n * buildQueryString({ filter: { status: 'active', age: 25 } })\r\n */\r\n private buildQueryString(params: QueryParams): string {\r\n const searchParams = new URLSearchParams();\r\n\r\n Object.entries(params).forEach(([key, value]) => {\r\n if (value === undefined || value === null) return;\r\n\r\n if (key === 'filter' && typeof value === 'object') {\r\n Object.entries(value as Record<string, unknown>).forEach(([fKey, fValue]) => {\r\n if (fValue !== undefined && fValue !== null) {\r\n searchParams.append(fKey, String(fValue));\r\n }\r\n });\r\n } else if ((key === 'populate' || key === 'expand') && Array.isArray(value)) {\r\n searchParams.append(key, value.join(','));\r\n } else {\r\n searchParams.append(key, String(value));\r\n }\r\n });\r\n\r\n const str = searchParams.toString();\r\n return str ? `?${str}` : '';\r\n }\r\n}\n","/// <reference lib=\"dom\" />\r\nimport { UrBackendClient } from '../client';\r\nimport { UploadResponse } from '../types';\r\n\r\n/**\r\n * Module for handling file storage operations in urBackend\r\n * \r\n * @class StorageModule\r\n * @description Provides methods to upload and delete files in the urBackend storage system.\r\n * Supports both browser (File/Blob) and Node.js (Buffer) environments.\r\n * \r\n * @example\r\n * // Initialize the storage module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const storage = new StorageModule(client);\r\n * \r\n * // Upload a file (Browser)\r\n * const fileInput = document.getElementById('fileInput');\r\n * const result = await storage.upload(fileInput.files[0], 'my-file.pdf');\r\n * console.log(result.url);\r\n * \r\n * @example\r\n * // Upload a file (Node.js)\r\n * const fs = require('fs');\r\n * const buffer = fs.readFileSync('./document.pdf');\r\n * const result = await storage.upload(buffer, 'document.pdf');\r\n */\r\nexport class StorageModule {\r\n /**\r\n * Creates an instance of StorageModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const storage = new StorageModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Uploads a file to the urBackend storage\r\n * \r\n * @param {unknown} file - The file to upload. Supports:\r\n * - Browser: File, Blob\r\n * - Node.js: Buffer\r\n * @param {string} [filename] - Optional custom filename for the uploaded file\r\n * @returns {Promise<UploadResponse>} Promise resolving to upload details including URL and file ID\r\n * \r\n * @throws {Error} If file is invalid or missing\r\n * @throws {Error} If file size exceeds limits\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If storage quota is exceeded\r\n * \r\n * @example\r\n * // Browser: Upload from file input\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * const result = await storage.upload(file, 'custom-name.pdf');\r\n * console.log('File URL:', result.url);\r\n * \r\n * @example\r\n * // Node.js: Upload Buffer\r\n * const fs = require('fs');\r\n * const buffer = fs.readFileSync('./image.png');\r\n * const result = await storage.upload(buffer, 'image.png');\r\n * console.log('Uploaded:', result.fileId);\r\n * \r\n * @example\r\n * // Upload without custom filename (uses original name)\r\n * const result = await storage.upload(file);\r\n * \r\n * @example\r\n * // Upload with error handling\r\n * try {\r\n * const result = await storage.upload(file, 'document.pdf');\r\n * console.log('Upload successful:', result.url);\r\n * } catch (error) {\r\n * console.error('Upload failed:', error.message);\r\n * // Handle error: retry, show user message, etc.\r\n * }\r\n */\r\n public async upload(file: unknown, filename?: string): Promise<UploadResponse> {\r\n // figure out name, contentType and size depending on environment\r\n let resolvedName = filename || \"file\";\r\n let contentType = \"application/octet-stream\";\r\n let fileSize: number;\r\n let fileData: Blob | BufferSource;\r\n\r\n if (typeof File !== \"undefined\" && file instanceof File) {\r\n // browser File object\r\n resolvedName = filename || file.name;\r\n contentType = file.type || contentType;\r\n fileSize = file.size;\r\n fileData = file;\r\n } else if (file instanceof Blob) {\r\n contentType = file.type || contentType;\r\n fileSize = file.size;\r\n fileData = file;\r\n } else if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(file)) {\r\n // Node.js Buffer\r\n fileSize = (file as Buffer).length;\r\n fileData = file as unknown as BufferSource;\r\n } else {\r\n throw new Error(\"Unsupported file type. Pass a File, Blob, or Buffer.\");\r\n }\r\n\r\n // step 1 — ask server for a signed URL\r\n const { signedUrl, filePath } = await this.client.request<{ signedUrl: string; filePath: string }>(\r\n \"POST\",\r\n \"/api/storage/upload-request\",\r\n { body: { filename: resolvedName, contentType, size: fileSize } }\r\n );\r\n\r\n // step 2 — upload directly to cloud, server not involved\r\n const putResponse = await fetch(signedUrl, {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": contentType },\r\n body: fileData as BodyInit,\r\n });\r\n\r\n if (!putResponse.ok) {\r\n throw new Error(`Direct upload to cloud failed: ${putResponse.status} ${putResponse.statusText}`);\r\n }\r\n\r\n // step 3 — tell server we're done so it can verify + update quota\r\n return this.client.request<UploadResponse>(\r\n \"POST\",\r\n \"/api/storage/upload-confirm\",\r\n { body: { filePath, size: fileSize } }\r\n );\r\n}\r\n /**\r\n * Deletes a file from storage by its path\r\n * \r\n * @param {string} path - The file path or URL of the file to delete\r\n * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status\r\n * \r\n * @throws {Error} If path is empty or invalid\r\n * @throws {Error} If file does not exist\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If user lacks permission to delete the file\r\n * \r\n * @example\r\n * // Delete a file by path\r\n * const result = await storage.deleteFile('uploads/document.pdf');\r\n * if (result.deleted) {\r\n * console.log('File deleted successfully');\r\n * }\r\n * \r\n * @example\r\n * // Delete with error handling\r\n * try {\r\n * const result = await storage.deleteFile('uploads/old-file.jpg');\r\n * console.log('Deleted:', result.deleted);\r\n * } catch (error) {\r\n * console.error('Deletion failed:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Delete after upload\r\n * const uploadResult = await storage.upload(file, 'temp-file.pdf');\r\n * console.log('Uploaded:', uploadResult.url);\r\n * \r\n * // Later, delete the file\r\n * await storage.deleteFile('temp-file.pdf');\r\n * console.log('File cleaned up');\r\n */\r\n public async deleteFile(path: string): Promise<{ deleted: boolean }> {\r\n return this.client.request<{ deleted: boolean }>('DELETE', '/api/storage/file', {\r\n body: { path },\r\n });\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { CollectionSchema } from '../types';\r\n\r\n/**\r\n * Module for managing database schemas in urBackend\r\n * \r\n * @class SchemaModule\r\n * @description Provides methods to fetch and manage collection schema definitions.\r\n * Schemas define the structure, validation rules, and data types for collections.\r\n * \r\n * @example\r\n * // Initialize the schema module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const schema = new SchemaModule(client);\r\n * \r\n * // Get schema for a collection\r\n * const collectionSchema = await schema.getSchema('users');\r\n * console.log(collectionSchema.fields);\r\n */\r\nexport class SchemaModule {\r\n /**\r\n * Creates an instance of SchemaModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const schema = new SchemaModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Fetches the schema definition for a specific collection\r\n * \r\n * @param {string} collection - Name of the collection to fetch schema for\r\n * @returns {Promise<CollectionSchema>} Promise resolving to the collection schema definition\r\n * \r\n * @throws {Error} If collection name is empty or contains only whitespace\r\n * @throws {Error} If collection does not exist\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Get schema for users collection\r\n * const userSchema = await schema.getSchema('users');\r\n * console.log(userSchema.fields);\r\n * \r\n * @example\r\n * // Get schema for products collection with error handling\r\n * try {\r\n * const productSchema = await schema.getSchema('products');\r\n * console.log('Schema fields:', Object.keys(productSchema.fields));\r\n * } catch (error) {\r\n * console.error('Failed to fetch schema:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Validate collection name before fetching\r\n * const collectionName = 'my_collection';\r\n * if (collectionName.trim()) {\r\n * const schemaDef = await schema.getSchema(collectionName);\r\n * // Use schema definition\r\n * }\r\n */\r\n public async getSchema(collection: string): Promise<CollectionSchema> {\r\n const trimmedCollection = collection.trim();\r\n if (trimmedCollection === '') {\r\n throw new Error('Collection name cannot be empty or whitespace-only');\r\n }\r\n\r\n const encodedCollection = encodeURIComponent(trimmedCollection);\r\n const response = await this.client.request<{\r\n message: string;\r\n collection: CollectionSchema;\r\n }>('GET', `/api/schemas/${encodedCollection}`);\r\n\r\n return response.collection;\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { SendMailPayload, SendMailResponse } from '../types';\r\n\r\n/**\r\n * Module for handling email operations in urBackend\r\n * \r\n * @class MailModule\r\n * @description Provides methods to send emails using the urBackend mail service.\r\n * Requires a Secret Key (sk_live_...) and should be called from a server environment.\r\n * \r\n * @example\r\n * // Initialize the mail module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const mail = new MailModule(client);\r\n * \r\n * // Send an email\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Welcome!',\r\n * html: '<h1>Hello World</h1>'\r\n * });\r\n */\r\nexport class MailModule {\r\n /**\r\n * Creates an instance of MailModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const mail = new MailModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Sends an email using the urBackend mail service\r\n * \r\n * @param {SendMailPayload} payload - The email content and configuration\r\n * @param {string} payload.to - Recipient email address\r\n * @param {string} payload.subject - Email subject line\r\n * @param {string} payload.html - HTML content of the email\r\n * @param {string} [payload.from] - Optional sender email address (defaults to configured sender)\r\n * @param {string[]} [payload.cc] - Optional CC recipient email addresses\r\n * @param {string[]} [payload.bcc] - Optional BCC recipient email addresses\r\n * @returns {Promise<SendMailResponse>} Promise resolving to email sending status and message ID\r\n * \r\n * @throws {Error} If secret key is missing or invalid\r\n * @throws {Error} If email validation fails\r\n * @throws {Error} If rate limit is exceeded\r\n * \r\n * @example\r\n * // Send a basic email\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Welcome to urBackend',\r\n * html: '<h1>Welcome!</h1><p>Thanks for joining.</p>'\r\n * });\r\n * console.log(result.messageId);\r\n * \r\n * @example\r\n * // Send an email with CC and custom sender\r\n * const result = await mail.send({\r\n * from: 'noreply@myapp.com',\r\n * to: 'user@example.com',\r\n * cc: ['admin@example.com'],\r\n * subject: 'Important Update',\r\n * html: '<p>Your account has been updated.</p>'\r\n * });\r\n * \r\n * @example\r\n * // Send email with error handling\r\n * try {\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Test',\r\n * html: '<p>Test email</p>'\r\n * });\r\n * console.log('Email sent:', result);\r\n * } catch (error) {\r\n * console.error('Failed to send email:', error);\r\n * }\r\n */\r\n public async send(payload: SendMailPayload): Promise<SendMailResponse> {\r\n return this.client.request<SendMailResponse>('POST', '/api/mail/send', {\r\n body: payload,\r\n });\r\n }\r\n}","import { UrBackendConfig, RequestOptions } from './types';\r\nimport { UrBackendError, parseApiError } from './errors';\r\nimport { AuthModule } from './modules/auth';\r\nimport { DatabaseModule } from './modules/database';\r\nimport { StorageModule } from './modules/storage';\r\nimport { SchemaModule } from './modules/schema';\r\nimport { MailModule } from './modules/mail';\r\n\r\nexport class UrBackendClient {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private _auth?: AuthModule;\r\n private _db?: DatabaseModule;\r\n private _storage?: StorageModule;\r\n private _schema?: SchemaModule;\r\n private _mail?: MailModule;\r\n private headers: Record<string, string>;\r\n\r\n constructor(config: UrBackendConfig) {\r\n this.apiKey = config.apiKey;\r\n this.baseUrl = config.baseUrl || 'https://api.ub.bitbros.in';\r\n this.headers = config.headers || {};\r\n\r\n if (typeof window !== 'undefined' && this.apiKey.startsWith('sk_live_')) {\r\n console.warn(\r\n '⚠️ urbackend-sdk: Avoid exposing your Secret Key (sk_live_...) in client-side code. This can lead to unauthorized access to your account and data. Use your Publishable Key (pk_live_...) instead.',\r\n );\r\n }\r\n }\r\n\r\n get auth(): AuthModule {\r\n if (!this._auth) {\r\n this._auth = new AuthModule(this);\r\n }\r\n return this._auth;\r\n }\r\n\r\n get db(): DatabaseModule {\r\n if (!this._db) {\r\n this._db = new DatabaseModule(this);\r\n }\r\n return this._db;\r\n }\r\n\r\n get storage(): StorageModule {\r\n if (!this._storage) {\r\n this._storage = new StorageModule(this);\r\n }\r\n return this._storage;\r\n }\r\n\r\n get schema(): SchemaModule {\r\n if (!this._schema) {\r\n this._schema = new SchemaModule(this);\r\n }\r\n return this._schema;\r\n }\r\n\r\n get mail(): MailModule {\r\n if (!this._mail) {\r\n this._mail = new MailModule(this);\r\n }\r\n return this._mail;\r\n }\r\n\r\n public getBaseUrl(): string {\r\n return this.baseUrl;\r\n }\r\n\r\n public getApiKey(): string {\r\n return this.apiKey;\r\n }\r\n\r\n /**\r\n * Internal request handler\r\n */\r\n public async request<T>(\r\n method: string,\r\n path: string,\r\n options: RequestOptions = {},\r\n ): Promise<T> {\r\n const url = `${this.baseUrl}${path}`;\r\n const headers: Record<string, string> = {\r\n 'x-api-key': this.apiKey,\r\n 'User-Agent': `urbackend-sdk-js/0.4.1`,\n ...this.headers,\r\n };\r\n\r\n if (options.token) {\r\n headers['Authorization'] = `Bearer ${options.token}`;\r\n }\r\n\r\n // Merge custom headers from options if provided\r\n if (options.headers) {\r\n Object.assign(headers, options.headers);\r\n }\r\n\r\n let requestBody: BodyInit | undefined;\r\n\r\n if (options.isMultipart) {\r\n // Fetch handles FormData content type and boundary\r\n requestBody = options.body as FormData;\r\n } else if (options.body) {\r\n headers['Content-Type'] = 'application/json';\r\n requestBody = JSON.stringify(options.body);\r\n }\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method,\r\n headers,\r\n body: requestBody,\r\n credentials: options.credentials,\r\n });\r\n\r\n if (!response.ok) {\r\n throw await parseApiError(response);\r\n }\r\n\r\n const contentType = response.headers.get('content-type');\r\n if (contentType && contentType.includes('application/json')) {\r\n const json = await response.json();\r\n // The API returns { data, success, message }\r\n // If data is present, return it. If success/message are present but no data, return the whole object (for exchange/logout etc)\r\n if (json.data !== undefined) {\r\n return json.data;\r\n }\r\n return json;\r\n }\r\n\r\n return (await response.text()) as unknown as T;\r\n } catch (error) {\r\n if (error instanceof UrBackendError) {\r\n throw error;\r\n }\r\n throw new UrBackendError(\r\n error instanceof Error ? error.message : 'Network request failed',\r\n 0,\r\n path,\r\n );\r\n }\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC,YACS,SACA,YACA,UACP;AACA,UAAM,OAAO;AAJN;AACA;AACA;AAGP,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,YAAN,cAAwB,eAAe;AAAA,EAC5C,YAAY,SAAiB,YAAoB,UAAkB;AACjE,UAAM,SAAS,YAAY,QAAQ;AACnC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,gBAAN,cAA4B,eAAe;AAAA,EAChD,YAAY,SAAiB,UAAkB;AAC7C,UAAM,SAAS,KAAK,QAAQ;AAC5B,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,iBAAN,cAA6B,eAAe;AAAA,EAGjD,YAAY,SAAiB,UAAkB,YAAqB;AAClE,UAAM,SAAS,KAAK,QAAQ;AAC5B,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,eAAN,cAA2B,eAAe;AAAA,EAC/C,YAAY,SAAiB,YAAoB,UAAkB;AACjE,UAAM,SAAS,YAAY,QAAQ;AACnC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,kBAAN,cAA8B,eAAe;AAAA,EAClD,YAAY,SAAiB,UAAkB;AAC7C,UAAM,SAAS,KAAK,QAAQ;AAC5B,SAAK,OAAO;AAAA,EACd;AACF;AAEA,eAAsB,cAAc,UAA6C;AAC/E,QAAM,WAAW,IAAI,IAAI,SAAS,GAAG,EAAE;AACvC,MAAI,UAAU;AACd,MAAI;AAEJ,MAAI;AACF,WAAO,MAAM,SAAS,KAAK;AAC3B,QAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,aAAa,MAAM;AAClE,gBAAW,KAA6B,WAAW;AAAA,IACrD;AAAA,EACF,QAAQ;AAEN,cAAU,SAAS,cAAc;AAAA,EACnC;AAEA,QAAM,SAAS,SAAS;AAExB,MAAI,WAAW,OAAO,WAAW,KAAK;AACpC,WAAO,IAAI,UAAU,SAAS,QAAQ,QAAQ;AAAA,EAChD;AAEA,MAAI,WAAW,KAAK;AAClB,WAAO,IAAI,cAAc,SAAS,QAAQ;AAAA,EAC5C;AAEA,MAAI,WAAW,KAAK;AAClB,UAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AACrD,WAAO,IAAI,eAAe,SAAS,UAAU,aAAa,SAAS,YAAY,EAAE,IAAI,MAAS;AAAA,EAChG;AAEA,MAAI,WAAW,KAAK;AAClB,WAAO,IAAI,gBAAgB,SAAS,QAAQ;AAAA,EAC9C;AAGA,MAAI,SAAS,SAAS,cAAc,GAAG;AACrC,WAAO,IAAI,aAAa,SAAS,QAAQ,QAAQ;AAAA,EACnD;AAEA,SAAO,IAAI,eAAe,SAAS,QAAQ,QAAQ;AACrD;;;ACvCO,IAAM,aAAN,MAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYtB,YAAoB,QAAyB;AAAzB;AAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwC9C,MAAa,OAAO,SAA2C;AAC7D,WAAO,KAAK,OAAO,QAAkB,QAAQ,wBAAwB,EAAE,MAAM,QAAQ,CAAC;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkCA,MAAa,MAAM,SAA8C;AAC/D,UAAM,WAAW,MAAM,KAAK,OAAO,QAAsB,QAAQ,uBAAuB;AAAA,MACtF,MAAM;AAAA,IACR,CAAC;AAED,SAAK,eAAe,SAAS,eAAe,SAAS;AAErD,QAAI,CAAC,SAAS,eAAe,SAAS,OAAO;AAC3C,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,MAAa,GAAG,OAAmC;AACjD,UAAM,cAAc,SAAS,KAAK;AAElC,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK,OAAO,QAAkB,OAAO,oBAAoB,EAAE,OAAO,YAAY,CAAC;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmCA,MAAa,cAAc,SAA+B,OAA8C;AACtG,UAAM,cAAc,SAAS,KAAK;AAClC,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,UAAU,sDAAsD,KAAK,8BAA8B;AAAA,IAC/G;AACA,WAAO,KAAK,OAAO,QAA6B,OAAO,gCAAgC;AAAA,MACrF,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoCA,MAAa,eAAe,SAAgC,OAA8C;AACxG,UAAM,cAAc,SAAS,KAAK;AAClC,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,UAAU,uDAAuD,KAAK,+BAA+B;AAAA,IACjH;AACA,WAAO,KAAK,OAAO,QAA6B,OAAO,iCAAiC;AAAA,MACtF,MAAM;AAAA,MACN,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BA,MAAa,YAAY,SAA2D;AAClF,WAAO,KAAK,OAAO,QAA6B,QAAQ,8BAA8B;AAAA,MACpF,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAa,sBAAsB,SAAyD;AAC1F,WAAO,KAAK,OAAO,QAA6B,QAAQ,yCAAyC;AAAA,MAC/F,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAa,qBAAqB,SAAoE;AACpG,WAAO,KAAK,OAAO,QAA6B,QAAQ,wCAAwC;AAAA,MAC9F,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoCA,MAAa,cAAc,SAA6D;AACtF,WAAO,KAAK,OAAO,QAA6B,QAAQ,gCAAgC;AAAA,MACtF,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,MAAa,cAAc,UAAqC;AAC9D,WAAO,KAAK,OAAO,QAAkB,OAAO,wBAAwB,QAAQ,EAAE;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BA,MAAa,aAAa,cAA8C;AACtE,UAAM,UAA0B,CAAC;AACjC,QAAI,cAAc;AAChB,cAAQ,UAAU,EAAE,mBAAmB,cAAc,wBAAwB,SAAS;AAAA,IACxF,OAAO;AACL,cAAQ,cAAc;AAAA,IACxB;AAEA,UAAM,WAAW,MAAM,KAAK,OAAO,QAAsB,QAAQ,+BAA+B,OAAO;AACvG,SAAK,eAAe,SAAS,eAAe,SAAS;AACrD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBO,YAAY,UAAuC;AACxD,WAAO,GAAG,KAAK,OAAO,WAAW,CAAC,wBAAwB,QAAQ,cAAc,KAAK,OAAO,UAAU,CAAC;AAAA,EACzG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,MAAa,eAAe,SAAiE;AAC3F,WAAO,KAAK,OAAO,QAAgC,QAAQ,iCAAiC;AAAA,MAC1F,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BA,MAAa,OAAO,OAAgE;AAClF,UAAM,cAAc,SAAS,KAAK;AAClC,QAAI,SAAS,EAAE,SAAS,MAAM,SAAS,qBAAqB;AAE5D,QAAI,aAAa;AACf,UAAI;AACF,iBAAS,MAAM,KAAK,OAAO;AAAA,UACzB;AAAA,UACA;AAAA,UACA,EAAE,OAAO,aAAa,aAAa,UAAU;AAAA,QAC/C;AAAA,MACF,SAAS,GAAG;AAEV,gBAAQ,KAAK,uCAAuC,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,SAAK,eAAe;AACpB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBO,SAAS,OAAqB;AACnC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBO,WAA+B;AACpC,WAAO,KAAK;AAAA,EACd;AACF;;;ACxkBO,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU1B,YAAoB,QAAyB;AAAzB;AAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmC9C,MAAa,OACX,YACA,SAAsB,CAAC,GACvB,OACc;AACd,UAAM,cAAc,KAAK,iBAAiB,MAAM;AAChD,UAAM,OAAO,aAAa,UAAU,GAAG,WAAW;AAElD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,OAAO,QAA+B,OAAO,MAAM,EAAE,MAAM,CAAC;AAEtF,UAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,eAAO;AAAA,MACT;AAEA,UAAI,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,KAAK,GAAG;AACvE,eAAO,OAAO;AAAA,MAChB;AAEA,aAAO,CAAC;AAAA,IACV,SAAS,GAAG;AACV,UAAI,aAAa,eAAe;AAC9B,eAAO,CAAC;AAAA,MACV;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,MAAa,MACX,YACA,SAAqC,CAAC,GACtC,OACiB;AACjB,UAAM,cAAc,KAAK,iBAAiB,EAAE,GAAG,QAAQ,OAAO,OAAO,CAAC;AACtE,UAAM,OAAO,aAAa,UAAU,GAAG,WAAW;AAClD,UAAM,SAAS,MAAM,KAAK,OAAO,QAA2B,OAAO,MAAM,EAAE,MAAM,CAAC;AAClF,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuCA,MAAa,OACX,YACA,IACA,UAAwE,CAAC,GACzE,OACY;AACZ,UAAM,cAAc,KAAK,iBAAiB,OAAO;AACjD,WAAO,KAAK,OAAO,QAAW,OAAO,aAAa,UAAU,IAAI,EAAE,GAAG,WAAW,IAAI,EAAE,MAAM,CAAC;AAAA,EAC/F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0CA,MAAa,OACX,YACA,MACA,OACY;AACZ,WAAO,KAAK,OAAO,QAAW,QAAQ,aAAa,UAAU,IAAI;AAAA,MAC/D,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoCA,MAAa,OACX,YACA,IACA,MACA,OACY;AACZ,WAAO,KAAK,OAAO,QAAW,OAAO,aAAa,UAAU,IAAI,EAAE,IAAI;AAAA,MACpE,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCA,MAAa,MACX,YACA,IACA,MACA,OACY;AACZ,WAAO,KAAK,OAAO,QAAW,SAAS,aAAa,UAAU,IAAI,EAAE,IAAI;AAAA,MACtE,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCA,MAAa,OAAO,YAAoB,IAAY,OAA+C;AACjG,UAAM,SAAS,MAAM,KAAK,OAAO;AAAA,MAC/B;AAAA,MACA,aAAa,UAAU,IAAI,EAAE;AAAA,MAC7B,EAAE,MAAM;AAAA,IACV;AAEA,UAAM,UACJ,OAAO,WAAW,YAClB,WAAW,SACV,OAAO,OAAO,MAAM,OAAO,YAAY;AAE1C,WAAO,EAAE,QAAQ;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBQ,iBAAiB,QAA6B;AACpD,UAAM,eAAe,IAAI,gBAAgB;AAEzC,WAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,UAAI,UAAU,UAAa,UAAU,KAAM;AAE3C,UAAI,QAAQ,YAAY,OAAO,UAAU,UAAU;AACjD,eAAO,QAAQ,KAAgC,EAAE,QAAQ,CAAC,CAAC,MAAM,MAAM,MAAM;AAC3E,cAAI,WAAW,UAAa,WAAW,MAAM;AAC3C,yBAAa,OAAO,MAAM,OAAO,MAAM,CAAC;AAAA,UAC1C;AAAA,QACF,CAAC;AAAA,MACH,YAAY,QAAQ,cAAc,QAAQ,aAAa,MAAM,QAAQ,KAAK,GAAG;AAC3E,qBAAa,OAAO,KAAK,MAAM,KAAK,GAAG,CAAC;AAAA,MAC1C,OAAO;AACL,qBAAa,OAAO,KAAK,OAAO,KAAK,CAAC;AAAA,MACxC;AAAA,IACF,CAAC;AAED,UAAM,MAAM,aAAa,SAAS;AAClC,WAAO,MAAM,IAAI,GAAG,KAAK;AAAA,EAC3B;AACF;;;AChZO,IAAM,gBAAN,MAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUzB,YAAoB,QAAyB;AAAzB;AAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4C9C,MAAa,OAAO,MAAe,UAA4C;AAE7E,QAAI,eAAe,YAAY;AAC/B,QAAI,cAAc;AAClB,QAAI;AACJ,QAAI;AAEJ,QAAI,OAAO,SAAS,eAAe,gBAAgB,MAAM;AAErD,qBAAe,YAAY,KAAK;AAChC,oBAAc,KAAK,QAAQ;AAC3B,iBAAW,KAAK;AAChB,iBAAW;AAAA,IACf,WAAW,gBAAgB,MAAM;AAC7B,oBAAc,KAAK,QAAQ;AAC3B,iBAAW,KAAK;AAChB,iBAAW;AAAA,IACf,WAAW,OAAO,WAAW,eAAe,OAAO,SAAS,IAAI,GAAG;AAE/D,iBAAY,KAAgB;AAC5B,iBAAW;AAAA,IACf,OAAO;AACH,YAAM,IAAI,MAAM,sDAAsD;AAAA,IAC1E;AAGA,UAAM,EAAE,WAAW,SAAS,IAAI,MAAM,KAAK,OAAO;AAAA,MAC9C;AAAA,MACA;AAAA,MACA,EAAE,MAAM,EAAE,UAAU,cAAc,aAAa,MAAM,SAAS,EAAE;AAAA,IACpE;AAGA,UAAM,cAAc,MAAM,MAAM,WAAW;AAAA,MACvC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,YAAY;AAAA,MACvC,MAAM;AAAA,IACV,CAAC;AAED,QAAI,CAAC,YAAY,IAAI;AACjB,YAAM,IAAI,MAAM,kCAAkC,YAAY,MAAM,IAAI,YAAY,UAAU,EAAE;AAAA,IACpG;AAGA,WAAO,KAAK,OAAO;AAAA,MACf;AAAA,MACA;AAAA,MACA,EAAE,MAAM,EAAE,UAAU,MAAM,SAAS,EAAE;AAAA,IACzC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqCE,MAAa,WAAW,MAA6C;AACnE,WAAO,KAAK,OAAO,QAA8B,UAAU,qBAAqB;AAAA,MAC9E,MAAM,EAAE,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AACF;;;ACzJO,IAAM,eAAN,MAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUxB,YAAoB,QAAyB;AAAzB;AAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkC9C,MAAa,UAAU,YAA+C;AACpE,UAAM,oBAAoB,WAAW,KAAK;AAC1C,QAAI,sBAAsB,IAAI;AAC5B,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AAEA,UAAM,oBAAoB,mBAAmB,iBAAiB;AAC9D,UAAM,WAAW,MAAM,KAAK,OAAO,QAGhC,OAAO,gBAAgB,iBAAiB,EAAE;AAE7C,WAAO,SAAS;AAAA,EAClB;AACF;;;ACvDO,IAAM,aAAN,MAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUtB,YAAoB,QAAyB;AAAzB;AAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkD9C,MAAa,KAAK,SAAqD;AACrE,WAAO,KAAK,OAAO,QAA0B,QAAQ,kBAAkB;AAAA,MACrE,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF;;;AC/EO,IAAM,kBAAN,MAAsB;AAAA,EAU3B,YAAY,QAAyB;AACnC,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,UAAU,OAAO,WAAW,CAAC;AAElC,QAAI,OAAO,WAAW,eAAe,KAAK,OAAO,WAAW,UAAU,GAAG;AACvE,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,OAAmB;AACrB,QAAI,CAAC,KAAK,OAAO;AACf,WAAK,QAAQ,IAAI,WAAW,IAAI;AAAA,IAClC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAqB;AACvB,QAAI,CAAC,KAAK,KAAK;AACb,WAAK,MAAM,IAAI,eAAe,IAAI;AAAA,IACpC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,UAAyB;AAC3B,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,IAAI,cAAc,IAAI;AAAA,IACxC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAuB;AACzB,QAAI,CAAC,KAAK,SAAS;AACjB,WAAK,UAAU,IAAI,aAAa,IAAI;AAAA,IACtC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAAmB;AACrB,QAAI,CAAC,KAAK,OAAO;AACf,WAAK,QAAQ,IAAI,WAAW,IAAI;AAAA,IAClC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,aAAqB;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,YAAoB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,QACX,QACA,MACA,UAA0B,CAAC,GACf;AACZ,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI;AAClC,UAAM,UAAkC;AAAA,MACtC,aAAa,KAAK;AAAA,MAClB,cAAc;AAAA,MACd,GAAG,KAAK;AAAA,IACV;AAEA,QAAI,QAAQ,OAAO;AACjB,cAAQ,eAAe,IAAI,UAAU,QAAQ,KAAK;AAAA,IACpD;AAGA,QAAI,QAAQ,SAAS;AACnB,aAAO,OAAO,SAAS,QAAQ,OAAO;AAAA,IACxC;AAEA,QAAI;AAEJ,QAAI,QAAQ,aAAa;AAEvB,oBAAc,QAAQ;AAAA,IACxB,WAAW,QAAQ,MAAM;AACvB,cAAQ,cAAc,IAAI;AAC1B,oBAAc,KAAK,UAAU,QAAQ,IAAI;AAAA,IAC3C;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,aAAa,QAAQ;AAAA,MACvB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,MAAM,cAAc,QAAQ;AAAA,MACpC;AAEA,YAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;AACvD,UAAI,eAAe,YAAY,SAAS,kBAAkB,GAAG;AAC3D,cAAM,OAAO,MAAM,SAAS,KAAK;AAGjC,YAAI,KAAK,SAAS,QAAW;AAC3B,iBAAO,KAAK;AAAA,QACd;AACA,eAAO;AAAA,MACT;AAEA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,SAAS,OAAO;AACd,UAAI,iBAAiB,gBAAgB;AACnC,cAAM;AAAA,MACR;AACA,YAAM,IAAI;AAAA,QACR,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACzC;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AP/He,SAAR,UAA2B,QAA0C;AAC1E,SAAO,IAAI,gBAAgB,MAAM;AACnC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/modules/auth.ts","../src/modules/database.ts","../src/modules/storage.ts","../src/modules/schema.ts","../src/modules/mail.ts","../src/client.ts"],"sourcesContent":["import { UrBackendClient } from './client';\r\nimport { UrBackendConfig } from './types';\r\nimport { AuthModule } from './modules/auth';\r\nimport { DatabaseModule } from './modules/database';\r\nimport { StorageModule } from './modules/storage';\r\nimport { SchemaModule } from './modules/schema';\r\nimport { MailModule } from './modules/mail';\r\n\r\nexport * from './types';\r\nexport * from './errors';\r\nexport { UrBackendClient, AuthModule, DatabaseModule, StorageModule, SchemaModule, MailModule };\r\n\r\n/**\r\n * Factory function to create a new urBackend client\r\n */\r\nexport default function urBackend(config: UrBackendConfig): UrBackendClient {\r\n return new UrBackendClient(config);\r\n}\r\n","export class UrBackendError extends Error {\r\n constructor(\r\n public message: string,\r\n public statusCode: number,\r\n public endpoint: string,\r\n ) {\r\n super(message);\r\n this.name = 'UrBackendError';\r\n }\r\n}\r\n\r\nexport class AuthError extends UrBackendError {\r\n constructor(message: string, statusCode: number, endpoint: string) {\r\n super(message, statusCode, endpoint);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\nexport class NotFoundError extends UrBackendError {\r\n constructor(message: string, endpoint: string) {\r\n super(message, 404, endpoint);\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\nexport class RateLimitError extends UrBackendError {\r\n public retryAfter?: number;\r\n\r\n constructor(message: string, endpoint: string, retryAfter?: number) {\r\n super(message, 429, endpoint);\r\n this.name = 'RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class StorageError extends UrBackendError {\r\n constructor(message: string, statusCode: number, endpoint: string) {\r\n super(message, statusCode, endpoint);\r\n this.name = 'StorageError';\r\n }\r\n}\r\n\r\nexport class ValidationError extends UrBackendError {\r\n constructor(message: string, endpoint: string) {\r\n super(message, 400, endpoint);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n\r\nexport async function parseApiError(response: Response): Promise<UrBackendError> {\r\n const endpoint = new URL(response.url).pathname;\r\n let message = 'An unexpected error occurred';\r\n let data: unknown;\r\n\r\n try {\r\n data = await response.json();\r\n if (typeof data === 'object' && data !== null) {\r\n const errData = data as Record<string, unknown>;\r\n if ('error' in errData) {\r\n let candidate = '';\r\n if (typeof errData.error === 'string') {\r\n candidate = errData.error;\r\n } else if (Array.isArray(errData.error) && errData.error.length > 0) {\r\n candidate = errData.error.map((e: unknown) => {\r\n if (typeof e === 'object' && e !== null && 'message' in e) {\r\n return String((e as Record<string, unknown>).message);\r\n }\r\n return String(e);\r\n }).join(', ');\r\n } else {\r\n candidate = JSON.stringify(errData.error);\r\n }\r\n \r\n if (candidate && candidate.trim().length > 0 && candidate !== '[]' && candidate !== 'null') {\r\n message = candidate;\r\n } else if ('message' in errData) {\r\n message = typeof errData.message === 'string' ? errData.message : JSON.stringify(errData.message);\r\n }\r\n } else if ('message' in errData) {\r\n if (typeof errData.message === 'string') {\r\n message = errData.message;\r\n } else {\r\n message = JSON.stringify(errData.message);\r\n }\r\n }\r\n }\r\n } catch {\r\n // If not JSON, use status text\r\n message = response.statusText || message;\r\n }\r\n\r\n const status = response.status;\r\n\r\n if (status === 401 || status === 403) {\r\n return new AuthError(message, status, endpoint);\r\n }\r\n\r\n if (status === 404) {\r\n return new NotFoundError(message, endpoint);\r\n }\r\n\r\n if (status === 429) {\r\n const retryAfter = response.headers.get('Retry-After');\r\n return new RateLimitError(message, endpoint, retryAfter ? parseInt(retryAfter, 10) : undefined);\r\n }\r\n\r\n if (status === 400) {\r\n return new ValidationError(message, endpoint);\r\n }\r\n\r\n // Default for 5xx or other 4xx\r\n if (endpoint.includes('/api/storage')) {\r\n return new StorageError(message, status, endpoint);\r\n }\r\n\r\n return new UrBackendError(message, status, endpoint);\r\n}\r\n","import { UrBackendClient } from '../client';\r\nimport {\r\n AuthUser,\r\n AuthResponse,\r\n SignUpPayload,\r\n LoginPayload,\r\n UpdateProfilePayload,\r\n ChangePasswordPayload,\r\n VerifyEmailPayload,\r\n ResendOtpPayload,\r\n RequestPasswordResetPayload,\r\n ResetPasswordPayload,\r\n SocialExchangePayload,\r\n SocialExchangeResponse,\r\n RequestOptions,\r\n} from '../types';\r\nimport { AuthError } from '../errors';\r\n\r\n/**\r\n * Module for authentication and user management in urBackend\r\n * \r\n * @class AuthModule\r\n * @description Provides complete authentication functionality including signup, login,\r\n * profile management, password operations, email verification, social authentication,\r\n * and session management. Manages session tokens automatically.\r\n * \r\n * @example\r\n * // Initialize the auth module\r\n * const client = new UrBackendClient({ apiKey: 'pk_live_xxx', secretKey: 'sk_live_xxx' });\r\n * const auth = new AuthModule(client);\r\n * \r\n * // Sign up a new user\r\n * const user = await auth.signUp({\r\n * email: 'user@example.com',\r\n * password: 'securePassword123',\r\n * name: 'John Doe'\r\n * });\r\n * \r\n * @example\r\n * // Log in and manage session\r\n * const session = await auth.login({\r\n * email: 'user@example.com',\r\n * password: 'securePassword123'\r\n * });\r\n * console.log('Access token:', session.accessToken);\r\n * \r\n * // Get current user profile\r\n * const profile = await auth.me();\r\n * console.log('Welcome:', profile.name);\r\n */\r\nexport class AuthModule {\r\n private sessionToken?: string;\r\n\r\n /**\r\n * Creates an instance of AuthModule\r\n * \r\n * @param {UrBackendClient} client - The urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ apiKey: 'pk_live_xxx' });\r\n * const auth = new AuthModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Creates a new user account\r\n * \r\n * @param {SignUpPayload} payload - User registration data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.password - User's password\r\n * @param {string} payload.name - User's full name\r\n * @returns {Promise<AuthUser>} Promise resolving to the created user object\r\n * \r\n * @throws {AuthError} If email already exists\r\n * @throws {AuthError} If password does not meet requirements\r\n * @throws {AuthError} If validation fails\r\n * \r\n * @example\r\n * // Sign up a new user\r\n * const user = await auth.signUp({\r\n * email: 'john@example.com',\r\n * password: 'StrongP@ss123',\r\n * name: 'John Doe'\r\n * });\r\n * console.log('User created:', user._id);\r\n * \r\n * @example\r\n * // Sign up with error handling\r\n * try {\r\n * const user = await auth.signUp({\r\n * email: 'existing@email.com',\r\n * password: 'weak',\r\n * name: 'Test'\r\n * });\r\n * } catch (error) {\r\n * if (error.message.includes('email')) {\r\n * console.log('Email already registered');\r\n * } else if (error.message.includes('password')) {\r\n * console.log('Password too weak');\r\n * }\r\n * }\r\n */\r\n public async signUp(payload: SignUpPayload): Promise<AuthUser> {\r\n return this.client.request<AuthUser>('POST', '/api/userAuth/signup', { body: payload });\r\n }\r\n\r\n /**\r\n * Authenticates an existing user and stores the session token\r\n * \r\n * @param {LoginPayload} payload - User login credentials\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.password - User's password\r\n * @returns {Promise<AuthResponse>} Promise resolving to authentication response with tokens\r\n * \r\n * @throws {AuthError} If credentials are invalid\r\n * @throws {AuthError} If account is locked or not verified\r\n * \r\n * @example\r\n * // Log in a user\r\n * const response = await auth.login({\r\n * email: 'john@example.com',\r\n * password: 'StrongP@ss123'\r\n * });\r\n * console.log('Access token:', response.accessToken);\r\n * \r\n * @example\r\n * // Login with error handling\r\n * try {\r\n * const { accessToken, user } = await auth.login({\r\n * email: 'user@example.com',\r\n * password: 'wrongpassword'\r\n * });\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * console.log('Invalid email or password');\r\n * }\r\n * }\r\n */\r\n public async login(payload: LoginPayload): Promise<AuthResponse> {\r\n const response = await this.client.request<AuthResponse>('POST', '/api/userAuth/login', {\r\n body: payload,\r\n });\r\n\r\n this.sessionToken = response.accessToken || response.token;\r\n\r\n if (!response.accessToken && response.token) {\r\n console.warn(\r\n 'urbackend-sdk: The server returned \"token\" which is deprecated. Please update your backend to return \"accessToken\".',\r\n );\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Retrieves the current authenticated user's profile\r\n * \r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<AuthUser>} Promise resolving to the authenticated user's profile\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If token is invalid or expired\r\n * \r\n * @example\r\n * // Get current user profile (uses stored token from login)\r\n * const user = await auth.me();\r\n * console.log(`Hello ${user.name}, your email is ${user.email}`);\r\n * \r\n * @example\r\n * // Get profile with custom token\r\n * const user = await auth.me(customToken);\r\n * \r\n * @example\r\n * // Get profile with error handling\r\n * try {\r\n * const user = await auth.me();\r\n * console.log('Authenticated as:', user.email);\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * console.log('Please log in again');\r\n * }\r\n * }\r\n */\r\n public async me(token?: string): Promise<AuthUser> {\r\n const activeToken = token || this.sessionToken;\r\n\r\n if (!activeToken) {\r\n throw new AuthError(\r\n 'Authentication token is required for /me endpoint',\r\n 401,\r\n '/api/userAuth/me',\r\n );\r\n }\r\n\r\n return this.client.request<AuthUser>('GET', '/api/userAuth/me', { token: activeToken });\r\n }\r\n\r\n /**\r\n * Updates the current authenticated user's profile\r\n * \r\n * @param {UpdateProfilePayload} payload - Profile data to update\r\n * @param {string} [payload.name] - Updated name\r\n * @param {string} [payload.email] - Updated email (may require re-verification)\r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If token is invalid or expired\r\n * @throws {AuthError} If email is already taken\r\n * \r\n * @example\r\n * // Update user's name\r\n * const result = await auth.updateProfile({ name: 'Jane Smith' });\r\n * console.log(result.message);\r\n * \r\n * @example\r\n * // Update multiple fields\r\n * const result = await auth.updateProfile({\r\n * name: 'Jane Doe',\r\n * email: 'jane@newemail.com'\r\n * });\r\n * \r\n * @example\r\n * // Update with error handling\r\n * try {\r\n * await auth.updateProfile({ email: 'taken@email.com' });\r\n * } catch (error) {\r\n * console.log('Email already in use');\r\n * }\r\n */\r\n public async updateProfile(payload: UpdateProfilePayload, token?: string): Promise<{ message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n if (!activeToken) {\r\n throw new AuthError('Authentication token is required to update profile', 401, '/api/userAuth/update-profile');\r\n }\r\n return this.client.request<{ message: string }>('PUT', '/api/userAuth/update-profile', {\r\n body: payload,\r\n token: activeToken,\r\n });\r\n }\r\n\r\n /**\r\n * Changes the current authenticated user's password\r\n * \r\n * @param {ChangePasswordPayload} payload - Password change data\r\n * @param {string} payload.currentPassword - User's current password\r\n * @param {string} payload.newPassword - Desired new password\r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If current password is incorrect\r\n * @throws {AuthError} If new password does not meet requirements\r\n * \r\n * @example\r\n * // Change password\r\n * const result = await auth.changePassword({\r\n * currentPassword: 'oldPassword123',\r\n * newPassword: 'newStrongP@ss456'\r\n * });\r\n * console.log(result.message);\r\n * \r\n * @example\r\n * // Change password with error handling\r\n * try {\r\n * await auth.changePassword({\r\n * currentPassword: 'wrong',\r\n * newPassword: 'newPassword123'\r\n * });\r\n * } catch (error) {\r\n * if (error.message.includes('current password')) {\r\n * console.log('Current password is incorrect');\r\n * }\r\n * }\r\n */\r\n public async changePassword(payload: ChangePasswordPayload, token?: string): Promise<{ message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n if (!activeToken) {\r\n throw new AuthError('Authentication token is required to change password', 401, '/api/userAuth/change-password');\r\n }\r\n return this.client.request<{ message: string }>('PUT', '/api/userAuth/change-password', {\r\n body: payload,\r\n token: activeToken,\r\n });\r\n }\r\n\r\n /**\r\n * Verifies user's email address using OTP\r\n * \r\n * @param {VerifyEmailPayload} payload - Email verification data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.otp - One-time password sent to email\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If OTP is invalid or expired\r\n * @throws {AuthError} If email is not found\r\n * \r\n * @example\r\n * // Verify email with OTP\r\n * const result = await auth.verifyEmail({\r\n * email: 'user@example.com',\r\n * otp: '123456'\r\n * });\r\n * console.log('Email verified:', result.message);\r\n * \r\n * @example\r\n * // Verify with error handling\r\n * try {\r\n * await auth.verifyEmail({ email: 'user@example.com', otp: '000000' });\r\n * } catch (error) {\r\n * console.log('Invalid OTP. Please try again.');\r\n * }\r\n */\r\n public async verifyEmail(payload: VerifyEmailPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/verify-email', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Resends verification OTP to user's email\r\n * \r\n * @param {ResendOtpPayload} payload - Resend OTP request data\r\n * @param {string} payload.email - User's email address\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If too many attempts\r\n * \r\n * @example\r\n * // Resend verification OTP\r\n * const result = await auth.resendVerificationOtp({\r\n * email: 'user@example.com'\r\n * });\r\n * console.log('OTP resent:', result.message);\r\n */\r\n public async resendVerificationOtp(payload: ResendOtpPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/resend-verification-otp', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Requests a password reset OTP to be sent to user's email\r\n * \r\n * @param {RequestPasswordResetPayload} payload - Password reset request data\r\n * @param {string} payload.email - User's email address\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If too many attempts\r\n * \r\n * @example\r\n * // Request password reset\r\n * const result = await auth.requestPasswordReset({\r\n * email: 'user@example.com'\r\n * });\r\n * console.log('Reset OTP sent:', result.message);\r\n */\r\n public async requestPasswordReset(payload: RequestPasswordResetPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/request-password-reset', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Resets user's password using OTP\r\n * \r\n * @param {ResetPasswordPayload} payload - Password reset data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.otp - One-time password sent via email\r\n * @param {string} payload.newPassword - Desired new password\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If OTP is invalid or expired\r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If new password does not meet requirements\r\n * \r\n * @example\r\n * // Reset password with OTP\r\n * const result = await auth.resetPassword({\r\n * email: 'user@example.com',\r\n * otp: '123456',\r\n * newPassword: 'NewStrongP@ss789'\r\n * });\r\n * console.log('Password reset:', result.message);\r\n * \r\n * @example\r\n * // Reset password with error handling\r\n * try {\r\n * await auth.resetPassword({\r\n * email: 'user@example.com',\r\n * otp: 'wrong',\r\n * newPassword: 'newPass123'\r\n * });\r\n * } catch (error) {\r\n * console.log('Invalid OTP. Please request a new one.');\r\n * }\r\n */\r\n public async resetPassword(payload: ResetPasswordPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/reset-password', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Retrieves a public-safe user profile by username\r\n * \r\n * @param {string} username - Username of the user to fetch\r\n * @returns {Promise<AuthUser>} Promise resolving to public user profile (sensitive fields omitted)\r\n * \r\n * @throws {AuthError} If user with given username does not exist\r\n * \r\n * @example\r\n * // Get public profile\r\n * const profile = await auth.publicProfile('john_doe');\r\n * console.log(`${profile.name} joined on ${profile.createdAt}`);\r\n * \r\n * @example\r\n * // Display user profile on a public page\r\n * try {\r\n * const user = await auth.publicProfile('username');\r\n * // Show user info (no email or private data)\r\n * } catch (error) {\r\n * console.log('User not found');\r\n * }\r\n */\r\n public async publicProfile(username: string): Promise<AuthUser> {\r\n return this.client.request<AuthUser>('GET', `/api/userAuth/public/${username}`);\r\n }\r\n\r\n /**\r\n * Refreshes the access token using refresh token or cookie\r\n * \r\n * @param {string} [refreshToken] - Optional refresh token for header mode. If omitted, uses cookie mode.\r\n * @returns {Promise<AuthResponse>} Promise resolving to new authentication response with fresh tokens\r\n * \r\n * @throws {AuthError} If refresh token is invalid or expired\r\n * \r\n * @example\r\n * // Refresh token using cookie (if configured)\r\n * const newTokens = await auth.refreshToken();\r\n * console.log('New access token:', newTokens.accessToken);\r\n * \r\n * @example\r\n * // Refresh token using explicit refresh token\r\n * const newTokens = await auth.refreshToken(storedRefreshToken);\r\n * \r\n * @example\r\n * // Auto-refresh before API calls\r\n * try {\r\n * await auth.me();\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * await auth.refreshToken();\r\n * // Retry the original request\r\n * }\r\n * }\r\n */\r\n public async refreshToken(refreshToken?: string): Promise<AuthResponse> {\r\n const options: RequestOptions = {};\r\n if (refreshToken) {\r\n options.headers = { 'x-refresh-token': refreshToken, 'x-refresh-token-mode': 'header' };\r\n } else {\r\n options.credentials = 'include';\r\n }\r\n\r\n const response = await this.client.request<AuthResponse>('POST', '/api/userAuth/refresh-token', options);\r\n this.sessionToken = response.accessToken || response.token;\r\n return response;\r\n }\r\n\r\n /**\r\n * Returns the start URL for social authentication\r\n * \r\n * @param {('github' | 'google')} provider - The social authentication provider\r\n * @returns {string} URL to redirect the user's browser to begin the OAuth flow\r\n * \r\n * @example\r\n * // Redirect user to social login page\r\n * const githubUrl = auth.socialStart('github');\r\n * window.location.href = githubUrl;\r\n * \r\n * @example\r\n * // For Node.js backend\r\n * const googleUrl = auth.socialStart('google');\r\n * res.redirect(googleUrl);\r\n */\r\n public socialStart(provider: 'github' | 'google'): string {\r\n return `${this.client.getBaseUrl()}/api/userAuth/social/${provider}/start?key=${this.client.getApiKey()}`;\r\n }\r\n\r\n /**\r\n * Exchanges social authentication rtCode for a refresh token\r\n * \r\n * @param {SocialExchangePayload} payload - Social exchange data\r\n * @param {string} payload.token - Access token fragment from social provider\r\n * @param {string} payload.rtCode - Return code from social provider\r\n * @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response\r\n * \r\n * @throws {AuthError} If rtCode is invalid or expired\r\n * @throws {AuthError} If social provider fails\r\n * \r\n * @example\r\n * // After user returns from social login\r\n * const urlParams = new URLSearchParams(window.location.search);\r\n * const hashParams = new URLSearchParams(window.location.hash.substring(1));\r\n * const rtCode = urlParams.get('rtCode');\r\n * const token = hashParams.get('token');\r\n * if (rtCode && token) {\r\n * const response = await auth.socialExchange({ token, rtCode });\r\n * console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);\r\n * await auth.refreshToken();\r\n * }\r\n */\r\n public async socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse> {\r\n return this.client.request<SocialExchangeResponse>('POST', '/api/userAuth/social/exchange', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Revokes the current session and clears local state\r\n * \r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ success: boolean; message: string }>} Promise resolving to logout status\r\n * \r\n * @example\r\n * // Log out current user\r\n * const result = await auth.logout();\r\n * console.log(result.message);\r\n * // User is now logged out, session token is cleared\r\n * \r\n * @example\r\n * // Log out with custom token\r\n * const result = await auth.logout(customToken);\r\n * \r\n * @example\r\n * // Logout after API calls\r\n * try {\r\n * await auth.logout();\r\n * // Redirect to login page\r\n * window.location.href = '/login';\r\n * } catch (error) {\r\n * console.log('Logout failed, but local session cleared');\r\n * }\r\n */\r\n public async logout(token?: string): Promise<{ success: boolean; message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n let result = { success: true, message: 'Logged out locally' };\r\n\r\n if (activeToken) {\r\n try {\r\n result = await this.client.request<{ success: boolean; message: string }>(\r\n 'POST',\r\n '/api/userAuth/logout',\r\n { token: activeToken, credentials: 'include' },\r\n );\r\n } catch (e) {\r\n // Silently fail if server logout fails, we still want to clear local state\r\n console.warn('urbackend-sdk: Server logout failed', e);\r\n }\r\n }\r\n\r\n this.sessionToken = undefined;\r\n return result;\r\n }\r\n\r\n /**\r\n * Manually sets the session token (e.g., after social authentication exchange)\r\n * \r\n * @param {string} token - The session/access token to store\r\n * \r\n * @example\r\n * // After successful social exchange\r\n * const response = await auth.socialExchange({ rtCode, provider: 'github' });\r\n * auth.setToken(response.accessToken);\r\n * \r\n * @example\r\n * // Restore session from localStorage\r\n * const savedToken = localStorage.getItem('authToken');\r\n * if (savedToken) {\r\n * auth.setToken(savedToken);\r\n * const user = await auth.me();\r\n * }\r\n */\r\n public setToken(token: string): void {\r\n this.sessionToken = token;\r\n }\r\n\r\n /**\r\n * Gets the current stored session token\r\n * \r\n * @returns {string | undefined} The current session token, if any\r\n * \r\n * @example\r\n * // Get token for custom API calls\r\n * const token = auth.getToken();\r\n * if (token) {\r\n * // Use token in custom API request\r\n * fetch('/api/custom', { headers: { Authorization: `Bearer ${token}` } });\r\n * }\r\n * \r\n * @example\r\n * // Save token to localStorage for persistence\r\n * const token = auth.getToken();\r\n * if (token) {\r\n * localStorage.setItem('authToken', token);\r\n * }\r\n */\r\n public getToken(): string | undefined {\r\n return this.sessionToken;\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { DocumentData, InsertPayload, UpdatePayload, PatchPayload, QueryParams } from '../types';\r\nimport { NotFoundError } from '../errors';\r\n\r\n/**\r\n * Module for database operations in urBackend\r\n * \r\n * @class DatabaseModule\r\n * @description Provides CRUD (Create, Read, Update, Delete) operations for collections.\r\n * Supports filtering, pagination, sorting, population, and expansion of related data.\r\n * \r\n * @example\r\n * // Initialize the database module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const db = new DatabaseModule(client);\r\n * \r\n * // Get all users\r\n * const users = await db.getAll('users');\r\n * console.log(users);\r\n * \r\n * @example\r\n * // Insert a new document\r\n * const newUser = await db.insert('users', {\r\n * name: 'John Doe',\r\n * email: 'john@example.com'\r\n * });\r\n * console.log('Created:', newUser._id);\r\n */\r\nexport class DatabaseModule {\r\n /**\r\n * Creates an instance of DatabaseModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const db = new DatabaseModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Fetches all documents from a collection with optional query parameters\r\n * \r\n * @template T - The document type (extends DocumentData)\n * @param {string} collection - Name of the collection to query\n * @param {QueryParams} [params={}] - Optional query parameters for filtering, sorting, pagination\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<T[]>} Promise resolving to an array of documents (empty array if none found)\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If query parameters are malformed\r\n * \r\n * @example\r\n * // Get all users\r\n * const users = await db.getAll('users');\r\n * \r\n * @example\r\n * // Get users with filters and pagination\r\n * const activeUsers = await db.getAll('users', {\r\n * filter: { status: 'active' },\r\n * limit: 10,\r\n * skip: 0,\r\n * sort: '-createdAt'\r\n * });\r\n * \r\n * @example\r\n * // Get users with populated relations\r\n * const usersWithPosts = await db.getAll('users', {\r\n * populate: ['posts'],\r\n * expand: ['profile']\r\n * });\r\n */\r\n public async getAll<T extends DocumentData>(\n collection: string,\n params: QueryParams = {},\n token?: string\n ): Promise<T[]> {\n const queryString = this.buildQueryString(params);\n const path = `/api/data/${collection}${queryString}`;\n \n try {\n const result = await this.client.request<T[] | { items?: T[] }>('GET', path, { token });\n\n if (Array.isArray(result)) {\n return result;\n }\n\n if (result && typeof result === 'object' && Array.isArray(result.items)) {\n return result.items;\n }\n\n return [] as T[];\n } catch (e) {\n if (e instanceof NotFoundError) {\n return [] as T[];\n }\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Counts documents in a collection with optional filters\r\n * \r\n * @param {string} collection - Name of the collection to count\n * @param {Omit<QueryParams, 'count'>} [params={}] - Optional filter parameters\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<number>} Promise resolving to the total count of matching documents\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Count all users\r\n * const totalUsers = await db.count('users');\r\n * console.log(`Total users: ${totalUsers}`);\r\n * \r\n * @example\r\n * // Count users with filter\r\n * const activeUsers = await db.count('users', {\r\n * filter: { status: 'active' }\r\n * });\r\n * \r\n * @example\r\n * // Count for pagination\r\n * const total = await db.count('products', {\r\n * filter: { category: 'electronics' }\r\n * });\r\n * const totalPages = Math.ceil(total / 10);\r\n */\r\n public async count(\n collection: string,\n params: Omit<QueryParams, 'count'> = {},\n token?: string\n ): Promise<number> {\n const queryString = this.buildQueryString({ ...params, count: 'true' });\n const path = `/api/data/${collection}${queryString}`;\n const result = await this.client.request<{ count: number }>('GET', path, { token });\n return result.count;\n }\n\r\n /**\r\n * Fetches a single document by its ID\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {Object} [options={}] - Optional parameters\n * @param {string|string[]} [options.populate] - Fields to populate with related data\n * @param {string|string[]} [options.expand] - Fields to expand with nested data\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<T>} Promise resolving to the document\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Get user by ID\r\n * const user = await db.getOne('users', 'user_123');\r\n * console.log(user.name);\r\n * \r\n * @example\r\n * // Get user with populated posts\r\n * const userWithPosts = await db.getOne('users', 'user_123', {\r\n * populate: ['posts', 'comments']\r\n * });\r\n * \r\n * @example\r\n * // Get with error handling\r\n * try {\r\n * const user = await db.getOne('users', 'non_existent_id');\r\n * } catch (error) {\r\n * if (error instanceof NotFoundError) {\r\n * console.log('User not found');\r\n * }\r\n * }\r\n */\r\n public async getOne<T extends DocumentData>(\n collection: string, \n id: string, \n options: { populate?: string | string[]; expand?: string | string[] } = {},\n token?: string\n ): Promise<T> {\n const queryString = this.buildQueryString(options);\n return this.client.request<T>('GET', `/api/data/${collection}/${id}${queryString}`, { token });\n }\n\r\n /**\r\n * Inserts a new document into a collection\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {InsertPayload} data - Document data to insert\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the created document with generated ID\r\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If unique constraint violation occurs\r\n * \r\n * @example\r\n * // Insert a new user\r\n * const newUser = await db.insert('users', {\r\n * name: 'John Doe',\r\n * email: 'john@example.com',\r\n * age: 25\r\n * });\r\n * console.log('User created:', newUser._id);\r\n * \r\n * @example\r\n * // Insert with custom token\r\n * const result = await db.insert('posts', {\r\n * title: 'My Post',\r\n * content: 'Hello World'\r\n * }, customAuthToken);\r\n * \r\n * @example\r\n * // Insert with error handling\r\n * try {\r\n * const user = await db.insert('users', { email: 'existing@email.com' });\r\n * } catch (error) {\r\n * if (error.message.includes('duplicate')) {\r\n * console.log('Email already exists');\r\n * }\r\n * }\r\n */\r\n public async insert<T extends DocumentData>(\r\n collection: string, \r\n data: InsertPayload, \r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('POST', `/api/data/${collection}`, { \r\n body: data,\r\n token \r\n });\r\n }\r\n\r\n /**\r\n * Updates an existing document by its ID (full replacement)\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {UpdatePayload} data - Complete document data for replacement\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the updated document\r\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Full update of a user\r\n * const updatedUser = await db.update('users', 'user_123', {\r\n * name: 'Jane Doe',\r\n * email: 'jane@example.com',\r\n * age: 26\r\n * });\r\n * \r\n * @example\r\n * // Update with error handling\r\n * try {\r\n * const result = await db.update('users', 'user_123', updatedData);\r\n * console.log('Update successful:', result);\r\n * } catch (error) {\r\n * if (error instanceof NotFoundError) {\r\n * console.log('User not found');\r\n * }\r\n * }\r\n */\r\n public async update<T extends DocumentData>(\r\n collection: string,\r\n id: string,\r\n data: UpdatePayload,\r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('PUT', `/api/data/${collection}/${id}`, { \r\n body: data,\r\n token\r\n });\r\n }\r\n\r\n /**\r\n * Partially updates an existing document by its ID (only provided fields)\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {PatchPayload} data - Partial data to update\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the updated document\r\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Partial update - only update age\r\n * const updatedUser = await db.patch('users', 'user_123', {\r\n * age: 26\r\n * });\r\n * \r\n * @example\r\n * // Add a new field to document\r\n * const result = await db.patch('users', 'user_123', {\r\n * lastLogin: new Date().toISOString()\r\n * });\r\n * \r\n * @example\r\n * // Partial update with error handling\r\n * try {\r\n * const result = await db.patch('products', 'prod_123', {\r\n * price: 29.99\r\n * });\r\n * console.log('Price updated:', result);\r\n * } catch (error) {\r\n * console.error('Update failed:', error.message);\r\n * }\r\n */\r\n public async patch<T extends DocumentData>(\r\n collection: string,\r\n id: string,\r\n data: PatchPayload,\r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('PATCH', `/api/data/${collection}/${id}`, { \r\n body: data,\r\n token\r\n });\r\n }\r\n\r\n /**\r\n * Deletes a document by its ID\r\n * \r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document to delete\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status\r\n * \r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If user lacks permission to delete\r\n * \r\n * @example\r\n * // Delete a user\r\n * const result = await db.delete('users', 'user_123');\r\n * if (result.deleted) {\r\n * console.log('User deleted successfully');\r\n * }\r\n * \r\n * @example\r\n * // Delete with error handling\r\n * try {\r\n * const { deleted } = await db.delete('posts', 'post_456');\r\n * if (deleted) {\r\n * console.log('Post removed');\r\n * }\r\n * } catch (error) {\r\n * console.error('Deletion failed:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Delete after checking existence\r\n * const exists = await db.getOne('users', 'user_123').catch(() => null);\r\n * if (exists) {\r\n * await db.delete('users', 'user_123');\r\n * console.log('User deleted');\r\n * }\r\n */\r\n public async delete(collection: string, id: string, token?: string): Promise<{ deleted: boolean }> {\r\n const result = await this.client.request<{ message?: string; id?: string } | null>(\r\n 'DELETE',\r\n `/api/data/${collection}/${id}`,\r\n { token },\r\n );\r\n\r\n const deleted =\r\n typeof result === 'object' &&\r\n result !== null &&\r\n (result.id === id || result.message === 'Document deleted');\r\n\r\n return { deleted };\r\n }\r\n\r\n /**\r\n * Internal helper to build query string from QueryParams\r\n * \r\n * @param {QueryParams} params - Query parameters to convert\r\n * @returns {string} URL query string (starting with '?' if parameters exist, otherwise empty)\r\n * \r\n * @internal\r\n * @private\r\n * \r\n * @example\r\n * // Returns \"?limit=10&sort=-createdAt\"\r\n * buildQueryString({ limit: 10, sort: '-createdAt' })\r\n * \r\n * @example\r\n * // Returns \"?status=active&age=25\"\r\n * buildQueryString({ filter: { status: 'active', age: 25 } })\r\n */\r\n private buildQueryString(params: QueryParams): string {\r\n const searchParams = new URLSearchParams();\r\n\r\n Object.entries(params).forEach(([key, value]) => {\r\n if (value === undefined || value === null) return;\r\n\r\n if (key === 'filter' && typeof value === 'object') {\r\n Object.entries(value as Record<string, unknown>).forEach(([fKey, fValue]) => {\r\n if (fValue !== undefined && fValue !== null) {\r\n searchParams.append(fKey, String(fValue));\r\n }\r\n });\r\n } else if ((key === 'populate' || key === 'expand') && Array.isArray(value)) {\r\n searchParams.append(key, value.join(','));\r\n } else {\r\n searchParams.append(key, String(value));\r\n }\r\n });\r\n\r\n const str = searchParams.toString();\r\n return str ? `?${str}` : '';\r\n }\r\n}\n","/// <reference lib=\"dom\" />\r\nimport { UrBackendClient } from '../client';\r\nimport { UploadResponse } from '../types';\r\n\r\n/**\r\n * Module for handling file storage operations in urBackend\r\n * \r\n * @class StorageModule\r\n * @description Provides methods to upload and delete files in the urBackend storage system.\r\n * Supports both browser (File/Blob) and Node.js (Buffer) environments.\r\n * \r\n * @example\r\n * // Initialize the storage module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const storage = new StorageModule(client);\r\n * \r\n * // Upload a file (Browser)\r\n * const fileInput = document.getElementById('fileInput');\r\n * const result = await storage.upload(fileInput.files[0], 'my-file.pdf');\r\n * console.log(result.url);\r\n * \r\n * @example\r\n * // Upload a file (Node.js)\r\n * const fs = require('fs');\r\n * const buffer = fs.readFileSync('./document.pdf');\r\n * const result = await storage.upload(buffer, 'document.pdf');\r\n */\r\nexport class StorageModule {\r\n /**\r\n * Creates an instance of StorageModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const storage = new StorageModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Uploads a file to the urBackend storage\r\n * \r\n * @param {unknown} file - The file to upload. Supports:\r\n * - Browser: File, Blob\r\n * - Node.js: Buffer\r\n * @param {string} [filename] - Optional custom filename for the uploaded file\r\n * @returns {Promise<UploadResponse>} Promise resolving to upload details including URL and file ID\r\n * \r\n * @throws {Error} If file is invalid or missing\r\n * @throws {Error} If file size exceeds limits\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If storage quota is exceeded\r\n * \r\n * @example\r\n * // Browser: Upload from file input\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * const result = await storage.upload(file, 'custom-name.pdf');\r\n * console.log('File URL:', result.url);\r\n * \r\n * @example\r\n * // Node.js: Upload Buffer\r\n * const fs = require('fs');\r\n * const buffer = fs.readFileSync('./image.png');\r\n * const result = await storage.upload(buffer, 'image.png');\r\n * console.log('Uploaded:', result.fileId);\r\n * \r\n * @example\r\n * // Upload without custom filename (uses original name)\r\n * const result = await storage.upload(file);\r\n * \r\n * @example\r\n * // Upload with error handling\r\n * try {\r\n * const result = await storage.upload(file, 'document.pdf');\r\n * console.log('Upload successful:', result.url);\r\n * } catch (error) {\r\n * console.error('Upload failed:', error.message);\r\n * // Handle error: retry, show user message, etc.\r\n * }\r\n */\r\n public async upload(file: unknown, filename?: string): Promise<UploadResponse> {\r\n // figure out name, contentType and size depending on environment\r\n let resolvedName = filename || \"file\";\r\n let contentType = \"application/octet-stream\";\r\n let fileSize: number;\r\n let fileData: Blob | BufferSource;\r\n\r\n if (typeof File !== \"undefined\" && file instanceof File) {\r\n // browser File object\r\n resolvedName = filename || file.name;\r\n contentType = file.type || contentType;\r\n fileSize = file.size;\r\n fileData = file;\r\n } else if (file instanceof Blob) {\r\n contentType = file.type || contentType;\r\n fileSize = file.size;\r\n fileData = file;\r\n } else if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(file)) {\r\n // Node.js Buffer\r\n fileSize = (file as Buffer).length;\r\n fileData = file as unknown as BufferSource;\r\n } else {\r\n throw new Error(\"Unsupported file type. Pass a File, Blob, or Buffer.\");\r\n }\r\n\r\n // step 1 — ask server for a signed URL\r\n const { signedUrl, filePath } = await this.client.request<{ signedUrl: string; filePath: string }>(\r\n \"POST\",\r\n \"/api/storage/upload-request\",\r\n { body: { filename: resolvedName, contentType, size: fileSize } }\r\n );\r\n\r\n // step 2 — upload directly to cloud, server not involved\r\n const putResponse = await fetch(signedUrl, {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": contentType },\r\n body: fileData as BodyInit,\r\n });\r\n\r\n if (!putResponse.ok) {\r\n throw new Error(`Direct upload to cloud failed: ${putResponse.status} ${putResponse.statusText}`);\r\n }\r\n\r\n // step 3 — tell server we're done so it can verify + update quota\r\n return this.client.request<UploadResponse>(\r\n \"POST\",\r\n \"/api/storage/upload-confirm\",\r\n { body: { filePath, size: fileSize } }\r\n );\r\n}\r\n /**\r\n * Deletes a file from storage by its path\r\n * \r\n * @param {string} path - The file path or URL of the file to delete\r\n * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status\r\n * \r\n * @throws {Error} If path is empty or invalid\r\n * @throws {Error} If file does not exist\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If user lacks permission to delete the file\r\n * \r\n * @example\r\n * // Delete a file by path\r\n * const result = await storage.deleteFile('uploads/document.pdf');\r\n * if (result.deleted) {\r\n * console.log('File deleted successfully');\r\n * }\r\n * \r\n * @example\r\n * // Delete with error handling\r\n * try {\r\n * const result = await storage.deleteFile('uploads/old-file.jpg');\r\n * console.log('Deleted:', result.deleted);\r\n * } catch (error) {\r\n * console.error('Deletion failed:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Delete after upload\r\n * const uploadResult = await storage.upload(file, 'temp-file.pdf');\r\n * console.log('Uploaded:', uploadResult.url);\r\n * \r\n * // Later, delete the file\r\n * await storage.deleteFile('temp-file.pdf');\r\n * console.log('File cleaned up');\r\n */\r\n public async deleteFile(path: string): Promise<{ deleted: boolean }> {\r\n return this.client.request<{ deleted: boolean }>('DELETE', '/api/storage/file', {\r\n body: { path },\r\n });\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { CollectionSchema } from '../types';\r\n\r\n/**\r\n * Module for managing database schemas in urBackend\r\n * \r\n * @class SchemaModule\r\n * @description Provides methods to fetch and manage collection schema definitions.\r\n * Schemas define the structure, validation rules, and data types for collections.\r\n * \r\n * @example\r\n * // Initialize the schema module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const schema = new SchemaModule(client);\r\n * \r\n * // Get schema for a collection\r\n * const collectionSchema = await schema.getSchema('users');\r\n * console.log(collectionSchema.fields);\r\n */\r\nexport class SchemaModule {\r\n /**\r\n * Creates an instance of SchemaModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const schema = new SchemaModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Fetches the schema definition for a specific collection\r\n * \r\n * @param {string} collection - Name of the collection to fetch schema for\r\n * @returns {Promise<CollectionSchema>} Promise resolving to the collection schema definition\r\n * \r\n * @throws {Error} If collection name is empty or contains only whitespace\r\n * @throws {Error} If collection does not exist\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Get schema for users collection\r\n * const userSchema = await schema.getSchema('users');\r\n * console.log(userSchema.fields);\r\n * \r\n * @example\r\n * // Get schema for products collection with error handling\r\n * try {\r\n * const productSchema = await schema.getSchema('products');\r\n * console.log('Schema fields:', Object.keys(productSchema.fields));\r\n * } catch (error) {\r\n * console.error('Failed to fetch schema:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Validate collection name before fetching\r\n * const collectionName = 'my_collection';\r\n * if (collectionName.trim()) {\r\n * const schemaDef = await schema.getSchema(collectionName);\r\n * // Use schema definition\r\n * }\r\n */\r\n public async getSchema(collection: string): Promise<CollectionSchema> {\r\n const trimmedCollection = collection.trim();\r\n if (trimmedCollection === '') {\r\n throw new Error('Collection name cannot be empty or whitespace-only');\r\n }\r\n\r\n const encodedCollection = encodeURIComponent(trimmedCollection);\r\n const response = await this.client.request<{\r\n message: string;\r\n collection: CollectionSchema;\r\n }>('GET', `/api/schemas/${encodedCollection}`);\r\n\r\n return response.collection;\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { SendMailPayload, SendMailResponse } from '../types';\r\n\r\n/**\r\n * Module for handling email operations in urBackend\r\n * \r\n * @class MailModule\r\n * @description Provides methods to send emails using the urBackend mail service.\r\n * Requires a Secret Key (sk_live_...) and should be called from a server environment.\r\n * \r\n * @example\r\n * // Initialize the mail module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const mail = new MailModule(client);\r\n * \r\n * // Send an email\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Welcome!',\r\n * html: '<h1>Hello World</h1>'\r\n * });\r\n */\r\nexport class MailModule {\r\n /**\r\n * Creates an instance of MailModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const mail = new MailModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Sends an email using the urBackend mail service\r\n * \r\n * @param {SendMailPayload} payload - The email content and configuration\r\n * @param {string} payload.to - Recipient email address\r\n * @param {string} payload.subject - Email subject line\r\n * @param {string} payload.html - HTML content of the email\r\n * @param {string} [payload.from] - Optional sender email address (defaults to configured sender)\r\n * @param {string[]} [payload.cc] - Optional CC recipient email addresses\r\n * @param {string[]} [payload.bcc] - Optional BCC recipient email addresses\r\n * @returns {Promise<SendMailResponse>} Promise resolving to email sending status and message ID\r\n * \r\n * @throws {Error} If secret key is missing or invalid\r\n * @throws {Error} If email validation fails\r\n * @throws {Error} If rate limit is exceeded\r\n * \r\n * @example\r\n * // Send a basic email\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Welcome to urBackend',\r\n * html: '<h1>Welcome!</h1><p>Thanks for joining.</p>'\r\n * });\r\n * console.log(result.messageId);\r\n * \r\n * @example\r\n * // Send an email with CC and custom sender\r\n * const result = await mail.send({\r\n * from: 'noreply@myapp.com',\r\n * to: 'user@example.com',\r\n * cc: ['admin@example.com'],\r\n * subject: 'Important Update',\r\n * html: '<p>Your account has been updated.</p>'\r\n * });\r\n * \r\n * @example\r\n * // Send email with error handling\r\n * try {\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Test',\r\n * html: '<p>Test email</p>'\r\n * });\r\n * console.log('Email sent:', result);\r\n * } catch (error) {\r\n * console.error('Failed to send email:', error);\r\n * }\r\n */\r\n public async send(payload: SendMailPayload): Promise<SendMailResponse> {\r\n return this.client.request<SendMailResponse>('POST', '/api/mail/send', {\r\n body: payload,\r\n });\r\n }\r\n}","import { UrBackendConfig, RequestOptions } from './types';\r\nimport { UrBackendError, parseApiError } from './errors';\r\nimport { AuthModule } from './modules/auth';\r\nimport { DatabaseModule } from './modules/database';\r\nimport { StorageModule } from './modules/storage';\r\nimport { SchemaModule } from './modules/schema';\r\nimport { MailModule } from './modules/mail';\r\n\r\nexport class UrBackendClient {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private _auth?: AuthModule;\r\n private _db?: DatabaseModule;\r\n private _storage?: StorageModule;\r\n private _schema?: SchemaModule;\r\n private _mail?: MailModule;\r\n private headers: Record<string, string>;\r\n\r\n constructor(config: UrBackendConfig) {\r\n if (!config.apiKey) {\r\n throw new Error('urbackend-sdk: apiKey is required to initialize the client.');\r\n }\r\n\r\n this.apiKey = config.apiKey;\r\n this.baseUrl = config.baseUrl || 'https://api.ub.bitbros.in';\r\n this.headers = config.headers || {};\r\n\r\n if (typeof window !== 'undefined' && this.apiKey.startsWith('sk_live_')) {\r\n console.warn(\r\n '⚠️ urbackend-sdk: Avoid exposing your Secret Key (sk_live_...) in client-side code. This can lead to unauthorized access to your account and data. Use your Publishable Key (pk_live_...) instead.',\r\n );\r\n }\r\n }\r\n\r\n get auth(): AuthModule {\r\n if (!this._auth) {\r\n this._auth = new AuthModule(this);\r\n }\r\n return this._auth;\r\n }\r\n\r\n get db(): DatabaseModule {\r\n if (!this._db) {\r\n this._db = new DatabaseModule(this);\r\n }\r\n return this._db;\r\n }\r\n\r\n get storage(): StorageModule {\r\n if (!this._storage) {\r\n this._storage = new StorageModule(this);\r\n }\r\n return this._storage;\r\n }\r\n\r\n get schema(): SchemaModule {\r\n if (!this._schema) {\r\n this._schema = new SchemaModule(this);\r\n }\r\n return this._schema;\r\n }\r\n\r\n get mail(): MailModule {\r\n if (!this._mail) {\r\n this._mail = new MailModule(this);\r\n }\r\n return this._mail;\r\n }\r\n\r\n public getBaseUrl(): string {\r\n return this.baseUrl;\r\n }\r\n\r\n public getApiKey(): string {\r\n return this.apiKey;\r\n }\r\n\r\n /**\r\n * Internal request handler\r\n */\r\n public async request<T>(\r\n method: string,\r\n path: string,\r\n options: RequestOptions = {},\r\n ): Promise<T> {\r\n const url = `${this.baseUrl}${path}`;\r\n const headers: Record<string, string> = {\r\n 'x-api-key': this.apiKey,\r\n 'User-Agent': `urbackend-sdk-js/0.4.2`,\r\n ...this.headers,\r\n };\r\n\r\n if (options.token) {\r\n headers['Authorization'] = `Bearer ${options.token}`;\r\n }\r\n\r\n // Merge custom headers from options if provided\r\n if (options.headers) {\r\n Object.assign(headers, options.headers);\r\n }\r\n\r\n let requestBody: BodyInit | undefined;\r\n\r\n if (options.isMultipart) {\r\n // Fetch handles FormData content type and boundary\r\n requestBody = options.body as FormData;\r\n } else if (options.body) {\r\n headers['Content-Type'] = 'application/json';\r\n requestBody = JSON.stringify(options.body);\r\n }\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method,\r\n headers,\r\n body: requestBody,\r\n credentials: options.credentials,\r\n });\r\n\r\n if (!response.ok) {\r\n throw await parseApiError(response);\r\n }\r\n\r\n const contentType = response.headers.get('content-type');\r\n if (contentType && contentType.includes('application/json')) {\r\n const json = await response.json();\r\n // The API returns { data, success, message }\r\n // If data is present, return it. If success/message are present but no data, return the whole object (for exchange/logout etc)\r\n if (json.data !== undefined) {\r\n return json.data;\r\n }\r\n return json;\r\n }\r\n\r\n return (await response.text()) as unknown as T;\r\n } catch (error) {\r\n if (error instanceof UrBackendError) {\r\n throw error;\r\n }\r\n throw new UrBackendError(\r\n error instanceof Error ? error.message : 'Network request failed',\r\n 0,\r\n path,\r\n );\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -537,8 +537,8 @@ declare class AuthModule {
|
|
|
537
537
|
* Exchanges social authentication rtCode for a refresh token
|
|
538
538
|
*
|
|
539
539
|
* @param {SocialExchangePayload} payload - Social exchange data
|
|
540
|
+
* @param {string} payload.token - Access token fragment from social provider
|
|
540
541
|
* @param {string} payload.rtCode - Return code from social provider
|
|
541
|
-
* @param {string} payload.provider - Social provider ('github' or 'google')
|
|
542
542
|
* @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response
|
|
543
543
|
*
|
|
544
544
|
* @throws {AuthError} If rtCode is invalid or expired
|
|
@@ -546,13 +546,14 @@ declare class AuthModule {
|
|
|
546
546
|
*
|
|
547
547
|
* @example
|
|
548
548
|
* // After user returns from social login
|
|
549
|
-
* const
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
* });
|
|
555
|
-
* console.log('
|
|
549
|
+
* const urlParams = new URLSearchParams(window.location.search);
|
|
550
|
+
* const hashParams = new URLSearchParams(window.location.hash.substring(1));
|
|
551
|
+
* const rtCode = urlParams.get('rtCode');
|
|
552
|
+
* const token = hashParams.get('token');
|
|
553
|
+
* if (rtCode && token) {
|
|
554
|
+
* const response = await auth.socialExchange({ token, rtCode });
|
|
555
|
+
* console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);
|
|
556
|
+
* await auth.refreshToken();
|
|
556
557
|
* }
|
|
557
558
|
*/
|
|
558
559
|
socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse>;
|
package/dist/index.d.ts
CHANGED
|
@@ -537,8 +537,8 @@ declare class AuthModule {
|
|
|
537
537
|
* Exchanges social authentication rtCode for a refresh token
|
|
538
538
|
*
|
|
539
539
|
* @param {SocialExchangePayload} payload - Social exchange data
|
|
540
|
+
* @param {string} payload.token - Access token fragment from social provider
|
|
540
541
|
* @param {string} payload.rtCode - Return code from social provider
|
|
541
|
-
* @param {string} payload.provider - Social provider ('github' or 'google')
|
|
542
542
|
* @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response
|
|
543
543
|
*
|
|
544
544
|
* @throws {AuthError} If rtCode is invalid or expired
|
|
@@ -546,13 +546,14 @@ declare class AuthModule {
|
|
|
546
546
|
*
|
|
547
547
|
* @example
|
|
548
548
|
* // After user returns from social login
|
|
549
|
-
* const
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
* });
|
|
555
|
-
* console.log('
|
|
549
|
+
* const urlParams = new URLSearchParams(window.location.search);
|
|
550
|
+
* const hashParams = new URLSearchParams(window.location.hash.substring(1));
|
|
551
|
+
* const rtCode = urlParams.get('rtCode');
|
|
552
|
+
* const token = hashParams.get('token');
|
|
553
|
+
* if (rtCode && token) {
|
|
554
|
+
* const response = await auth.socialExchange({ token, rtCode });
|
|
555
|
+
* console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);
|
|
556
|
+
* await auth.refreshToken();
|
|
556
557
|
* }
|
|
557
558
|
*/
|
|
558
559
|
socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse>;
|
package/dist/index.mjs
CHANGED
|
@@ -45,8 +45,34 @@ async function parseApiError(response) {
|
|
|
45
45
|
let data;
|
|
46
46
|
try {
|
|
47
47
|
data = await response.json();
|
|
48
|
-
if (typeof data === "object" && data !== null
|
|
49
|
-
|
|
48
|
+
if (typeof data === "object" && data !== null) {
|
|
49
|
+
const errData = data;
|
|
50
|
+
if ("error" in errData) {
|
|
51
|
+
let candidate = "";
|
|
52
|
+
if (typeof errData.error === "string") {
|
|
53
|
+
candidate = errData.error;
|
|
54
|
+
} else if (Array.isArray(errData.error) && errData.error.length > 0) {
|
|
55
|
+
candidate = errData.error.map((e) => {
|
|
56
|
+
if (typeof e === "object" && e !== null && "message" in e) {
|
|
57
|
+
return String(e.message);
|
|
58
|
+
}
|
|
59
|
+
return String(e);
|
|
60
|
+
}).join(", ");
|
|
61
|
+
} else {
|
|
62
|
+
candidate = JSON.stringify(errData.error);
|
|
63
|
+
}
|
|
64
|
+
if (candidate && candidate.trim().length > 0 && candidate !== "[]" && candidate !== "null") {
|
|
65
|
+
message = candidate;
|
|
66
|
+
} else if ("message" in errData) {
|
|
67
|
+
message = typeof errData.message === "string" ? errData.message : JSON.stringify(errData.message);
|
|
68
|
+
}
|
|
69
|
+
} else if ("message" in errData) {
|
|
70
|
+
if (typeof errData.message === "string") {
|
|
71
|
+
message = errData.message;
|
|
72
|
+
} else {
|
|
73
|
+
message = JSON.stringify(errData.message);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
50
76
|
}
|
|
51
77
|
} catch {
|
|
52
78
|
message = response.statusText || message;
|
|
@@ -499,8 +525,8 @@ var AuthModule = class {
|
|
|
499
525
|
* Exchanges social authentication rtCode for a refresh token
|
|
500
526
|
*
|
|
501
527
|
* @param {SocialExchangePayload} payload - Social exchange data
|
|
528
|
+
* @param {string} payload.token - Access token fragment from social provider
|
|
502
529
|
* @param {string} payload.rtCode - Return code from social provider
|
|
503
|
-
* @param {string} payload.provider - Social provider ('github' or 'google')
|
|
504
530
|
* @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response
|
|
505
531
|
*
|
|
506
532
|
* @throws {AuthError} If rtCode is invalid or expired
|
|
@@ -508,13 +534,14 @@ var AuthModule = class {
|
|
|
508
534
|
*
|
|
509
535
|
* @example
|
|
510
536
|
* // After user returns from social login
|
|
511
|
-
* const
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
* });
|
|
517
|
-
* console.log('
|
|
537
|
+
* const urlParams = new URLSearchParams(window.location.search);
|
|
538
|
+
* const hashParams = new URLSearchParams(window.location.hash.substring(1));
|
|
539
|
+
* const rtCode = urlParams.get('rtCode');
|
|
540
|
+
* const token = hashParams.get('token');
|
|
541
|
+
* if (rtCode && token) {
|
|
542
|
+
* const response = await auth.socialExchange({ token, rtCode });
|
|
543
|
+
* console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);
|
|
544
|
+
* await auth.refreshToken();
|
|
518
545
|
* }
|
|
519
546
|
*/
|
|
520
547
|
async socialExchange(payload) {
|
|
@@ -1235,6 +1262,9 @@ var MailModule = class {
|
|
|
1235
1262
|
// src/client.ts
|
|
1236
1263
|
var UrBackendClient = class {
|
|
1237
1264
|
constructor(config) {
|
|
1265
|
+
if (!config.apiKey) {
|
|
1266
|
+
throw new Error("urbackend-sdk: apiKey is required to initialize the client.");
|
|
1267
|
+
}
|
|
1238
1268
|
this.apiKey = config.apiKey;
|
|
1239
1269
|
this.baseUrl = config.baseUrl || "https://api.ub.bitbros.in";
|
|
1240
1270
|
this.headers = config.headers || {};
|
|
@@ -1287,7 +1317,7 @@ var UrBackendClient = class {
|
|
|
1287
1317
|
const url = `${this.baseUrl}${path}`;
|
|
1288
1318
|
const headers = {
|
|
1289
1319
|
"x-api-key": this.apiKey,
|
|
1290
|
-
"User-Agent": `urbackend-sdk-js/0.4.
|
|
1320
|
+
"User-Agent": `urbackend-sdk-js/0.4.2`,
|
|
1291
1321
|
...this.headers
|
|
1292
1322
|
};
|
|
1293
1323
|
if (options.token) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/modules/auth.ts","../src/modules/database.ts","../src/modules/storage.ts","../src/modules/schema.ts","../src/modules/mail.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["export class UrBackendError extends Error {\r\n constructor(\r\n public message: string,\r\n public statusCode: number,\r\n public endpoint: string,\r\n ) {\r\n super(message);\r\n this.name = 'UrBackendError';\r\n }\r\n}\r\n\r\nexport class AuthError extends UrBackendError {\r\n constructor(message: string, statusCode: number, endpoint: string) {\r\n super(message, statusCode, endpoint);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\nexport class NotFoundError extends UrBackendError {\r\n constructor(message: string, endpoint: string) {\r\n super(message, 404, endpoint);\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\nexport class RateLimitError extends UrBackendError {\r\n public retryAfter?: number;\r\n\r\n constructor(message: string, endpoint: string, retryAfter?: number) {\r\n super(message, 429, endpoint);\r\n this.name = 'RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class StorageError extends UrBackendError {\r\n constructor(message: string, statusCode: number, endpoint: string) {\r\n super(message, statusCode, endpoint);\r\n this.name = 'StorageError';\r\n }\r\n}\r\n\r\nexport class ValidationError extends UrBackendError {\r\n constructor(message: string, endpoint: string) {\r\n super(message, 400, endpoint);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n\r\nexport async function parseApiError(response: Response): Promise<UrBackendError> {\r\n const endpoint = new URL(response.url).pathname;\r\n let message = 'An unexpected error occurred';\r\n let data: unknown;\r\n\r\n try {\r\n data = await response.json();\r\n if (typeof data === 'object' && data !== null && 'message' in data) {\r\n message = (data as { message: string }).message || message;\r\n }\r\n } catch {\r\n // If not JSON, use status text\r\n message = response.statusText || message;\r\n }\r\n\r\n const status = response.status;\r\n\r\n if (status === 401 || status === 403) {\r\n return new AuthError(message, status, endpoint);\r\n }\r\n\r\n if (status === 404) {\r\n return new NotFoundError(message, endpoint);\r\n }\r\n\r\n if (status === 429) {\r\n const retryAfter = response.headers.get('Retry-After');\r\n return new RateLimitError(message, endpoint, retryAfter ? parseInt(retryAfter, 10) : undefined);\r\n }\r\n\r\n if (status === 400) {\r\n return new ValidationError(message, endpoint);\r\n }\r\n\r\n // Default for 5xx or other 4xx\r\n if (endpoint.includes('/api/storage')) {\r\n return new StorageError(message, status, endpoint);\r\n }\r\n\r\n return new UrBackendError(message, status, endpoint);\r\n}\r\n","import { UrBackendClient } from '../client';\r\nimport {\r\n AuthUser,\r\n AuthResponse,\r\n SignUpPayload,\r\n LoginPayload,\r\n UpdateProfilePayload,\r\n ChangePasswordPayload,\r\n VerifyEmailPayload,\r\n ResendOtpPayload,\r\n RequestPasswordResetPayload,\r\n ResetPasswordPayload,\r\n SocialExchangePayload,\r\n SocialExchangeResponse,\r\n RequestOptions,\r\n} from '../types';\r\nimport { AuthError } from '../errors';\r\n\r\n/**\r\n * Module for authentication and user management in urBackend\r\n * \r\n * @class AuthModule\r\n * @description Provides complete authentication functionality including signup, login,\r\n * profile management, password operations, email verification, social authentication,\r\n * and session management. Manages session tokens automatically.\r\n * \r\n * @example\r\n * // Initialize the auth module\r\n * const client = new UrBackendClient({ apiKey: 'pk_live_xxx', secretKey: 'sk_live_xxx' });\r\n * const auth = new AuthModule(client);\r\n * \r\n * // Sign up a new user\r\n * const user = await auth.signUp({\r\n * email: 'user@example.com',\r\n * password: 'securePassword123',\r\n * name: 'John Doe'\r\n * });\r\n * \r\n * @example\r\n * // Log in and manage session\r\n * const session = await auth.login({\r\n * email: 'user@example.com',\r\n * password: 'securePassword123'\r\n * });\r\n * console.log('Access token:', session.accessToken);\r\n * \r\n * // Get current user profile\r\n * const profile = await auth.me();\r\n * console.log('Welcome:', profile.name);\r\n */\r\nexport class AuthModule {\r\n private sessionToken?: string;\r\n\r\n /**\r\n * Creates an instance of AuthModule\r\n * \r\n * @param {UrBackendClient} client - The urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ apiKey: 'pk_live_xxx' });\r\n * const auth = new AuthModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Creates a new user account\r\n * \r\n * @param {SignUpPayload} payload - User registration data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.password - User's password\r\n * @param {string} payload.name - User's full name\r\n * @returns {Promise<AuthUser>} Promise resolving to the created user object\r\n * \r\n * @throws {AuthError} If email already exists\r\n * @throws {AuthError} If password does not meet requirements\r\n * @throws {AuthError} If validation fails\r\n * \r\n * @example\r\n * // Sign up a new user\r\n * const user = await auth.signUp({\r\n * email: 'john@example.com',\r\n * password: 'StrongP@ss123',\r\n * name: 'John Doe'\r\n * });\r\n * console.log('User created:', user._id);\r\n * \r\n * @example\r\n * // Sign up with error handling\r\n * try {\r\n * const user = await auth.signUp({\r\n * email: 'existing@email.com',\r\n * password: 'weak',\r\n * name: 'Test'\r\n * });\r\n * } catch (error) {\r\n * if (error.message.includes('email')) {\r\n * console.log('Email already registered');\r\n * } else if (error.message.includes('password')) {\r\n * console.log('Password too weak');\r\n * }\r\n * }\r\n */\r\n public async signUp(payload: SignUpPayload): Promise<AuthUser> {\r\n return this.client.request<AuthUser>('POST', '/api/userAuth/signup', { body: payload });\r\n }\r\n\r\n /**\r\n * Authenticates an existing user and stores the session token\r\n * \r\n * @param {LoginPayload} payload - User login credentials\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.password - User's password\r\n * @returns {Promise<AuthResponse>} Promise resolving to authentication response with tokens\r\n * \r\n * @throws {AuthError} If credentials are invalid\r\n * @throws {AuthError} If account is locked or not verified\r\n * \r\n * @example\r\n * // Log in a user\r\n * const response = await auth.login({\r\n * email: 'john@example.com',\r\n * password: 'StrongP@ss123'\r\n * });\r\n * console.log('Access token:', response.accessToken);\r\n * \r\n * @example\r\n * // Login with error handling\r\n * try {\r\n * const { accessToken, user } = await auth.login({\r\n * email: 'user@example.com',\r\n * password: 'wrongpassword'\r\n * });\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * console.log('Invalid email or password');\r\n * }\r\n * }\r\n */\r\n public async login(payload: LoginPayload): Promise<AuthResponse> {\r\n const response = await this.client.request<AuthResponse>('POST', '/api/userAuth/login', {\r\n body: payload,\r\n });\r\n\r\n this.sessionToken = response.accessToken || response.token;\r\n\r\n if (!response.accessToken && response.token) {\r\n console.warn(\r\n 'urbackend-sdk: The server returned \"token\" which is deprecated. Please update your backend to return \"accessToken\".',\r\n );\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Retrieves the current authenticated user's profile\r\n * \r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<AuthUser>} Promise resolving to the authenticated user's profile\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If token is invalid or expired\r\n * \r\n * @example\r\n * // Get current user profile (uses stored token from login)\r\n * const user = await auth.me();\r\n * console.log(`Hello ${user.name}, your email is ${user.email}`);\r\n * \r\n * @example\r\n * // Get profile with custom token\r\n * const user = await auth.me(customToken);\r\n * \r\n * @example\r\n * // Get profile with error handling\r\n * try {\r\n * const user = await auth.me();\r\n * console.log('Authenticated as:', user.email);\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * console.log('Please log in again');\r\n * }\r\n * }\r\n */\r\n public async me(token?: string): Promise<AuthUser> {\r\n const activeToken = token || this.sessionToken;\r\n\r\n if (!activeToken) {\r\n throw new AuthError(\r\n 'Authentication token is required for /me endpoint',\r\n 401,\r\n '/api/userAuth/me',\r\n );\r\n }\r\n\r\n return this.client.request<AuthUser>('GET', '/api/userAuth/me', { token: activeToken });\r\n }\r\n\r\n /**\r\n * Updates the current authenticated user's profile\r\n * \r\n * @param {UpdateProfilePayload} payload - Profile data to update\r\n * @param {string} [payload.name] - Updated name\r\n * @param {string} [payload.email] - Updated email (may require re-verification)\r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If token is invalid or expired\r\n * @throws {AuthError} If email is already taken\r\n * \r\n * @example\r\n * // Update user's name\r\n * const result = await auth.updateProfile({ name: 'Jane Smith' });\r\n * console.log(result.message);\r\n * \r\n * @example\r\n * // Update multiple fields\r\n * const result = await auth.updateProfile({\r\n * name: 'Jane Doe',\r\n * email: 'jane@newemail.com'\r\n * });\r\n * \r\n * @example\r\n * // Update with error handling\r\n * try {\r\n * await auth.updateProfile({ email: 'taken@email.com' });\r\n * } catch (error) {\r\n * console.log('Email already in use');\r\n * }\r\n */\r\n public async updateProfile(payload: UpdateProfilePayload, token?: string): Promise<{ message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n if (!activeToken) {\r\n throw new AuthError('Authentication token is required to update profile', 401, '/api/userAuth/update-profile');\r\n }\r\n return this.client.request<{ message: string }>('PUT', '/api/userAuth/update-profile', {\r\n body: payload,\r\n token: activeToken,\r\n });\r\n }\r\n\r\n /**\r\n * Changes the current authenticated user's password\r\n * \r\n * @param {ChangePasswordPayload} payload - Password change data\r\n * @param {string} payload.currentPassword - User's current password\r\n * @param {string} payload.newPassword - Desired new password\r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If current password is incorrect\r\n * @throws {AuthError} If new password does not meet requirements\r\n * \r\n * @example\r\n * // Change password\r\n * const result = await auth.changePassword({\r\n * currentPassword: 'oldPassword123',\r\n * newPassword: 'newStrongP@ss456'\r\n * });\r\n * console.log(result.message);\r\n * \r\n * @example\r\n * // Change password with error handling\r\n * try {\r\n * await auth.changePassword({\r\n * currentPassword: 'wrong',\r\n * newPassword: 'newPassword123'\r\n * });\r\n * } catch (error) {\r\n * if (error.message.includes('current password')) {\r\n * console.log('Current password is incorrect');\r\n * }\r\n * }\r\n */\r\n public async changePassword(payload: ChangePasswordPayload, token?: string): Promise<{ message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n if (!activeToken) {\r\n throw new AuthError('Authentication token is required to change password', 401, '/api/userAuth/change-password');\r\n }\r\n return this.client.request<{ message: string }>('PUT', '/api/userAuth/change-password', {\r\n body: payload,\r\n token: activeToken,\r\n });\r\n }\r\n\r\n /**\r\n * Verifies user's email address using OTP\r\n * \r\n * @param {VerifyEmailPayload} payload - Email verification data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.otp - One-time password sent to email\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If OTP is invalid or expired\r\n * @throws {AuthError} If email is not found\r\n * \r\n * @example\r\n * // Verify email with OTP\r\n * const result = await auth.verifyEmail({\r\n * email: 'user@example.com',\r\n * otp: '123456'\r\n * });\r\n * console.log('Email verified:', result.message);\r\n * \r\n * @example\r\n * // Verify with error handling\r\n * try {\r\n * await auth.verifyEmail({ email: 'user@example.com', otp: '000000' });\r\n * } catch (error) {\r\n * console.log('Invalid OTP. Please try again.');\r\n * }\r\n */\r\n public async verifyEmail(payload: VerifyEmailPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/verify-email', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Resends verification OTP to user's email\r\n * \r\n * @param {ResendOtpPayload} payload - Resend OTP request data\r\n * @param {string} payload.email - User's email address\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If too many attempts\r\n * \r\n * @example\r\n * // Resend verification OTP\r\n * const result = await auth.resendVerificationOtp({\r\n * email: 'user@example.com'\r\n * });\r\n * console.log('OTP resent:', result.message);\r\n */\r\n public async resendVerificationOtp(payload: ResendOtpPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/resend-verification-otp', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Requests a password reset OTP to be sent to user's email\r\n * \r\n * @param {RequestPasswordResetPayload} payload - Password reset request data\r\n * @param {string} payload.email - User's email address\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If too many attempts\r\n * \r\n * @example\r\n * // Request password reset\r\n * const result = await auth.requestPasswordReset({\r\n * email: 'user@example.com'\r\n * });\r\n * console.log('Reset OTP sent:', result.message);\r\n */\r\n public async requestPasswordReset(payload: RequestPasswordResetPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/request-password-reset', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Resets user's password using OTP\r\n * \r\n * @param {ResetPasswordPayload} payload - Password reset data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.otp - One-time password sent via email\r\n * @param {string} payload.newPassword - Desired new password\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If OTP is invalid or expired\r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If new password does not meet requirements\r\n * \r\n * @example\r\n * // Reset password with OTP\r\n * const result = await auth.resetPassword({\r\n * email: 'user@example.com',\r\n * otp: '123456',\r\n * newPassword: 'NewStrongP@ss789'\r\n * });\r\n * console.log('Password reset:', result.message);\r\n * \r\n * @example\r\n * // Reset password with error handling\r\n * try {\r\n * await auth.resetPassword({\r\n * email: 'user@example.com',\r\n * otp: 'wrong',\r\n * newPassword: 'newPass123'\r\n * });\r\n * } catch (error) {\r\n * console.log('Invalid OTP. Please request a new one.');\r\n * }\r\n */\r\n public async resetPassword(payload: ResetPasswordPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/reset-password', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Retrieves a public-safe user profile by username\r\n * \r\n * @param {string} username - Username of the user to fetch\r\n * @returns {Promise<AuthUser>} Promise resolving to public user profile (sensitive fields omitted)\r\n * \r\n * @throws {AuthError} If user with given username does not exist\r\n * \r\n * @example\r\n * // Get public profile\r\n * const profile = await auth.publicProfile('john_doe');\r\n * console.log(`${profile.name} joined on ${profile.createdAt}`);\r\n * \r\n * @example\r\n * // Display user profile on a public page\r\n * try {\r\n * const user = await auth.publicProfile('username');\r\n * // Show user info (no email or private data)\r\n * } catch (error) {\r\n * console.log('User not found');\r\n * }\r\n */\r\n public async publicProfile(username: string): Promise<AuthUser> {\r\n return this.client.request<AuthUser>('GET', `/api/userAuth/public/${username}`);\r\n }\r\n\r\n /**\r\n * Refreshes the access token using refresh token or cookie\r\n * \r\n * @param {string} [refreshToken] - Optional refresh token for header mode. If omitted, uses cookie mode.\r\n * @returns {Promise<AuthResponse>} Promise resolving to new authentication response with fresh tokens\r\n * \r\n * @throws {AuthError} If refresh token is invalid or expired\r\n * \r\n * @example\r\n * // Refresh token using cookie (if configured)\r\n * const newTokens = await auth.refreshToken();\r\n * console.log('New access token:', newTokens.accessToken);\r\n * \r\n * @example\r\n * // Refresh token using explicit refresh token\r\n * const newTokens = await auth.refreshToken(storedRefreshToken);\r\n * \r\n * @example\r\n * // Auto-refresh before API calls\r\n * try {\r\n * await auth.me();\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * await auth.refreshToken();\r\n * // Retry the original request\r\n * }\r\n * }\r\n */\r\n public async refreshToken(refreshToken?: string): Promise<AuthResponse> {\r\n const options: RequestOptions = {};\r\n if (refreshToken) {\r\n options.headers = { 'x-refresh-token': refreshToken, 'x-refresh-token-mode': 'header' };\r\n } else {\r\n options.credentials = 'include';\r\n }\r\n\r\n const response = await this.client.request<AuthResponse>('POST', '/api/userAuth/refresh-token', options);\r\n this.sessionToken = response.accessToken || response.token;\r\n return response;\r\n }\r\n\r\n /**\r\n * Returns the start URL for social authentication\r\n * \r\n * @param {('github' | 'google')} provider - The social authentication provider\r\n * @returns {string} URL to redirect the user's browser to begin the OAuth flow\r\n * \r\n * @example\r\n * // Redirect user to social login page\r\n * const githubUrl = auth.socialStart('github');\r\n * window.location.href = githubUrl;\r\n * \r\n * @example\r\n * // For Node.js backend\r\n * const googleUrl = auth.socialStart('google');\r\n * res.redirect(googleUrl);\r\n */\r\n public socialStart(provider: 'github' | 'google'): string {\r\n return `${this.client.getBaseUrl()}/api/userAuth/social/${provider}/start?key=${this.client.getApiKey()}`;\r\n }\r\n\r\n /**\r\n * Exchanges social authentication rtCode for a refresh token\r\n * \r\n * @param {SocialExchangePayload} payload - Social exchange data\r\n * @param {string} payload.rtCode - Return code from social provider\r\n * @param {string} payload.provider - Social provider ('github' or 'google')\r\n * @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response\r\n * \r\n * @throws {AuthError} If rtCode is invalid or expired\r\n * @throws {AuthError} If social provider fails\r\n * \r\n * @example\r\n * // After user returns from social login\r\n * const rtCode = new URLSearchParams(window.location.search).get('rtCode');\r\n * if (rtCode) {\r\n * const response = await auth.socialExchange({\r\n * rtCode: rtCode,\r\n * provider: 'github'\r\n * });\r\n * console.log('Social login successful:', response.accessToken);\r\n * }\r\n */\r\n public async socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse> {\r\n return this.client.request<SocialExchangeResponse>('POST', '/api/userAuth/social/exchange', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Revokes the current session and clears local state\r\n * \r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ success: boolean; message: string }>} Promise resolving to logout status\r\n * \r\n * @example\r\n * // Log out current user\r\n * const result = await auth.logout();\r\n * console.log(result.message);\r\n * // User is now logged out, session token is cleared\r\n * \r\n * @example\r\n * // Log out with custom token\r\n * const result = await auth.logout(customToken);\r\n * \r\n * @example\r\n * // Logout after API calls\r\n * try {\r\n * await auth.logout();\r\n * // Redirect to login page\r\n * window.location.href = '/login';\r\n * } catch (error) {\r\n * console.log('Logout failed, but local session cleared');\r\n * }\r\n */\r\n public async logout(token?: string): Promise<{ success: boolean; message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n let result = { success: true, message: 'Logged out locally' };\r\n\r\n if (activeToken) {\r\n try {\r\n result = await this.client.request<{ success: boolean; message: string }>(\r\n 'POST',\r\n '/api/userAuth/logout',\r\n { token: activeToken, credentials: 'include' },\r\n );\r\n } catch (e) {\r\n // Silently fail if server logout fails, we still want to clear local state\r\n console.warn('urbackend-sdk: Server logout failed', e);\r\n }\r\n }\r\n\r\n this.sessionToken = undefined;\r\n return result;\r\n }\r\n\r\n /**\r\n * Manually sets the session token (e.g., after social authentication exchange)\r\n * \r\n * @param {string} token - The session/access token to store\r\n * \r\n * @example\r\n * // After successful social exchange\r\n * const response = await auth.socialExchange({ rtCode, provider: 'github' });\r\n * auth.setToken(response.accessToken);\r\n * \r\n * @example\r\n * // Restore session from localStorage\r\n * const savedToken = localStorage.getItem('authToken');\r\n * if (savedToken) {\r\n * auth.setToken(savedToken);\r\n * const user = await auth.me();\r\n * }\r\n */\r\n public setToken(token: string): void {\r\n this.sessionToken = token;\r\n }\r\n\r\n /**\r\n * Gets the current stored session token\r\n * \r\n * @returns {string | undefined} The current session token, if any\r\n * \r\n * @example\r\n * // Get token for custom API calls\r\n * const token = auth.getToken();\r\n * if (token) {\r\n * // Use token in custom API request\r\n * fetch('/api/custom', { headers: { Authorization: `Bearer ${token}` } });\r\n * }\r\n * \r\n * @example\r\n * // Save token to localStorage for persistence\r\n * const token = auth.getToken();\r\n * if (token) {\r\n * localStorage.setItem('authToken', token);\r\n * }\r\n */\r\n public getToken(): string | undefined {\r\n return this.sessionToken;\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { DocumentData, InsertPayload, UpdatePayload, PatchPayload, QueryParams } from '../types';\r\nimport { NotFoundError } from '../errors';\r\n\r\n/**\r\n * Module for database operations in urBackend\r\n * \r\n * @class DatabaseModule\r\n * @description Provides CRUD (Create, Read, Update, Delete) operations for collections.\r\n * Supports filtering, pagination, sorting, population, and expansion of related data.\r\n * \r\n * @example\r\n * // Initialize the database module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const db = new DatabaseModule(client);\r\n * \r\n * // Get all users\r\n * const users = await db.getAll('users');\r\n * console.log(users);\r\n * \r\n * @example\r\n * // Insert a new document\r\n * const newUser = await db.insert('users', {\r\n * name: 'John Doe',\r\n * email: 'john@example.com'\r\n * });\r\n * console.log('Created:', newUser._id);\r\n */\r\nexport class DatabaseModule {\r\n /**\r\n * Creates an instance of DatabaseModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const db = new DatabaseModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Fetches all documents from a collection with optional query parameters\r\n * \r\n * @template T - The document type (extends DocumentData)\n * @param {string} collection - Name of the collection to query\n * @param {QueryParams} [params={}] - Optional query parameters for filtering, sorting, pagination\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<T[]>} Promise resolving to an array of documents (empty array if none found)\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If query parameters are malformed\r\n * \r\n * @example\r\n * // Get all users\r\n * const users = await db.getAll('users');\r\n * \r\n * @example\r\n * // Get users with filters and pagination\r\n * const activeUsers = await db.getAll('users', {\r\n * filter: { status: 'active' },\r\n * limit: 10,\r\n * skip: 0,\r\n * sort: '-createdAt'\r\n * });\r\n * \r\n * @example\r\n * // Get users with populated relations\r\n * const usersWithPosts = await db.getAll('users', {\r\n * populate: ['posts'],\r\n * expand: ['profile']\r\n * });\r\n */\r\n public async getAll<T extends DocumentData>(\n collection: string,\n params: QueryParams = {},\n token?: string\n ): Promise<T[]> {\n const queryString = this.buildQueryString(params);\n const path = `/api/data/${collection}${queryString}`;\n \n try {\n const result = await this.client.request<T[] | { items?: T[] }>('GET', path, { token });\n\n if (Array.isArray(result)) {\n return result;\n }\n\n if (result && typeof result === 'object' && Array.isArray(result.items)) {\n return result.items;\n }\n\n return [] as T[];\n } catch (e) {\n if (e instanceof NotFoundError) {\n return [] as T[];\n }\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Counts documents in a collection with optional filters\r\n * \r\n * @param {string} collection - Name of the collection to count\n * @param {Omit<QueryParams, 'count'>} [params={}] - Optional filter parameters\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<number>} Promise resolving to the total count of matching documents\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Count all users\r\n * const totalUsers = await db.count('users');\r\n * console.log(`Total users: ${totalUsers}`);\r\n * \r\n * @example\r\n * // Count users with filter\r\n * const activeUsers = await db.count('users', {\r\n * filter: { status: 'active' }\r\n * });\r\n * \r\n * @example\r\n * // Count for pagination\r\n * const total = await db.count('products', {\r\n * filter: { category: 'electronics' }\r\n * });\r\n * const totalPages = Math.ceil(total / 10);\r\n */\r\n public async count(\n collection: string,\n params: Omit<QueryParams, 'count'> = {},\n token?: string\n ): Promise<number> {\n const queryString = this.buildQueryString({ ...params, count: 'true' });\n const path = `/api/data/${collection}${queryString}`;\n const result = await this.client.request<{ count: number }>('GET', path, { token });\n return result.count;\n }\n\r\n /**\r\n * Fetches a single document by its ID\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {Object} [options={}] - Optional parameters\n * @param {string|string[]} [options.populate] - Fields to populate with related data\n * @param {string|string[]} [options.expand] - Fields to expand with nested data\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<T>} Promise resolving to the document\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Get user by ID\r\n * const user = await db.getOne('users', 'user_123');\r\n * console.log(user.name);\r\n * \r\n * @example\r\n * // Get user with populated posts\r\n * const userWithPosts = await db.getOne('users', 'user_123', {\r\n * populate: ['posts', 'comments']\r\n * });\r\n * \r\n * @example\r\n * // Get with error handling\r\n * try {\r\n * const user = await db.getOne('users', 'non_existent_id');\r\n * } catch (error) {\r\n * if (error instanceof NotFoundError) {\r\n * console.log('User not found');\r\n * }\r\n * }\r\n */\r\n public async getOne<T extends DocumentData>(\n collection: string, \n id: string, \n options: { populate?: string | string[]; expand?: string | string[] } = {},\n token?: string\n ): Promise<T> {\n const queryString = this.buildQueryString(options);\n return this.client.request<T>('GET', `/api/data/${collection}/${id}${queryString}`, { token });\n }\n\r\n /**\r\n * Inserts a new document into a collection\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {InsertPayload} data - Document data to insert\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the created document with generated ID\r\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If unique constraint violation occurs\r\n * \r\n * @example\r\n * // Insert a new user\r\n * const newUser = await db.insert('users', {\r\n * name: 'John Doe',\r\n * email: 'john@example.com',\r\n * age: 25\r\n * });\r\n * console.log('User created:', newUser._id);\r\n * \r\n * @example\r\n * // Insert with custom token\r\n * const result = await db.insert('posts', {\r\n * title: 'My Post',\r\n * content: 'Hello World'\r\n * }, customAuthToken);\r\n * \r\n * @example\r\n * // Insert with error handling\r\n * try {\r\n * const user = await db.insert('users', { email: 'existing@email.com' });\r\n * } catch (error) {\r\n * if (error.message.includes('duplicate')) {\r\n * console.log('Email already exists');\r\n * }\r\n * }\r\n */\r\n public async insert<T extends DocumentData>(\r\n collection: string, \r\n data: InsertPayload, \r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('POST', `/api/data/${collection}`, { \r\n body: data,\r\n token \r\n });\r\n }\r\n\r\n /**\r\n * Updates an existing document by its ID (full replacement)\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {UpdatePayload} data - Complete document data for replacement\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the updated document\r\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Full update of a user\r\n * const updatedUser = await db.update('users', 'user_123', {\r\n * name: 'Jane Doe',\r\n * email: 'jane@example.com',\r\n * age: 26\r\n * });\r\n * \r\n * @example\r\n * // Update with error handling\r\n * try {\r\n * const result = await db.update('users', 'user_123', updatedData);\r\n * console.log('Update successful:', result);\r\n * } catch (error) {\r\n * if (error instanceof NotFoundError) {\r\n * console.log('User not found');\r\n * }\r\n * }\r\n */\r\n public async update<T extends DocumentData>(\r\n collection: string,\r\n id: string,\r\n data: UpdatePayload,\r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('PUT', `/api/data/${collection}/${id}`, { \r\n body: data,\r\n token\r\n });\r\n }\r\n\r\n /**\r\n * Partially updates an existing document by its ID (only provided fields)\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {PatchPayload} data - Partial data to update\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the updated document\r\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Partial update - only update age\r\n * const updatedUser = await db.patch('users', 'user_123', {\r\n * age: 26\r\n * });\r\n * \r\n * @example\r\n * // Add a new field to document\r\n * const result = await db.patch('users', 'user_123', {\r\n * lastLogin: new Date().toISOString()\r\n * });\r\n * \r\n * @example\r\n * // Partial update with error handling\r\n * try {\r\n * const result = await db.patch('products', 'prod_123', {\r\n * price: 29.99\r\n * });\r\n * console.log('Price updated:', result);\r\n * } catch (error) {\r\n * console.error('Update failed:', error.message);\r\n * }\r\n */\r\n public async patch<T extends DocumentData>(\r\n collection: string,\r\n id: string,\r\n data: PatchPayload,\r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('PATCH', `/api/data/${collection}/${id}`, { \r\n body: data,\r\n token\r\n });\r\n }\r\n\r\n /**\r\n * Deletes a document by its ID\r\n * \r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document to delete\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status\r\n * \r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If user lacks permission to delete\r\n * \r\n * @example\r\n * // Delete a user\r\n * const result = await db.delete('users', 'user_123');\r\n * if (result.deleted) {\r\n * console.log('User deleted successfully');\r\n * }\r\n * \r\n * @example\r\n * // Delete with error handling\r\n * try {\r\n * const { deleted } = await db.delete('posts', 'post_456');\r\n * if (deleted) {\r\n * console.log('Post removed');\r\n * }\r\n * } catch (error) {\r\n * console.error('Deletion failed:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Delete after checking existence\r\n * const exists = await db.getOne('users', 'user_123').catch(() => null);\r\n * if (exists) {\r\n * await db.delete('users', 'user_123');\r\n * console.log('User deleted');\r\n * }\r\n */\r\n public async delete(collection: string, id: string, token?: string): Promise<{ deleted: boolean }> {\r\n const result = await this.client.request<{ message?: string; id?: string } | null>(\r\n 'DELETE',\r\n `/api/data/${collection}/${id}`,\r\n { token },\r\n );\r\n\r\n const deleted =\r\n typeof result === 'object' &&\r\n result !== null &&\r\n (result.id === id || result.message === 'Document deleted');\r\n\r\n return { deleted };\r\n }\r\n\r\n /**\r\n * Internal helper to build query string from QueryParams\r\n * \r\n * @param {QueryParams} params - Query parameters to convert\r\n * @returns {string} URL query string (starting with '?' if parameters exist, otherwise empty)\r\n * \r\n * @internal\r\n * @private\r\n * \r\n * @example\r\n * // Returns \"?limit=10&sort=-createdAt\"\r\n * buildQueryString({ limit: 10, sort: '-createdAt' })\r\n * \r\n * @example\r\n * // Returns \"?status=active&age=25\"\r\n * buildQueryString({ filter: { status: 'active', age: 25 } })\r\n */\r\n private buildQueryString(params: QueryParams): string {\r\n const searchParams = new URLSearchParams();\r\n\r\n Object.entries(params).forEach(([key, value]) => {\r\n if (value === undefined || value === null) return;\r\n\r\n if (key === 'filter' && typeof value === 'object') {\r\n Object.entries(value as Record<string, unknown>).forEach(([fKey, fValue]) => {\r\n if (fValue !== undefined && fValue !== null) {\r\n searchParams.append(fKey, String(fValue));\r\n }\r\n });\r\n } else if ((key === 'populate' || key === 'expand') && Array.isArray(value)) {\r\n searchParams.append(key, value.join(','));\r\n } else {\r\n searchParams.append(key, String(value));\r\n }\r\n });\r\n\r\n const str = searchParams.toString();\r\n return str ? `?${str}` : '';\r\n }\r\n}\n","/// <reference lib=\"dom\" />\r\nimport { UrBackendClient } from '../client';\r\nimport { UploadResponse } from '../types';\r\n\r\n/**\r\n * Module for handling file storage operations in urBackend\r\n * \r\n * @class StorageModule\r\n * @description Provides methods to upload and delete files in the urBackend storage system.\r\n * Supports both browser (File/Blob) and Node.js (Buffer) environments.\r\n * \r\n * @example\r\n * // Initialize the storage module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const storage = new StorageModule(client);\r\n * \r\n * // Upload a file (Browser)\r\n * const fileInput = document.getElementById('fileInput');\r\n * const result = await storage.upload(fileInput.files[0], 'my-file.pdf');\r\n * console.log(result.url);\r\n * \r\n * @example\r\n * // Upload a file (Node.js)\r\n * const fs = require('fs');\r\n * const buffer = fs.readFileSync('./document.pdf');\r\n * const result = await storage.upload(buffer, 'document.pdf');\r\n */\r\nexport class StorageModule {\r\n /**\r\n * Creates an instance of StorageModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const storage = new StorageModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Uploads a file to the urBackend storage\r\n * \r\n * @param {unknown} file - The file to upload. Supports:\r\n * - Browser: File, Blob\r\n * - Node.js: Buffer\r\n * @param {string} [filename] - Optional custom filename for the uploaded file\r\n * @returns {Promise<UploadResponse>} Promise resolving to upload details including URL and file ID\r\n * \r\n * @throws {Error} If file is invalid or missing\r\n * @throws {Error} If file size exceeds limits\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If storage quota is exceeded\r\n * \r\n * @example\r\n * // Browser: Upload from file input\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * const result = await storage.upload(file, 'custom-name.pdf');\r\n * console.log('File URL:', result.url);\r\n * \r\n * @example\r\n * // Node.js: Upload Buffer\r\n * const fs = require('fs');\r\n * const buffer = fs.readFileSync('./image.png');\r\n * const result = await storage.upload(buffer, 'image.png');\r\n * console.log('Uploaded:', result.fileId);\r\n * \r\n * @example\r\n * // Upload without custom filename (uses original name)\r\n * const result = await storage.upload(file);\r\n * \r\n * @example\r\n * // Upload with error handling\r\n * try {\r\n * const result = await storage.upload(file, 'document.pdf');\r\n * console.log('Upload successful:', result.url);\r\n * } catch (error) {\r\n * console.error('Upload failed:', error.message);\r\n * // Handle error: retry, show user message, etc.\r\n * }\r\n */\r\n public async upload(file: unknown, filename?: string): Promise<UploadResponse> {\r\n // figure out name, contentType and size depending on environment\r\n let resolvedName = filename || \"file\";\r\n let contentType = \"application/octet-stream\";\r\n let fileSize: number;\r\n let fileData: Blob | BufferSource;\r\n\r\n if (typeof File !== \"undefined\" && file instanceof File) {\r\n // browser File object\r\n resolvedName = filename || file.name;\r\n contentType = file.type || contentType;\r\n fileSize = file.size;\r\n fileData = file;\r\n } else if (file instanceof Blob) {\r\n contentType = file.type || contentType;\r\n fileSize = file.size;\r\n fileData = file;\r\n } else if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(file)) {\r\n // Node.js Buffer\r\n fileSize = (file as Buffer).length;\r\n fileData = file as unknown as BufferSource;\r\n } else {\r\n throw new Error(\"Unsupported file type. Pass a File, Blob, or Buffer.\");\r\n }\r\n\r\n // step 1 — ask server for a signed URL\r\n const { signedUrl, filePath } = await this.client.request<{ signedUrl: string; filePath: string }>(\r\n \"POST\",\r\n \"/api/storage/upload-request\",\r\n { body: { filename: resolvedName, contentType, size: fileSize } }\r\n );\r\n\r\n // step 2 — upload directly to cloud, server not involved\r\n const putResponse = await fetch(signedUrl, {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": contentType },\r\n body: fileData as BodyInit,\r\n });\r\n\r\n if (!putResponse.ok) {\r\n throw new Error(`Direct upload to cloud failed: ${putResponse.status} ${putResponse.statusText}`);\r\n }\r\n\r\n // step 3 — tell server we're done so it can verify + update quota\r\n return this.client.request<UploadResponse>(\r\n \"POST\",\r\n \"/api/storage/upload-confirm\",\r\n { body: { filePath, size: fileSize } }\r\n );\r\n}\r\n /**\r\n * Deletes a file from storage by its path\r\n * \r\n * @param {string} path - The file path or URL of the file to delete\r\n * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status\r\n * \r\n * @throws {Error} If path is empty or invalid\r\n * @throws {Error} If file does not exist\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If user lacks permission to delete the file\r\n * \r\n * @example\r\n * // Delete a file by path\r\n * const result = await storage.deleteFile('uploads/document.pdf');\r\n * if (result.deleted) {\r\n * console.log('File deleted successfully');\r\n * }\r\n * \r\n * @example\r\n * // Delete with error handling\r\n * try {\r\n * const result = await storage.deleteFile('uploads/old-file.jpg');\r\n * console.log('Deleted:', result.deleted);\r\n * } catch (error) {\r\n * console.error('Deletion failed:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Delete after upload\r\n * const uploadResult = await storage.upload(file, 'temp-file.pdf');\r\n * console.log('Uploaded:', uploadResult.url);\r\n * \r\n * // Later, delete the file\r\n * await storage.deleteFile('temp-file.pdf');\r\n * console.log('File cleaned up');\r\n */\r\n public async deleteFile(path: string): Promise<{ deleted: boolean }> {\r\n return this.client.request<{ deleted: boolean }>('DELETE', '/api/storage/file', {\r\n body: { path },\r\n });\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { CollectionSchema } from '../types';\r\n\r\n/**\r\n * Module for managing database schemas in urBackend\r\n * \r\n * @class SchemaModule\r\n * @description Provides methods to fetch and manage collection schema definitions.\r\n * Schemas define the structure, validation rules, and data types for collections.\r\n * \r\n * @example\r\n * // Initialize the schema module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const schema = new SchemaModule(client);\r\n * \r\n * // Get schema for a collection\r\n * const collectionSchema = await schema.getSchema('users');\r\n * console.log(collectionSchema.fields);\r\n */\r\nexport class SchemaModule {\r\n /**\r\n * Creates an instance of SchemaModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const schema = new SchemaModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Fetches the schema definition for a specific collection\r\n * \r\n * @param {string} collection - Name of the collection to fetch schema for\r\n * @returns {Promise<CollectionSchema>} Promise resolving to the collection schema definition\r\n * \r\n * @throws {Error} If collection name is empty or contains only whitespace\r\n * @throws {Error} If collection does not exist\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Get schema for users collection\r\n * const userSchema = await schema.getSchema('users');\r\n * console.log(userSchema.fields);\r\n * \r\n * @example\r\n * // Get schema for products collection with error handling\r\n * try {\r\n * const productSchema = await schema.getSchema('products');\r\n * console.log('Schema fields:', Object.keys(productSchema.fields));\r\n * } catch (error) {\r\n * console.error('Failed to fetch schema:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Validate collection name before fetching\r\n * const collectionName = 'my_collection';\r\n * if (collectionName.trim()) {\r\n * const schemaDef = await schema.getSchema(collectionName);\r\n * // Use schema definition\r\n * }\r\n */\r\n public async getSchema(collection: string): Promise<CollectionSchema> {\r\n const trimmedCollection = collection.trim();\r\n if (trimmedCollection === '') {\r\n throw new Error('Collection name cannot be empty or whitespace-only');\r\n }\r\n\r\n const encodedCollection = encodeURIComponent(trimmedCollection);\r\n const response = await this.client.request<{\r\n message: string;\r\n collection: CollectionSchema;\r\n }>('GET', `/api/schemas/${encodedCollection}`);\r\n\r\n return response.collection;\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { SendMailPayload, SendMailResponse } from '../types';\r\n\r\n/**\r\n * Module for handling email operations in urBackend\r\n * \r\n * @class MailModule\r\n * @description Provides methods to send emails using the urBackend mail service.\r\n * Requires a Secret Key (sk_live_...) and should be called from a server environment.\r\n * \r\n * @example\r\n * // Initialize the mail module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const mail = new MailModule(client);\r\n * \r\n * // Send an email\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Welcome!',\r\n * html: '<h1>Hello World</h1>'\r\n * });\r\n */\r\nexport class MailModule {\r\n /**\r\n * Creates an instance of MailModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const mail = new MailModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Sends an email using the urBackend mail service\r\n * \r\n * @param {SendMailPayload} payload - The email content and configuration\r\n * @param {string} payload.to - Recipient email address\r\n * @param {string} payload.subject - Email subject line\r\n * @param {string} payload.html - HTML content of the email\r\n * @param {string} [payload.from] - Optional sender email address (defaults to configured sender)\r\n * @param {string[]} [payload.cc] - Optional CC recipient email addresses\r\n * @param {string[]} [payload.bcc] - Optional BCC recipient email addresses\r\n * @returns {Promise<SendMailResponse>} Promise resolving to email sending status and message ID\r\n * \r\n * @throws {Error} If secret key is missing or invalid\r\n * @throws {Error} If email validation fails\r\n * @throws {Error} If rate limit is exceeded\r\n * \r\n * @example\r\n * // Send a basic email\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Welcome to urBackend',\r\n * html: '<h1>Welcome!</h1><p>Thanks for joining.</p>'\r\n * });\r\n * console.log(result.messageId);\r\n * \r\n * @example\r\n * // Send an email with CC and custom sender\r\n * const result = await mail.send({\r\n * from: 'noreply@myapp.com',\r\n * to: 'user@example.com',\r\n * cc: ['admin@example.com'],\r\n * subject: 'Important Update',\r\n * html: '<p>Your account has been updated.</p>'\r\n * });\r\n * \r\n * @example\r\n * // Send email with error handling\r\n * try {\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Test',\r\n * html: '<p>Test email</p>'\r\n * });\r\n * console.log('Email sent:', result);\r\n * } catch (error) {\r\n * console.error('Failed to send email:', error);\r\n * }\r\n */\r\n public async send(payload: SendMailPayload): Promise<SendMailResponse> {\r\n return this.client.request<SendMailResponse>('POST', '/api/mail/send', {\r\n body: payload,\r\n });\r\n }\r\n}","import { UrBackendConfig, RequestOptions } from './types';\r\nimport { UrBackendError, parseApiError } from './errors';\r\nimport { AuthModule } from './modules/auth';\r\nimport { DatabaseModule } from './modules/database';\r\nimport { StorageModule } from './modules/storage';\r\nimport { SchemaModule } from './modules/schema';\r\nimport { MailModule } from './modules/mail';\r\n\r\nexport class UrBackendClient {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private _auth?: AuthModule;\r\n private _db?: DatabaseModule;\r\n private _storage?: StorageModule;\r\n private _schema?: SchemaModule;\r\n private _mail?: MailModule;\r\n private headers: Record<string, string>;\r\n\r\n constructor(config: UrBackendConfig) {\r\n this.apiKey = config.apiKey;\r\n this.baseUrl = config.baseUrl || 'https://api.ub.bitbros.in';\r\n this.headers = config.headers || {};\r\n\r\n if (typeof window !== 'undefined' && this.apiKey.startsWith('sk_live_')) {\r\n console.warn(\r\n '⚠️ urbackend-sdk: Avoid exposing your Secret Key (sk_live_...) in client-side code. This can lead to unauthorized access to your account and data. Use your Publishable Key (pk_live_...) instead.',\r\n );\r\n }\r\n }\r\n\r\n get auth(): AuthModule {\r\n if (!this._auth) {\r\n this._auth = new AuthModule(this);\r\n }\r\n return this._auth;\r\n }\r\n\r\n get db(): DatabaseModule {\r\n if (!this._db) {\r\n this._db = new DatabaseModule(this);\r\n }\r\n return this._db;\r\n }\r\n\r\n get storage(): StorageModule {\r\n if (!this._storage) {\r\n this._storage = new StorageModule(this);\r\n }\r\n return this._storage;\r\n }\r\n\r\n get schema(): SchemaModule {\r\n if (!this._schema) {\r\n this._schema = new SchemaModule(this);\r\n }\r\n return this._schema;\r\n }\r\n\r\n get mail(): MailModule {\r\n if (!this._mail) {\r\n this._mail = new MailModule(this);\r\n }\r\n return this._mail;\r\n }\r\n\r\n public getBaseUrl(): string {\r\n return this.baseUrl;\r\n }\r\n\r\n public getApiKey(): string {\r\n return this.apiKey;\r\n }\r\n\r\n /**\r\n * Internal request handler\r\n */\r\n public async request<T>(\r\n method: string,\r\n path: string,\r\n options: RequestOptions = {},\r\n ): Promise<T> {\r\n const url = `${this.baseUrl}${path}`;\r\n const headers: Record<string, string> = {\r\n 'x-api-key': this.apiKey,\r\n 'User-Agent': `urbackend-sdk-js/0.4.1`,\n ...this.headers,\r\n };\r\n\r\n if (options.token) {\r\n headers['Authorization'] = `Bearer ${options.token}`;\r\n }\r\n\r\n // Merge custom headers from options if provided\r\n if (options.headers) {\r\n Object.assign(headers, options.headers);\r\n }\r\n\r\n let requestBody: BodyInit | undefined;\r\n\r\n if (options.isMultipart) {\r\n // Fetch handles FormData content type and boundary\r\n requestBody = options.body as FormData;\r\n } else if (options.body) {\r\n headers['Content-Type'] = 'application/json';\r\n requestBody = JSON.stringify(options.body);\r\n }\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method,\r\n headers,\r\n body: requestBody,\r\n credentials: options.credentials,\r\n });\r\n\r\n if (!response.ok) {\r\n throw await parseApiError(response);\r\n }\r\n\r\n const contentType = response.headers.get('content-type');\r\n if (contentType && contentType.includes('application/json')) {\r\n const json = await response.json();\r\n // The API returns { data, success, message }\r\n // If data is present, return it. If success/message are present but no data, return the whole object (for exchange/logout etc)\r\n if (json.data !== undefined) {\r\n return json.data;\r\n }\r\n return json;\r\n }\r\n\r\n return (await response.text()) as unknown as T;\r\n } catch (error) {\r\n if (error instanceof UrBackendError) {\r\n throw error;\r\n }\r\n throw new UrBackendError(\r\n error instanceof Error ? error.message : 'Network request failed',\r\n 0,\r\n path,\r\n );\r\n }\r\n }\r\n}\r\n","import { UrBackendClient } from './client';\r\nimport { UrBackendConfig } from './types';\r\nimport { AuthModule } from './modules/auth';\r\nimport { DatabaseModule } from './modules/database';\r\nimport { StorageModule } from './modules/storage';\r\nimport { SchemaModule } from './modules/schema';\r\nimport { MailModule } from './modules/mail';\r\n\r\nexport * from './types';\r\nexport * from './errors';\r\nexport { UrBackendClient, AuthModule, DatabaseModule, StorageModule, SchemaModule, MailModule };\r\n\r\n/**\r\n * Factory function to create a new urBackend client\r\n */\r\nexport default function urBackend(config: UrBackendConfig): UrBackendClient {\r\n return new UrBackendClient(config);\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/modules/auth.ts","../src/modules/database.ts","../src/modules/storage.ts","../src/modules/schema.ts","../src/modules/mail.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["export class UrBackendError extends Error {\r\n constructor(\r\n public message: string,\r\n public statusCode: number,\r\n public endpoint: string,\r\n ) {\r\n super(message);\r\n this.name = 'UrBackendError';\r\n }\r\n}\r\n\r\nexport class AuthError extends UrBackendError {\r\n constructor(message: string, statusCode: number, endpoint: string) {\r\n super(message, statusCode, endpoint);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\nexport class NotFoundError extends UrBackendError {\r\n constructor(message: string, endpoint: string) {\r\n super(message, 404, endpoint);\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\nexport class RateLimitError extends UrBackendError {\r\n public retryAfter?: number;\r\n\r\n constructor(message: string, endpoint: string, retryAfter?: number) {\r\n super(message, 429, endpoint);\r\n this.name = 'RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class StorageError extends UrBackendError {\r\n constructor(message: string, statusCode: number, endpoint: string) {\r\n super(message, statusCode, endpoint);\r\n this.name = 'StorageError';\r\n }\r\n}\r\n\r\nexport class ValidationError extends UrBackendError {\r\n constructor(message: string, endpoint: string) {\r\n super(message, 400, endpoint);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n\r\nexport async function parseApiError(response: Response): Promise<UrBackendError> {\r\n const endpoint = new URL(response.url).pathname;\r\n let message = 'An unexpected error occurred';\r\n let data: unknown;\r\n\r\n try {\r\n data = await response.json();\r\n if (typeof data === 'object' && data !== null) {\r\n const errData = data as Record<string, unknown>;\r\n if ('error' in errData) {\r\n let candidate = '';\r\n if (typeof errData.error === 'string') {\r\n candidate = errData.error;\r\n } else if (Array.isArray(errData.error) && errData.error.length > 0) {\r\n candidate = errData.error.map((e: unknown) => {\r\n if (typeof e === 'object' && e !== null && 'message' in e) {\r\n return String((e as Record<string, unknown>).message);\r\n }\r\n return String(e);\r\n }).join(', ');\r\n } else {\r\n candidate = JSON.stringify(errData.error);\r\n }\r\n \r\n if (candidate && candidate.trim().length > 0 && candidate !== '[]' && candidate !== 'null') {\r\n message = candidate;\r\n } else if ('message' in errData) {\r\n message = typeof errData.message === 'string' ? errData.message : JSON.stringify(errData.message);\r\n }\r\n } else if ('message' in errData) {\r\n if (typeof errData.message === 'string') {\r\n message = errData.message;\r\n } else {\r\n message = JSON.stringify(errData.message);\r\n }\r\n }\r\n }\r\n } catch {\r\n // If not JSON, use status text\r\n message = response.statusText || message;\r\n }\r\n\r\n const status = response.status;\r\n\r\n if (status === 401 || status === 403) {\r\n return new AuthError(message, status, endpoint);\r\n }\r\n\r\n if (status === 404) {\r\n return new NotFoundError(message, endpoint);\r\n }\r\n\r\n if (status === 429) {\r\n const retryAfter = response.headers.get('Retry-After');\r\n return new RateLimitError(message, endpoint, retryAfter ? parseInt(retryAfter, 10) : undefined);\r\n }\r\n\r\n if (status === 400) {\r\n return new ValidationError(message, endpoint);\r\n }\r\n\r\n // Default for 5xx or other 4xx\r\n if (endpoint.includes('/api/storage')) {\r\n return new StorageError(message, status, endpoint);\r\n }\r\n\r\n return new UrBackendError(message, status, endpoint);\r\n}\r\n","import { UrBackendClient } from '../client';\r\nimport {\r\n AuthUser,\r\n AuthResponse,\r\n SignUpPayload,\r\n LoginPayload,\r\n UpdateProfilePayload,\r\n ChangePasswordPayload,\r\n VerifyEmailPayload,\r\n ResendOtpPayload,\r\n RequestPasswordResetPayload,\r\n ResetPasswordPayload,\r\n SocialExchangePayload,\r\n SocialExchangeResponse,\r\n RequestOptions,\r\n} from '../types';\r\nimport { AuthError } from '../errors';\r\n\r\n/**\r\n * Module for authentication and user management in urBackend\r\n * \r\n * @class AuthModule\r\n * @description Provides complete authentication functionality including signup, login,\r\n * profile management, password operations, email verification, social authentication,\r\n * and session management. Manages session tokens automatically.\r\n * \r\n * @example\r\n * // Initialize the auth module\r\n * const client = new UrBackendClient({ apiKey: 'pk_live_xxx', secretKey: 'sk_live_xxx' });\r\n * const auth = new AuthModule(client);\r\n * \r\n * // Sign up a new user\r\n * const user = await auth.signUp({\r\n * email: 'user@example.com',\r\n * password: 'securePassword123',\r\n * name: 'John Doe'\r\n * });\r\n * \r\n * @example\r\n * // Log in and manage session\r\n * const session = await auth.login({\r\n * email: 'user@example.com',\r\n * password: 'securePassword123'\r\n * });\r\n * console.log('Access token:', session.accessToken);\r\n * \r\n * // Get current user profile\r\n * const profile = await auth.me();\r\n * console.log('Welcome:', profile.name);\r\n */\r\nexport class AuthModule {\r\n private sessionToken?: string;\r\n\r\n /**\r\n * Creates an instance of AuthModule\r\n * \r\n * @param {UrBackendClient} client - The urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ apiKey: 'pk_live_xxx' });\r\n * const auth = new AuthModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Creates a new user account\r\n * \r\n * @param {SignUpPayload} payload - User registration data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.password - User's password\r\n * @param {string} payload.name - User's full name\r\n * @returns {Promise<AuthUser>} Promise resolving to the created user object\r\n * \r\n * @throws {AuthError} If email already exists\r\n * @throws {AuthError} If password does not meet requirements\r\n * @throws {AuthError} If validation fails\r\n * \r\n * @example\r\n * // Sign up a new user\r\n * const user = await auth.signUp({\r\n * email: 'john@example.com',\r\n * password: 'StrongP@ss123',\r\n * name: 'John Doe'\r\n * });\r\n * console.log('User created:', user._id);\r\n * \r\n * @example\r\n * // Sign up with error handling\r\n * try {\r\n * const user = await auth.signUp({\r\n * email: 'existing@email.com',\r\n * password: 'weak',\r\n * name: 'Test'\r\n * });\r\n * } catch (error) {\r\n * if (error.message.includes('email')) {\r\n * console.log('Email already registered');\r\n * } else if (error.message.includes('password')) {\r\n * console.log('Password too weak');\r\n * }\r\n * }\r\n */\r\n public async signUp(payload: SignUpPayload): Promise<AuthUser> {\r\n return this.client.request<AuthUser>('POST', '/api/userAuth/signup', { body: payload });\r\n }\r\n\r\n /**\r\n * Authenticates an existing user and stores the session token\r\n * \r\n * @param {LoginPayload} payload - User login credentials\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.password - User's password\r\n * @returns {Promise<AuthResponse>} Promise resolving to authentication response with tokens\r\n * \r\n * @throws {AuthError} If credentials are invalid\r\n * @throws {AuthError} If account is locked or not verified\r\n * \r\n * @example\r\n * // Log in a user\r\n * const response = await auth.login({\r\n * email: 'john@example.com',\r\n * password: 'StrongP@ss123'\r\n * });\r\n * console.log('Access token:', response.accessToken);\r\n * \r\n * @example\r\n * // Login with error handling\r\n * try {\r\n * const { accessToken, user } = await auth.login({\r\n * email: 'user@example.com',\r\n * password: 'wrongpassword'\r\n * });\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * console.log('Invalid email or password');\r\n * }\r\n * }\r\n */\r\n public async login(payload: LoginPayload): Promise<AuthResponse> {\r\n const response = await this.client.request<AuthResponse>('POST', '/api/userAuth/login', {\r\n body: payload,\r\n });\r\n\r\n this.sessionToken = response.accessToken || response.token;\r\n\r\n if (!response.accessToken && response.token) {\r\n console.warn(\r\n 'urbackend-sdk: The server returned \"token\" which is deprecated. Please update your backend to return \"accessToken\".',\r\n );\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Retrieves the current authenticated user's profile\r\n * \r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<AuthUser>} Promise resolving to the authenticated user's profile\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If token is invalid or expired\r\n * \r\n * @example\r\n * // Get current user profile (uses stored token from login)\r\n * const user = await auth.me();\r\n * console.log(`Hello ${user.name}, your email is ${user.email}`);\r\n * \r\n * @example\r\n * // Get profile with custom token\r\n * const user = await auth.me(customToken);\r\n * \r\n * @example\r\n * // Get profile with error handling\r\n * try {\r\n * const user = await auth.me();\r\n * console.log('Authenticated as:', user.email);\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * console.log('Please log in again');\r\n * }\r\n * }\r\n */\r\n public async me(token?: string): Promise<AuthUser> {\r\n const activeToken = token || this.sessionToken;\r\n\r\n if (!activeToken) {\r\n throw new AuthError(\r\n 'Authentication token is required for /me endpoint',\r\n 401,\r\n '/api/userAuth/me',\r\n );\r\n }\r\n\r\n return this.client.request<AuthUser>('GET', '/api/userAuth/me', { token: activeToken });\r\n }\r\n\r\n /**\r\n * Updates the current authenticated user's profile\r\n * \r\n * @param {UpdateProfilePayload} payload - Profile data to update\r\n * @param {string} [payload.name] - Updated name\r\n * @param {string} [payload.email] - Updated email (may require re-verification)\r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If token is invalid or expired\r\n * @throws {AuthError} If email is already taken\r\n * \r\n * @example\r\n * // Update user's name\r\n * const result = await auth.updateProfile({ name: 'Jane Smith' });\r\n * console.log(result.message);\r\n * \r\n * @example\r\n * // Update multiple fields\r\n * const result = await auth.updateProfile({\r\n * name: 'Jane Doe',\r\n * email: 'jane@newemail.com'\r\n * });\r\n * \r\n * @example\r\n * // Update with error handling\r\n * try {\r\n * await auth.updateProfile({ email: 'taken@email.com' });\r\n * } catch (error) {\r\n * console.log('Email already in use');\r\n * }\r\n */\r\n public async updateProfile(payload: UpdateProfilePayload, token?: string): Promise<{ message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n if (!activeToken) {\r\n throw new AuthError('Authentication token is required to update profile', 401, '/api/userAuth/update-profile');\r\n }\r\n return this.client.request<{ message: string }>('PUT', '/api/userAuth/update-profile', {\r\n body: payload,\r\n token: activeToken,\r\n });\r\n }\r\n\r\n /**\r\n * Changes the current authenticated user's password\r\n * \r\n * @param {ChangePasswordPayload} payload - Password change data\r\n * @param {string} payload.currentPassword - User's current password\r\n * @param {string} payload.newPassword - Desired new password\r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If no authentication token is provided\r\n * @throws {AuthError} If current password is incorrect\r\n * @throws {AuthError} If new password does not meet requirements\r\n * \r\n * @example\r\n * // Change password\r\n * const result = await auth.changePassword({\r\n * currentPassword: 'oldPassword123',\r\n * newPassword: 'newStrongP@ss456'\r\n * });\r\n * console.log(result.message);\r\n * \r\n * @example\r\n * // Change password with error handling\r\n * try {\r\n * await auth.changePassword({\r\n * currentPassword: 'wrong',\r\n * newPassword: 'newPassword123'\r\n * });\r\n * } catch (error) {\r\n * if (error.message.includes('current password')) {\r\n * console.log('Current password is incorrect');\r\n * }\r\n * }\r\n */\r\n public async changePassword(payload: ChangePasswordPayload, token?: string): Promise<{ message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n if (!activeToken) {\r\n throw new AuthError('Authentication token is required to change password', 401, '/api/userAuth/change-password');\r\n }\r\n return this.client.request<{ message: string }>('PUT', '/api/userAuth/change-password', {\r\n body: payload,\r\n token: activeToken,\r\n });\r\n }\r\n\r\n /**\r\n * Verifies user's email address using OTP\r\n * \r\n * @param {VerifyEmailPayload} payload - Email verification data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.otp - One-time password sent to email\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If OTP is invalid or expired\r\n * @throws {AuthError} If email is not found\r\n * \r\n * @example\r\n * // Verify email with OTP\r\n * const result = await auth.verifyEmail({\r\n * email: 'user@example.com',\r\n * otp: '123456'\r\n * });\r\n * console.log('Email verified:', result.message);\r\n * \r\n * @example\r\n * // Verify with error handling\r\n * try {\r\n * await auth.verifyEmail({ email: 'user@example.com', otp: '000000' });\r\n * } catch (error) {\r\n * console.log('Invalid OTP. Please try again.');\r\n * }\r\n */\r\n public async verifyEmail(payload: VerifyEmailPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/verify-email', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Resends verification OTP to user's email\r\n * \r\n * @param {ResendOtpPayload} payload - Resend OTP request data\r\n * @param {string} payload.email - User's email address\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If too many attempts\r\n * \r\n * @example\r\n * // Resend verification OTP\r\n * const result = await auth.resendVerificationOtp({\r\n * email: 'user@example.com'\r\n * });\r\n * console.log('OTP resent:', result.message);\r\n */\r\n public async resendVerificationOtp(payload: ResendOtpPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/resend-verification-otp', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Requests a password reset OTP to be sent to user's email\r\n * \r\n * @param {RequestPasswordResetPayload} payload - Password reset request data\r\n * @param {string} payload.email - User's email address\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If too many attempts\r\n * \r\n * @example\r\n * // Request password reset\r\n * const result = await auth.requestPasswordReset({\r\n * email: 'user@example.com'\r\n * });\r\n * console.log('Reset OTP sent:', result.message);\r\n */\r\n public async requestPasswordReset(payload: RequestPasswordResetPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/request-password-reset', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Resets user's password using OTP\r\n * \r\n * @param {ResetPasswordPayload} payload - Password reset data\r\n * @param {string} payload.email - User's email address\r\n * @param {string} payload.otp - One-time password sent via email\r\n * @param {string} payload.newPassword - Desired new password\r\n * @returns {Promise<{ message: string }>} Promise resolving to success message\r\n * \r\n * @throws {AuthError} If OTP is invalid or expired\r\n * @throws {AuthError} If email is not found\r\n * @throws {AuthError} If new password does not meet requirements\r\n * \r\n * @example\r\n * // Reset password with OTP\r\n * const result = await auth.resetPassword({\r\n * email: 'user@example.com',\r\n * otp: '123456',\r\n * newPassword: 'NewStrongP@ss789'\r\n * });\r\n * console.log('Password reset:', result.message);\r\n * \r\n * @example\r\n * // Reset password with error handling\r\n * try {\r\n * await auth.resetPassword({\r\n * email: 'user@example.com',\r\n * otp: 'wrong',\r\n * newPassword: 'newPass123'\r\n * });\r\n * } catch (error) {\r\n * console.log('Invalid OTP. Please request a new one.');\r\n * }\r\n */\r\n public async resetPassword(payload: ResetPasswordPayload): Promise<{ message: string }> {\r\n return this.client.request<{ message: string }>('POST', '/api/userAuth/reset-password', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Retrieves a public-safe user profile by username\r\n * \r\n * @param {string} username - Username of the user to fetch\r\n * @returns {Promise<AuthUser>} Promise resolving to public user profile (sensitive fields omitted)\r\n * \r\n * @throws {AuthError} If user with given username does not exist\r\n * \r\n * @example\r\n * // Get public profile\r\n * const profile = await auth.publicProfile('john_doe');\r\n * console.log(`${profile.name} joined on ${profile.createdAt}`);\r\n * \r\n * @example\r\n * // Display user profile on a public page\r\n * try {\r\n * const user = await auth.publicProfile('username');\r\n * // Show user info (no email or private data)\r\n * } catch (error) {\r\n * console.log('User not found');\r\n * }\r\n */\r\n public async publicProfile(username: string): Promise<AuthUser> {\r\n return this.client.request<AuthUser>('GET', `/api/userAuth/public/${username}`);\r\n }\r\n\r\n /**\r\n * Refreshes the access token using refresh token or cookie\r\n * \r\n * @param {string} [refreshToken] - Optional refresh token for header mode. If omitted, uses cookie mode.\r\n * @returns {Promise<AuthResponse>} Promise resolving to new authentication response with fresh tokens\r\n * \r\n * @throws {AuthError} If refresh token is invalid or expired\r\n * \r\n * @example\r\n * // Refresh token using cookie (if configured)\r\n * const newTokens = await auth.refreshToken();\r\n * console.log('New access token:', newTokens.accessToken);\r\n * \r\n * @example\r\n * // Refresh token using explicit refresh token\r\n * const newTokens = await auth.refreshToken(storedRefreshToken);\r\n * \r\n * @example\r\n * // Auto-refresh before API calls\r\n * try {\r\n * await auth.me();\r\n * } catch (error) {\r\n * if (error.status === 401) {\r\n * await auth.refreshToken();\r\n * // Retry the original request\r\n * }\r\n * }\r\n */\r\n public async refreshToken(refreshToken?: string): Promise<AuthResponse> {\r\n const options: RequestOptions = {};\r\n if (refreshToken) {\r\n options.headers = { 'x-refresh-token': refreshToken, 'x-refresh-token-mode': 'header' };\r\n } else {\r\n options.credentials = 'include';\r\n }\r\n\r\n const response = await this.client.request<AuthResponse>('POST', '/api/userAuth/refresh-token', options);\r\n this.sessionToken = response.accessToken || response.token;\r\n return response;\r\n }\r\n\r\n /**\r\n * Returns the start URL for social authentication\r\n * \r\n * @param {('github' | 'google')} provider - The social authentication provider\r\n * @returns {string} URL to redirect the user's browser to begin the OAuth flow\r\n * \r\n * @example\r\n * // Redirect user to social login page\r\n * const githubUrl = auth.socialStart('github');\r\n * window.location.href = githubUrl;\r\n * \r\n * @example\r\n * // For Node.js backend\r\n * const googleUrl = auth.socialStart('google');\r\n * res.redirect(googleUrl);\r\n */\r\n public socialStart(provider: 'github' | 'google'): string {\r\n return `${this.client.getBaseUrl()}/api/userAuth/social/${provider}/start?key=${this.client.getApiKey()}`;\r\n }\r\n\r\n /**\r\n * Exchanges social authentication rtCode for a refresh token\r\n * \r\n * @param {SocialExchangePayload} payload - Social exchange data\r\n * @param {string} payload.token - Access token fragment from social provider\r\n * @param {string} payload.rtCode - Return code from social provider\r\n * @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response\r\n * \r\n * @throws {AuthError} If rtCode is invalid or expired\r\n * @throws {AuthError} If social provider fails\r\n * \r\n * @example\r\n * // After user returns from social login\r\n * const urlParams = new URLSearchParams(window.location.search);\r\n * const hashParams = new URLSearchParams(window.location.hash.substring(1));\r\n * const rtCode = urlParams.get('rtCode');\r\n * const token = hashParams.get('token');\r\n * if (rtCode && token) {\r\n * const response = await auth.socialExchange({ token, rtCode });\r\n * console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);\r\n * await auth.refreshToken();\r\n * }\r\n */\r\n public async socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse> {\r\n return this.client.request<SocialExchangeResponse>('POST', '/api/userAuth/social/exchange', {\r\n body: payload,\r\n });\r\n }\r\n\r\n /**\r\n * Revokes the current session and clears local state\r\n * \r\n * @param {string} [token] - Optional authentication token (overrides stored token)\r\n * @returns {Promise<{ success: boolean; message: string }>} Promise resolving to logout status\r\n * \r\n * @example\r\n * // Log out current user\r\n * const result = await auth.logout();\r\n * console.log(result.message);\r\n * // User is now logged out, session token is cleared\r\n * \r\n * @example\r\n * // Log out with custom token\r\n * const result = await auth.logout(customToken);\r\n * \r\n * @example\r\n * // Logout after API calls\r\n * try {\r\n * await auth.logout();\r\n * // Redirect to login page\r\n * window.location.href = '/login';\r\n * } catch (error) {\r\n * console.log('Logout failed, but local session cleared');\r\n * }\r\n */\r\n public async logout(token?: string): Promise<{ success: boolean; message: string }> {\r\n const activeToken = token || this.sessionToken;\r\n let result = { success: true, message: 'Logged out locally' };\r\n\r\n if (activeToken) {\r\n try {\r\n result = await this.client.request<{ success: boolean; message: string }>(\r\n 'POST',\r\n '/api/userAuth/logout',\r\n { token: activeToken, credentials: 'include' },\r\n );\r\n } catch (e) {\r\n // Silently fail if server logout fails, we still want to clear local state\r\n console.warn('urbackend-sdk: Server logout failed', e);\r\n }\r\n }\r\n\r\n this.sessionToken = undefined;\r\n return result;\r\n }\r\n\r\n /**\r\n * Manually sets the session token (e.g., after social authentication exchange)\r\n * \r\n * @param {string} token - The session/access token to store\r\n * \r\n * @example\r\n * // After successful social exchange\r\n * const response = await auth.socialExchange({ rtCode, provider: 'github' });\r\n * auth.setToken(response.accessToken);\r\n * \r\n * @example\r\n * // Restore session from localStorage\r\n * const savedToken = localStorage.getItem('authToken');\r\n * if (savedToken) {\r\n * auth.setToken(savedToken);\r\n * const user = await auth.me();\r\n * }\r\n */\r\n public setToken(token: string): void {\r\n this.sessionToken = token;\r\n }\r\n\r\n /**\r\n * Gets the current stored session token\r\n * \r\n * @returns {string | undefined} The current session token, if any\r\n * \r\n * @example\r\n * // Get token for custom API calls\r\n * const token = auth.getToken();\r\n * if (token) {\r\n * // Use token in custom API request\r\n * fetch('/api/custom', { headers: { Authorization: `Bearer ${token}` } });\r\n * }\r\n * \r\n * @example\r\n * // Save token to localStorage for persistence\r\n * const token = auth.getToken();\r\n * if (token) {\r\n * localStorage.setItem('authToken', token);\r\n * }\r\n */\r\n public getToken(): string | undefined {\r\n return this.sessionToken;\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { DocumentData, InsertPayload, UpdatePayload, PatchPayload, QueryParams } from '../types';\r\nimport { NotFoundError } from '../errors';\r\n\r\n/**\r\n * Module for database operations in urBackend\r\n * \r\n * @class DatabaseModule\r\n * @description Provides CRUD (Create, Read, Update, Delete) operations for collections.\r\n * Supports filtering, pagination, sorting, population, and expansion of related data.\r\n * \r\n * @example\r\n * // Initialize the database module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const db = new DatabaseModule(client);\r\n * \r\n * // Get all users\r\n * const users = await db.getAll('users');\r\n * console.log(users);\r\n * \r\n * @example\r\n * // Insert a new document\r\n * const newUser = await db.insert('users', {\r\n * name: 'John Doe',\r\n * email: 'john@example.com'\r\n * });\r\n * console.log('Created:', newUser._id);\r\n */\r\nexport class DatabaseModule {\r\n /**\r\n * Creates an instance of DatabaseModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const db = new DatabaseModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Fetches all documents from a collection with optional query parameters\r\n * \r\n * @template T - The document type (extends DocumentData)\n * @param {string} collection - Name of the collection to query\n * @param {QueryParams} [params={}] - Optional query parameters for filtering, sorting, pagination\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<T[]>} Promise resolving to an array of documents (empty array if none found)\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If query parameters are malformed\r\n * \r\n * @example\r\n * // Get all users\r\n * const users = await db.getAll('users');\r\n * \r\n * @example\r\n * // Get users with filters and pagination\r\n * const activeUsers = await db.getAll('users', {\r\n * filter: { status: 'active' },\r\n * limit: 10,\r\n * skip: 0,\r\n * sort: '-createdAt'\r\n * });\r\n * \r\n * @example\r\n * // Get users with populated relations\r\n * const usersWithPosts = await db.getAll('users', {\r\n * populate: ['posts'],\r\n * expand: ['profile']\r\n * });\r\n */\r\n public async getAll<T extends DocumentData>(\n collection: string,\n params: QueryParams = {},\n token?: string\n ): Promise<T[]> {\n const queryString = this.buildQueryString(params);\n const path = `/api/data/${collection}${queryString}`;\n \n try {\n const result = await this.client.request<T[] | { items?: T[] }>('GET', path, { token });\n\n if (Array.isArray(result)) {\n return result;\n }\n\n if (result && typeof result === 'object' && Array.isArray(result.items)) {\n return result.items;\n }\n\n return [] as T[];\n } catch (e) {\n if (e instanceof NotFoundError) {\n return [] as T[];\n }\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Counts documents in a collection with optional filters\r\n * \r\n * @param {string} collection - Name of the collection to count\n * @param {Omit<QueryParams, 'count'>} [params={}] - Optional filter parameters\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<number>} Promise resolving to the total count of matching documents\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Count all users\r\n * const totalUsers = await db.count('users');\r\n * console.log(`Total users: ${totalUsers}`);\r\n * \r\n * @example\r\n * // Count users with filter\r\n * const activeUsers = await db.count('users', {\r\n * filter: { status: 'active' }\r\n * });\r\n * \r\n * @example\r\n * // Count for pagination\r\n * const total = await db.count('products', {\r\n * filter: { category: 'electronics' }\r\n * });\r\n * const totalPages = Math.ceil(total / 10);\r\n */\r\n public async count(\n collection: string,\n params: Omit<QueryParams, 'count'> = {},\n token?: string\n ): Promise<number> {\n const queryString = this.buildQueryString({ ...params, count: 'true' });\n const path = `/api/data/${collection}${queryString}`;\n const result = await this.client.request<{ count: number }>('GET', path, { token });\n return result.count;\n }\n\r\n /**\r\n * Fetches a single document by its ID\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {Object} [options={}] - Optional parameters\n * @param {string|string[]} [options.populate] - Fields to populate with related data\n * @param {string|string[]} [options.expand] - Fields to expand with nested data\n * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)\n * @returns {Promise<T>} Promise resolving to the document\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Get user by ID\r\n * const user = await db.getOne('users', 'user_123');\r\n * console.log(user.name);\r\n * \r\n * @example\r\n * // Get user with populated posts\r\n * const userWithPosts = await db.getOne('users', 'user_123', {\r\n * populate: ['posts', 'comments']\r\n * });\r\n * \r\n * @example\r\n * // Get with error handling\r\n * try {\r\n * const user = await db.getOne('users', 'non_existent_id');\r\n * } catch (error) {\r\n * if (error instanceof NotFoundError) {\r\n * console.log('User not found');\r\n * }\r\n * }\r\n */\r\n public async getOne<T extends DocumentData>(\n collection: string, \n id: string, \n options: { populate?: string | string[]; expand?: string | string[] } = {},\n token?: string\n ): Promise<T> {\n const queryString = this.buildQueryString(options);\n return this.client.request<T>('GET', `/api/data/${collection}/${id}${queryString}`, { token });\n }\n\r\n /**\r\n * Inserts a new document into a collection\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {InsertPayload} data - Document data to insert\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the created document with generated ID\r\n * \r\n * @throws {Error} If collection name is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If unique constraint violation occurs\r\n * \r\n * @example\r\n * // Insert a new user\r\n * const newUser = await db.insert('users', {\r\n * name: 'John Doe',\r\n * email: 'john@example.com',\r\n * age: 25\r\n * });\r\n * console.log('User created:', newUser._id);\r\n * \r\n * @example\r\n * // Insert with custom token\r\n * const result = await db.insert('posts', {\r\n * title: 'My Post',\r\n * content: 'Hello World'\r\n * }, customAuthToken);\r\n * \r\n * @example\r\n * // Insert with error handling\r\n * try {\r\n * const user = await db.insert('users', { email: 'existing@email.com' });\r\n * } catch (error) {\r\n * if (error.message.includes('duplicate')) {\r\n * console.log('Email already exists');\r\n * }\r\n * }\r\n */\r\n public async insert<T extends DocumentData>(\r\n collection: string, \r\n data: InsertPayload, \r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('POST', `/api/data/${collection}`, { \r\n body: data,\r\n token \r\n });\r\n }\r\n\r\n /**\r\n * Updates an existing document by its ID (full replacement)\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {UpdatePayload} data - Complete document data for replacement\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the updated document\r\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Full update of a user\r\n * const updatedUser = await db.update('users', 'user_123', {\r\n * name: 'Jane Doe',\r\n * email: 'jane@example.com',\r\n * age: 26\r\n * });\r\n * \r\n * @example\r\n * // Update with error handling\r\n * try {\r\n * const result = await db.update('users', 'user_123', updatedData);\r\n * console.log('Update successful:', result);\r\n * } catch (error) {\r\n * if (error instanceof NotFoundError) {\r\n * console.log('User not found');\r\n * }\r\n * }\r\n */\r\n public async update<T extends DocumentData>(\r\n collection: string,\r\n id: string,\r\n data: UpdatePayload,\r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('PUT', `/api/data/${collection}/${id}`, { \r\n body: data,\r\n token\r\n });\r\n }\r\n\r\n /**\r\n * Partially updates an existing document by its ID (only provided fields)\r\n * \r\n * @template T - The document type (extends DocumentData)\r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document\r\n * @param {PatchPayload} data - Partial data to update\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<T>} Promise resolving to the updated document\r\n * \r\n * @throws {NotFoundError} If document with given ID does not exist\r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If data validation fails\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Partial update - only update age\r\n * const updatedUser = await db.patch('users', 'user_123', {\r\n * age: 26\r\n * });\r\n * \r\n * @example\r\n * // Add a new field to document\r\n * const result = await db.patch('users', 'user_123', {\r\n * lastLogin: new Date().toISOString()\r\n * });\r\n * \r\n * @example\r\n * // Partial update with error handling\r\n * try {\r\n * const result = await db.patch('products', 'prod_123', {\r\n * price: 29.99\r\n * });\r\n * console.log('Price updated:', result);\r\n * } catch (error) {\r\n * console.error('Update failed:', error.message);\r\n * }\r\n */\r\n public async patch<T extends DocumentData>(\r\n collection: string,\r\n id: string,\r\n data: PatchPayload,\r\n token?: string\r\n ): Promise<T> {\r\n return this.client.request<T>('PATCH', `/api/data/${collection}/${id}`, { \r\n body: data,\r\n token\r\n });\r\n }\r\n\r\n /**\r\n * Deletes a document by its ID\r\n * \r\n * @param {string} collection - Name of the collection\r\n * @param {string} id - Unique identifier of the document to delete\r\n * @param {string} [token] - Optional authentication token (overrides client default)\r\n * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status\r\n * \r\n * @throws {Error} If collection name or ID is invalid\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If user lacks permission to delete\r\n * \r\n * @example\r\n * // Delete a user\r\n * const result = await db.delete('users', 'user_123');\r\n * if (result.deleted) {\r\n * console.log('User deleted successfully');\r\n * }\r\n * \r\n * @example\r\n * // Delete with error handling\r\n * try {\r\n * const { deleted } = await db.delete('posts', 'post_456');\r\n * if (deleted) {\r\n * console.log('Post removed');\r\n * }\r\n * } catch (error) {\r\n * console.error('Deletion failed:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Delete after checking existence\r\n * const exists = await db.getOne('users', 'user_123').catch(() => null);\r\n * if (exists) {\r\n * await db.delete('users', 'user_123');\r\n * console.log('User deleted');\r\n * }\r\n */\r\n public async delete(collection: string, id: string, token?: string): Promise<{ deleted: boolean }> {\r\n const result = await this.client.request<{ message?: string; id?: string } | null>(\r\n 'DELETE',\r\n `/api/data/${collection}/${id}`,\r\n { token },\r\n );\r\n\r\n const deleted =\r\n typeof result === 'object' &&\r\n result !== null &&\r\n (result.id === id || result.message === 'Document deleted');\r\n\r\n return { deleted };\r\n }\r\n\r\n /**\r\n * Internal helper to build query string from QueryParams\r\n * \r\n * @param {QueryParams} params - Query parameters to convert\r\n * @returns {string} URL query string (starting with '?' if parameters exist, otherwise empty)\r\n * \r\n * @internal\r\n * @private\r\n * \r\n * @example\r\n * // Returns \"?limit=10&sort=-createdAt\"\r\n * buildQueryString({ limit: 10, sort: '-createdAt' })\r\n * \r\n * @example\r\n * // Returns \"?status=active&age=25\"\r\n * buildQueryString({ filter: { status: 'active', age: 25 } })\r\n */\r\n private buildQueryString(params: QueryParams): string {\r\n const searchParams = new URLSearchParams();\r\n\r\n Object.entries(params).forEach(([key, value]) => {\r\n if (value === undefined || value === null) return;\r\n\r\n if (key === 'filter' && typeof value === 'object') {\r\n Object.entries(value as Record<string, unknown>).forEach(([fKey, fValue]) => {\r\n if (fValue !== undefined && fValue !== null) {\r\n searchParams.append(fKey, String(fValue));\r\n }\r\n });\r\n } else if ((key === 'populate' || key === 'expand') && Array.isArray(value)) {\r\n searchParams.append(key, value.join(','));\r\n } else {\r\n searchParams.append(key, String(value));\r\n }\r\n });\r\n\r\n const str = searchParams.toString();\r\n return str ? `?${str}` : '';\r\n }\r\n}\n","/// <reference lib=\"dom\" />\r\nimport { UrBackendClient } from '../client';\r\nimport { UploadResponse } from '../types';\r\n\r\n/**\r\n * Module for handling file storage operations in urBackend\r\n * \r\n * @class StorageModule\r\n * @description Provides methods to upload and delete files in the urBackend storage system.\r\n * Supports both browser (File/Blob) and Node.js (Buffer) environments.\r\n * \r\n * @example\r\n * // Initialize the storage module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const storage = new StorageModule(client);\r\n * \r\n * // Upload a file (Browser)\r\n * const fileInput = document.getElementById('fileInput');\r\n * const result = await storage.upload(fileInput.files[0], 'my-file.pdf');\r\n * console.log(result.url);\r\n * \r\n * @example\r\n * // Upload a file (Node.js)\r\n * const fs = require('fs');\r\n * const buffer = fs.readFileSync('./document.pdf');\r\n * const result = await storage.upload(buffer, 'document.pdf');\r\n */\r\nexport class StorageModule {\r\n /**\r\n * Creates an instance of StorageModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const storage = new StorageModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Uploads a file to the urBackend storage\r\n * \r\n * @param {unknown} file - The file to upload. Supports:\r\n * - Browser: File, Blob\r\n * - Node.js: Buffer\r\n * @param {string} [filename] - Optional custom filename for the uploaded file\r\n * @returns {Promise<UploadResponse>} Promise resolving to upload details including URL and file ID\r\n * \r\n * @throws {Error} If file is invalid or missing\r\n * @throws {Error} If file size exceeds limits\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If storage quota is exceeded\r\n * \r\n * @example\r\n * // Browser: Upload from file input\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * const result = await storage.upload(file, 'custom-name.pdf');\r\n * console.log('File URL:', result.url);\r\n * \r\n * @example\r\n * // Node.js: Upload Buffer\r\n * const fs = require('fs');\r\n * const buffer = fs.readFileSync('./image.png');\r\n * const result = await storage.upload(buffer, 'image.png');\r\n * console.log('Uploaded:', result.fileId);\r\n * \r\n * @example\r\n * // Upload without custom filename (uses original name)\r\n * const result = await storage.upload(file);\r\n * \r\n * @example\r\n * // Upload with error handling\r\n * try {\r\n * const result = await storage.upload(file, 'document.pdf');\r\n * console.log('Upload successful:', result.url);\r\n * } catch (error) {\r\n * console.error('Upload failed:', error.message);\r\n * // Handle error: retry, show user message, etc.\r\n * }\r\n */\r\n public async upload(file: unknown, filename?: string): Promise<UploadResponse> {\r\n // figure out name, contentType and size depending on environment\r\n let resolvedName = filename || \"file\";\r\n let contentType = \"application/octet-stream\";\r\n let fileSize: number;\r\n let fileData: Blob | BufferSource;\r\n\r\n if (typeof File !== \"undefined\" && file instanceof File) {\r\n // browser File object\r\n resolvedName = filename || file.name;\r\n contentType = file.type || contentType;\r\n fileSize = file.size;\r\n fileData = file;\r\n } else if (file instanceof Blob) {\r\n contentType = file.type || contentType;\r\n fileSize = file.size;\r\n fileData = file;\r\n } else if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(file)) {\r\n // Node.js Buffer\r\n fileSize = (file as Buffer).length;\r\n fileData = file as unknown as BufferSource;\r\n } else {\r\n throw new Error(\"Unsupported file type. Pass a File, Blob, or Buffer.\");\r\n }\r\n\r\n // step 1 — ask server for a signed URL\r\n const { signedUrl, filePath } = await this.client.request<{ signedUrl: string; filePath: string }>(\r\n \"POST\",\r\n \"/api/storage/upload-request\",\r\n { body: { filename: resolvedName, contentType, size: fileSize } }\r\n );\r\n\r\n // step 2 — upload directly to cloud, server not involved\r\n const putResponse = await fetch(signedUrl, {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": contentType },\r\n body: fileData as BodyInit,\r\n });\r\n\r\n if (!putResponse.ok) {\r\n throw new Error(`Direct upload to cloud failed: ${putResponse.status} ${putResponse.statusText}`);\r\n }\r\n\r\n // step 3 — tell server we're done so it can verify + update quota\r\n return this.client.request<UploadResponse>(\r\n \"POST\",\r\n \"/api/storage/upload-confirm\",\r\n { body: { filePath, size: fileSize } }\r\n );\r\n}\r\n /**\r\n * Deletes a file from storage by its path\r\n * \r\n * @param {string} path - The file path or URL of the file to delete\r\n * @returns {Promise<{ deleted: boolean }>} Promise resolving to deletion status\r\n * \r\n * @throws {Error} If path is empty or invalid\r\n * @throws {Error} If file does not exist\r\n * @throws {Error} If authentication fails\r\n * @throws {Error} If user lacks permission to delete the file\r\n * \r\n * @example\r\n * // Delete a file by path\r\n * const result = await storage.deleteFile('uploads/document.pdf');\r\n * if (result.deleted) {\r\n * console.log('File deleted successfully');\r\n * }\r\n * \r\n * @example\r\n * // Delete with error handling\r\n * try {\r\n * const result = await storage.deleteFile('uploads/old-file.jpg');\r\n * console.log('Deleted:', result.deleted);\r\n * } catch (error) {\r\n * console.error('Deletion failed:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Delete after upload\r\n * const uploadResult = await storage.upload(file, 'temp-file.pdf');\r\n * console.log('Uploaded:', uploadResult.url);\r\n * \r\n * // Later, delete the file\r\n * await storage.deleteFile('temp-file.pdf');\r\n * console.log('File cleaned up');\r\n */\r\n public async deleteFile(path: string): Promise<{ deleted: boolean }> {\r\n return this.client.request<{ deleted: boolean }>('DELETE', '/api/storage/file', {\r\n body: { path },\r\n });\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { CollectionSchema } from '../types';\r\n\r\n/**\r\n * Module for managing database schemas in urBackend\r\n * \r\n * @class SchemaModule\r\n * @description Provides methods to fetch and manage collection schema definitions.\r\n * Schemas define the structure, validation rules, and data types for collections.\r\n * \r\n * @example\r\n * // Initialize the schema module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const schema = new SchemaModule(client);\r\n * \r\n * // Get schema for a collection\r\n * const collectionSchema = await schema.getSchema('users');\r\n * console.log(collectionSchema.fields);\r\n */\r\nexport class SchemaModule {\r\n /**\r\n * Creates an instance of SchemaModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const schema = new SchemaModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Fetches the schema definition for a specific collection\r\n * \r\n * @param {string} collection - Name of the collection to fetch schema for\r\n * @returns {Promise<CollectionSchema>} Promise resolving to the collection schema definition\r\n * \r\n * @throws {Error} If collection name is empty or contains only whitespace\r\n * @throws {Error} If collection does not exist\r\n * @throws {Error} If authentication fails\r\n * \r\n * @example\r\n * // Get schema for users collection\r\n * const userSchema = await schema.getSchema('users');\r\n * console.log(userSchema.fields);\r\n * \r\n * @example\r\n * // Get schema for products collection with error handling\r\n * try {\r\n * const productSchema = await schema.getSchema('products');\r\n * console.log('Schema fields:', Object.keys(productSchema.fields));\r\n * } catch (error) {\r\n * console.error('Failed to fetch schema:', error.message);\r\n * }\r\n * \r\n * @example\r\n * // Validate collection name before fetching\r\n * const collectionName = 'my_collection';\r\n * if (collectionName.trim()) {\r\n * const schemaDef = await schema.getSchema(collectionName);\r\n * // Use schema definition\r\n * }\r\n */\r\n public async getSchema(collection: string): Promise<CollectionSchema> {\r\n const trimmedCollection = collection.trim();\r\n if (trimmedCollection === '') {\r\n throw new Error('Collection name cannot be empty or whitespace-only');\r\n }\r\n\r\n const encodedCollection = encodeURIComponent(trimmedCollection);\r\n const response = await this.client.request<{\r\n message: string;\r\n collection: CollectionSchema;\r\n }>('GET', `/api/schemas/${encodedCollection}`);\r\n\r\n return response.collection;\r\n }\r\n}","import { UrBackendClient } from '../client';\r\nimport { SendMailPayload, SendMailResponse } from '../types';\r\n\r\n/**\r\n * Module for handling email operations in urBackend\r\n * \r\n * @class MailModule\r\n * @description Provides methods to send emails using the urBackend mail service.\r\n * Requires a Secret Key (sk_live_...) and should be called from a server environment.\r\n * \r\n * @example\r\n * // Initialize the mail module\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const mail = new MailModule(client);\r\n * \r\n * // Send an email\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Welcome!',\r\n * html: '<h1>Hello World</h1>'\r\n * });\r\n */\r\nexport class MailModule {\r\n /**\r\n * Creates an instance of MailModule\r\n * \r\n * @param {UrBackendClient} client - The authenticated urBackend client instance\r\n * \r\n * @example\r\n * const client = new UrBackendClient({ secretKey: 'sk_live_xxx' });\r\n * const mail = new MailModule(client);\r\n */\r\n constructor(private client: UrBackendClient) {}\r\n\r\n /**\r\n * Sends an email using the urBackend mail service\r\n * \r\n * @param {SendMailPayload} payload - The email content and configuration\r\n * @param {string} payload.to - Recipient email address\r\n * @param {string} payload.subject - Email subject line\r\n * @param {string} payload.html - HTML content of the email\r\n * @param {string} [payload.from] - Optional sender email address (defaults to configured sender)\r\n * @param {string[]} [payload.cc] - Optional CC recipient email addresses\r\n * @param {string[]} [payload.bcc] - Optional BCC recipient email addresses\r\n * @returns {Promise<SendMailResponse>} Promise resolving to email sending status and message ID\r\n * \r\n * @throws {Error} If secret key is missing or invalid\r\n * @throws {Error} If email validation fails\r\n * @throws {Error} If rate limit is exceeded\r\n * \r\n * @example\r\n * // Send a basic email\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Welcome to urBackend',\r\n * html: '<h1>Welcome!</h1><p>Thanks for joining.</p>'\r\n * });\r\n * console.log(result.messageId);\r\n * \r\n * @example\r\n * // Send an email with CC and custom sender\r\n * const result = await mail.send({\r\n * from: 'noreply@myapp.com',\r\n * to: 'user@example.com',\r\n * cc: ['admin@example.com'],\r\n * subject: 'Important Update',\r\n * html: '<p>Your account has been updated.</p>'\r\n * });\r\n * \r\n * @example\r\n * // Send email with error handling\r\n * try {\r\n * const result = await mail.send({\r\n * to: 'user@example.com',\r\n * subject: 'Test',\r\n * html: '<p>Test email</p>'\r\n * });\r\n * console.log('Email sent:', result);\r\n * } catch (error) {\r\n * console.error('Failed to send email:', error);\r\n * }\r\n */\r\n public async send(payload: SendMailPayload): Promise<SendMailResponse> {\r\n return this.client.request<SendMailResponse>('POST', '/api/mail/send', {\r\n body: payload,\r\n });\r\n }\r\n}","import { UrBackendConfig, RequestOptions } from './types';\r\nimport { UrBackendError, parseApiError } from './errors';\r\nimport { AuthModule } from './modules/auth';\r\nimport { DatabaseModule } from './modules/database';\r\nimport { StorageModule } from './modules/storage';\r\nimport { SchemaModule } from './modules/schema';\r\nimport { MailModule } from './modules/mail';\r\n\r\nexport class UrBackendClient {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private _auth?: AuthModule;\r\n private _db?: DatabaseModule;\r\n private _storage?: StorageModule;\r\n private _schema?: SchemaModule;\r\n private _mail?: MailModule;\r\n private headers: Record<string, string>;\r\n\r\n constructor(config: UrBackendConfig) {\r\n if (!config.apiKey) {\r\n throw new Error('urbackend-sdk: apiKey is required to initialize the client.');\r\n }\r\n\r\n this.apiKey = config.apiKey;\r\n this.baseUrl = config.baseUrl || 'https://api.ub.bitbros.in';\r\n this.headers = config.headers || {};\r\n\r\n if (typeof window !== 'undefined' && this.apiKey.startsWith('sk_live_')) {\r\n console.warn(\r\n '⚠️ urbackend-sdk: Avoid exposing your Secret Key (sk_live_...) in client-side code. This can lead to unauthorized access to your account and data. Use your Publishable Key (pk_live_...) instead.',\r\n );\r\n }\r\n }\r\n\r\n get auth(): AuthModule {\r\n if (!this._auth) {\r\n this._auth = new AuthModule(this);\r\n }\r\n return this._auth;\r\n }\r\n\r\n get db(): DatabaseModule {\r\n if (!this._db) {\r\n this._db = new DatabaseModule(this);\r\n }\r\n return this._db;\r\n }\r\n\r\n get storage(): StorageModule {\r\n if (!this._storage) {\r\n this._storage = new StorageModule(this);\r\n }\r\n return this._storage;\r\n }\r\n\r\n get schema(): SchemaModule {\r\n if (!this._schema) {\r\n this._schema = new SchemaModule(this);\r\n }\r\n return this._schema;\r\n }\r\n\r\n get mail(): MailModule {\r\n if (!this._mail) {\r\n this._mail = new MailModule(this);\r\n }\r\n return this._mail;\r\n }\r\n\r\n public getBaseUrl(): string {\r\n return this.baseUrl;\r\n }\r\n\r\n public getApiKey(): string {\r\n return this.apiKey;\r\n }\r\n\r\n /**\r\n * Internal request handler\r\n */\r\n public async request<T>(\r\n method: string,\r\n path: string,\r\n options: RequestOptions = {},\r\n ): Promise<T> {\r\n const url = `${this.baseUrl}${path}`;\r\n const headers: Record<string, string> = {\r\n 'x-api-key': this.apiKey,\r\n 'User-Agent': `urbackend-sdk-js/0.4.2`,\r\n ...this.headers,\r\n };\r\n\r\n if (options.token) {\r\n headers['Authorization'] = `Bearer ${options.token}`;\r\n }\r\n\r\n // Merge custom headers from options if provided\r\n if (options.headers) {\r\n Object.assign(headers, options.headers);\r\n }\r\n\r\n let requestBody: BodyInit | undefined;\r\n\r\n if (options.isMultipart) {\r\n // Fetch handles FormData content type and boundary\r\n requestBody = options.body as FormData;\r\n } else if (options.body) {\r\n headers['Content-Type'] = 'application/json';\r\n requestBody = JSON.stringify(options.body);\r\n }\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method,\r\n headers,\r\n body: requestBody,\r\n credentials: options.credentials,\r\n });\r\n\r\n if (!response.ok) {\r\n throw await parseApiError(response);\r\n }\r\n\r\n const contentType = response.headers.get('content-type');\r\n if (contentType && contentType.includes('application/json')) {\r\n const json = await response.json();\r\n // The API returns { data, success, message }\r\n // If data is present, return it. If success/message are present but no data, return the whole object (for exchange/logout etc)\r\n if (json.data !== undefined) {\r\n return json.data;\r\n }\r\n return json;\r\n }\r\n\r\n return (await response.text()) as unknown as T;\r\n } catch (error) {\r\n if (error instanceof UrBackendError) {\r\n throw error;\r\n }\r\n throw new UrBackendError(\r\n error instanceof Error ? error.message : 'Network request failed',\r\n 0,\r\n path,\r\n );\r\n }\r\n }\r\n}\r\n","import { UrBackendClient } from './client';\r\nimport { UrBackendConfig } from './types';\r\nimport { AuthModule } from './modules/auth';\r\nimport { DatabaseModule } from './modules/database';\r\nimport { StorageModule } from './modules/storage';\r\nimport { SchemaModule } from './modules/schema';\r\nimport { MailModule } from './modules/mail';\r\n\r\nexport * from './types';\r\nexport * from './errors';\r\nexport { UrBackendClient, AuthModule, DatabaseModule, StorageModule, SchemaModule, MailModule };\r\n\r\n/**\r\n * Factory function to create a new urBackend client\r\n */\r\nexport default function urBackend(config: UrBackendConfig): UrBackendClient {\r\n return new UrBackendClient(config);\r\n}\r\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@urbackend/sdk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Official TypeScript SDK for urBackend BaaS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -51,12 +51,12 @@
|
|
|
51
51
|
"@types/node": "^25.5.0",
|
|
52
52
|
"@typescript-eslint/eslint-plugin": "^8.57.2",
|
|
53
53
|
"@typescript-eslint/parser": "^8.57.2",
|
|
54
|
-
"@vitest/coverage-v8": "^
|
|
54
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
55
55
|
"eslint": "^10.1.0",
|
|
56
56
|
"prettier": "^3.8.1",
|
|
57
57
|
"tsup": "^8.5.1",
|
|
58
58
|
"typescript": "^5.9.3",
|
|
59
59
|
"typescript-eslint": "^8.57.2",
|
|
60
|
-
"vitest": "^
|
|
60
|
+
"vitest": "^1.6.0"
|
|
61
61
|
}
|
|
62
62
|
}
|