@tradly/auth
v1.0.44
Published
Auth package for Tradly - handles authentication (email, phone, social login)
Readme
@tradly/auth
Authentication package for Tradly platform - handles email, phone, and social login with automatic PK key and auth key management.
Installation
npm install @tradly/authQuick Start
import { initializeAuth, emailLogin } from "@tradly/auth";
// Initialize the package with your domain and environment
initializeAuth("beauty.tradly.co", "production");
// Now you can use all auth functions
const response = await emailLogin("[email protected]", "password123");
if (response.status) {
console.log("Login successful!", response.data);
}Initialization
Important: You must call initializeAuth() before using any other
functions. This sets up the domain, environment, and base URL for all API calls.
Automatic Features on Initialization:
- ✅ UUID Auto-Generation - Automatically generates and stores UUID in cookie/localStorage
- ✅ PK Key Auto-Fetch - Automatically fetches and caches PK key from API
- ✅ PK Key Encryption - PK key is stored encrypted in cookie for security
import { initializeAuth } from "@tradly/auth";
// Initialize with domain and environment
// This automatically:
// 1. Generates UUID (if not exists)
// 2. Fetches PK key from API
// 3. Stores PK key encrypted in cookie/localStorage
// 4. Caches everything for fast access
initializeAuth("beauty.tradly.co", "production");
// Or with custom base URL
initializeAuth("beauty.tradly.co", "production", "https://api.custom.com");
// For React Native or custom storage (see React Native section below)
initializeAuth("beauty.tradly.co", "production", undefined, {
web: false,
storage: customStorageAdapter,
});Supported Environments
production- Useshttps://api.tradly.app(default)development- Useshttps://api.dev.tradly.applocal- Useshttp://localhost:3000
Multi-Domain Support
The package supports multiple domains in the same browser session. Each domain maintains its own configuration, auth keys, and PK keys.
// Initialize first domain
initializeAuth("beauty.tradly.co", "production");
// Switch to another domain
initializeAuth("fashion.tradly.co", "production");
// Get config for specific domain
import { getAuthConfigByDomain } from "@tradly/auth";
const config = getAuthConfigByDomain("beauty.tradly.co");Authentication Methods
Email Login
import { emailLogin } from "@tradly/auth";
const response = await emailLogin("[email protected]", "password123");
if (response.status) {
const { user } = response.data;
// Auth keys are automatically stored in cookies/localStorage
console.log("User:", user);
} else {
console.error("Login failed:", response.error);
}Phone Login
import { phoneLogin } from "@tradly/auth";
const response = await phoneLogin(
"1234567890", // phone number
"+1", // country code
"password123" // password
);
if (response.status) {
console.log("Login successful!", response.data);
}Social Login
import { socialLogin } from "@tradly/auth";
// Google login
const googleResponse = await socialLogin("google", googleAccessToken);
// Facebook login
const facebookResponse = await socialLogin("facebook", facebookAccessToken);
// Note:
// Currently the SDK types support "google" and "facebook" as providers.
// Apple login can be added when backend and SDK support are aligned.Sign Up
Email Sign Up
import { emailSignUp } from "@tradly/auth";
const response = await emailSignUp(
"John", // first name
"Doe", // last name
"[email protected]", // email
"password123" // password
);
if (response.status) {
console.log("Sign up successful!", response.data);
}Phone Sign Up
import { phoneSignUp } from "@tradly/auth";
const response = await phoneSignUp(
"John", // first name
"Doe", // last name
"1234567890", // phone number
"+1", // country code
"password123" // password
);
if (response.status) {
console.log("Sign up successful!", response.data);
}Verification
Verify OTP
import { verifyUser } from "@tradly/auth";
const response = await verifyUser(
verifyId, // Verification ID from sign up response
"123456" // OTP code
);
if (response.status) {
console.log("Verification successful!", response.data.user);
}Resend OTP
import { resendOTP } from "@tradly/auth";
const response = await resendOTP({
verify_id: verifyId,
// ... other user data
});
if (response.status) {
console.log("OTP resent successfully!");
}User Profile
Get User Profile
import { getUserProfile } from "@tradly/auth";
const response = await getUserProfile();
if (response.status) {
const user = response.data;
console.log("User profile:", user);
}Update User Profile
import { updateUserProfile } from "@tradly/auth";
const response = await updateUserProfile({
first_name: "John",
last_name: "Doe",
phone: "1234567890",
country_code: "+1",
// ... other fields
});
if (response.status) {
console.log("Profile updated!", response.data);
}Get User Info
import { getUserInfo } from "@tradly/auth";
// Get a specific user by ID
const response = await getUserInfo(123);
if (response.status) {
console.log("User info:", response.data);
}Auth Key Management
The package automatically manages auth keys using domain-scoped cookies and localStorage.
Get Auth Key
import { getAuthKey, getUUID, getRefreshKey } from "@tradly/auth";
// Get current auth key (automatically reads from cookies/localStorage)
const authKey = getAuthKey();
// Get UUID
const uuid = getUUID();
// Get refresh key
const refreshKey = getRefreshKey();Set Auth Key
import { setAuthKey, setUUID } from "@tradly/auth";
// Set auth key (stores in cookies and localStorage)
setAuthKey("your-auth-key");
// Set UUID
setUUID("your-uuid");Logout
import { logout, quickLogout } from "@tradly/auth";
// Full logout - calls logout API and clears all data
const response = await logout();
if (response.status) {
console.log("Logout successful:", response.data?.message);
}
// Logout with UUID clearing (optional)
await logout({ clearUUID: true });
// Quick logout - clears all data without API call (client-side only)
quickLogout(); // Keeps UUID
quickLogout(true); // Also clears UUIDWhat logout() clears:
- ✅ Auth key (from cache, cookie, localStorage)
- ✅ Refresh key (from cache, cookie, localStorage)
- ✅ Firebase token (from cache, cookie, localStorage)
- ✅ User info (from cache, localStorage)
- ✅ PK key cache
- ✅ Optionally UUID (default: keeps UUID for future logins)
Note: The logout function always clears local data even if the API call fails, ensuring users are logged out locally.
Clear Auth Key (Manual)
import { clearAuthKey, clearAllUserData } from "@tradly/auth";
// Clear only auth key
clearAuthKey();
// Clear all user data (auth_key, refresh_key, firebase_token, user_info)
clearAllUserData();Check Auth Key Status
import { hasAuthKey, hasUUID } from "@tradly/auth";
if (hasAuthKey()) {
console.log("User is authenticated");
}
if (hasUUID()) {
console.log("UUID is set");
}PK Key Management
Automatic PK Key Fetching
When you call initializeAuth(), the PK key is automatically fetched and:
- ✅ Cached in memory (1 hour TTL)
- ✅ Stored encrypted in cookie (1 hour TTL)
- ✅ Available immediately for all API calls
Security: PK keys are encrypted using domain-based encryption before storing in cookies.
Get PK Key by Domain
import { getPKKeyByDomain } from "@tradly/auth";
// Get PK key (checks cache first, then encrypted cookie, then API)
// Automatically stores encrypted in cookie after fetch
const pkData = await getPKKeyByDomain("beauty.tradly.co", "production");
if (pkData) {
const pkKey = pkData.key;
console.log("PK Key:", pkKey);
console.log("Domain Info:", pkData.domain);
}Note: PK key is automatically fetched during initializeAuth(), so you
rarely need to call this manually.
Get Cached PK Key
import { getCachedPKKey } from "@tradly/auth";
// Get PK key from cache (no API call)
const cachedPkKey = getCachedPKKey("beauty.tradly.co", "production");
if (cachedPkKey) {
console.log("Cached PK Key:", cachedPkKey.key);
}Clear PK Key Cache
import { clearPKKeyCache } from "@tradly/auth";
// Clear cached PK key
clearPKKeyCache("beauty.tradly.co", "production");Auth Type Validation
Get Auth Type
import { getAuthType } from "@tradly/auth";
// Get auth type configuration
const authType = await getAuthType();
// authType can be:
// - 1: Email only
// - 2: Phone only
// - 3: Both email and phone
// - null: Not configuredCheck Auth Methods
import { isEmailAuthEnabled, isPhoneAuthEnabled } from "@tradly/auth";
// Check if email auth is enabled
const emailEnabled = await isEmailAuthEnabled();
// Check if phone auth is enabled
const phoneEnabled = await isPhoneAuthEnabled();Configuration
Get Configuration
import {
getAuthConfig,
getDomain,
getEnv,
getBaseUrl,
isAuthInitialized,
} from "@tradly/auth";
// Get full config
const config = getAuthConfig();
console.log(config); // { domain, env, baseUrl }
// Get individual values
const domain = getDomain();
const env = getEnv();
const baseUrl = getBaseUrl();
// Check if initialized
if (isAuthInitialized()) {
console.log("Auth package is initialized");
}Clear Configuration
import { clearAuthConfig, clearAuthConfigByDomain } from "@tradly/auth";
// Clear current domain config
clearAuthConfig();
// Clear specific domain config
clearAuthConfigByDomain("beauty.tradly.co");Custom Storage (Advanced)
Custom Storage Adapter
For React Native or other non-browser environments, you can provide a custom storage adapter:
Simple Example (React Native with AsyncStorage):
import AsyncStorage from "@react-native-async-storage/async-storage";
import { initializeAuth } from "@tradly/auth";
// Create storage adapter
const storage = {
async getItem(key: string) {
return await AsyncStorage.getItem(key);
},
async setItem(key: string, value: string) {
await AsyncStorage.setItem(key, value);
},
async removeItem(key: string) {
await AsyncStorage.removeItem(key);
},
};
// Initialize with custom storage
initializeAuth("beauty.tradly.co", "production", undefined, {
web: false, // Use custom storage, not web
storage: storage, // Your AsyncStorage adapter
});Advanced Example (with error handling):
import { initializeAuth, AuthStorage } from "@tradly/auth";
const customStorage: AuthStorage = {
async getItem(key: string): Promise<string | null> {
try {
// Your storage implementation
return await yourStorage.get(key);
} catch (e) {
console.warn("Failed to get from storage:", e);
return null;
}
},
async setItem(key: string, value: string): Promise<void> {
try {
// Your storage implementation
await yourStorage.set(key, value);
} catch (e) {
console.warn("Failed to set in storage:", e);
}
},
async removeItem(key: string): Promise<void> {
try {
// Your storage implementation
await yourStorage.remove(key);
} catch (e) {
console.warn("Failed to remove from storage:", e);
}
},
};
// Initialize with custom storage
initializeAuth("beauty.tradly.co", "production", undefined, {
web: false, // Disable web storage (localStorage/cookies)
storage: customStorage, // Use your custom storage
});Custom Auth Key Source (Advanced)
For custom implementations (e.g., Next.js server-side with cookies-next):
import { setAuthKeySource } from "@tradly/auth";
import { getCookie } from "cookies-next";
setAuthKeySource({
getAuthKey: () => {
// Custom implementation
return getCookie(`${domain}_auth_key`, { req, res });
},
getUUID: () => {
return getCookie(`${domain}_uuid`, { req, res });
},
getDomain: () => {
return req.headers.host || window.location.host;
},
});API Fetch Utilities
The package provides low-level fetch utilities that automatically handle PK keys and auth keys:
import { get, post, put, del } from "@tradly/auth";
// GET request (automatically includes auth key or PK key)
const response = await get("/v1/users/me");
// POST request
const response = await post("/v1/users", {
name: "John Doe",
});
// PUT request
const response = await put("/v1/users/123", {
name: "Jane Doe",
});
// DELETE request
const response = await del("/v1/users/123");Features
- ✅ Automatic PK Key Management - Fetches and caches PK keys automatically on initialization
- ✅ PK Key Encryption - PK keys are encrypted (hash-based) before storing in cookies
- ✅ Automatic UUID Generation - Generates and stores UUID automatically on initialization
- ✅ Automatic Auth Key Management - Stores and retrieves auth keys from cookies/localStorage (web) or custom storage (React Native)
- ✅ Domain-Scoped Configuration - Supports multiple domains in the same session
- ✅ Email Authentication - Login and sign up with email
- ✅ Phone Authentication - Login and sign up with phone
- ✅ Social Authentication - Google, Facebook, Apple login
- ✅ OTP Verification - Verify and resend OTP codes
- ✅ User Profile Management - Get, update user profile
- ✅ Auth Type Validation - Check which auth methods are enabled
- ✅ Complete Logout - Calls logout API and clears all stored data (auth_key, refresh_key, firebase_token, user_info, PK key cache)
- ✅ TypeScript Support - Full TypeScript definitions
- ✅ Zero Configuration - Works out of the box with automatic cookie/localStorage handling (web) or custom storage (React Native)
- ✅ React Native Support - Use AsyncStorage or any custom storage adapter
- ✅ Server-Side Support - Custom auth key source for SSR
- ✅ Built-in Caching - PK keys and responses are cached automatically
- ✅ Secure Storage - PK keys encrypted with domain-based hash algorithm for storage
Testing
# Run all tests
npm run test:all
# Run integration tests (against real API)
npm run test:integration
# Run unit tests
npm run test:unit
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
# Run tests with UI
npm run test:uiTypeScript
Full TypeScript support with comprehensive type definitions:
import type {
ApiResponse,
LoginResponse,
SignUpResponse,
UserProfile,
PKKeyResponse,
} from "@tradly/auth";
const response: ApiResponse<UserProfile> = await getUserProfile();Error Handling
All API functions return a consistent response format:
interface ApiResponse<T> {
status: boolean;
data: T;
error?: {
code: number;
message: string;
};
}Example:
const response = await emailLogin("[email protected]", "wrong-password");
if (!response.status) {
console.error("Error:", response.error?.message);
console.error("Code:", response.error?.code);
}Storage Format
The package uses domain-scoped storage key naming:
- Auth Key:
${domain}_auth_key(e.g.,beauty.tradly.co_auth_key) - UUID:
${domain}_uuid(e.g.,beauty.tradly.co_uuid) - Refresh Key:
${domain}_refresh_key(e.g.,beauty.tradly.co_refresh_key) - PK Key:
${domain}_pk_key_${env}(e.g.,beauty.tradly.co_pk_key_production) - Encrypted
Web (default): Keys are stored in cookies and localStorage.
React Native/Custom Storage: Keys are stored using your provided storage adapter (e.g., AsyncStorage).
Security Note: PK keys are encrypted using a domain-based hash algorithm before storing. The encryption ensures that even if storage is accessed, the PK key cannot be easily extracted.
This ensures no conflicts when multiple Tradly applications run in the same environment.
Examples
Complete Login Flow
import {
initializeAuth,
emailLogin,
getUserProfile,
logout,
} from "@tradly/auth";
// Initialize
initializeAuth("beauty.tradly.co", "production");
// Login
const loginResponse = await emailLogin("[email protected]", "password123");
if (loginResponse.status) {
// All keys and user info are automatically stored
console.log("Login successful!");
// Get user profile
const profileResponse = await getUserProfile();
if (profileResponse.status) {
console.log("User:", profileResponse.data);
}
// Logout (calls API and clears all data)
const logoutResponse = await logout();
if (logoutResponse.status) {
console.log("Logout successful!");
}
} else {
console.error("Login failed:", loginResponse.error);
}Sign Up with Verification
import {
initializeAuth,
emailSignUp,
verifyUser,
resendOTP,
} from "@tradly/auth";
initializeAuth("beauty.tradly.co", "production");
// Sign up
const signUpResponse = await emailSignUp(
"John",
"Doe",
"[email protected]",
"password123"
);
if (signUpResponse.status) {
const { verify_id } = signUpResponse.data;
// Verify OTP
const verifyResponse = await verifyUser(verify_id, "123456");
if (verifyResponse.status) {
console.log("Account verified!");
} else {
// Resend OTP if needed
await resendOTP({ verify_id });
}
}React Native Integration
The package supports React Native by using custom storage adapters. Instead of
using browser localStorage and document.cookie, you can provide your own
storage implementation (e.g., AsyncStorage).
Setup
- Install dependencies:
npm install @tradly/auth @react-native-async-storage/async-storage- Create a storage adapter:
Simple Example:
import AsyncStorage from "@react-native-async-storage/async-storage";
import { initializeAuth } from "@tradly/auth";
// Create storage adapter
const storage = {
async getItem(key: string) {
return await AsyncStorage.getItem(key);
},
async setItem(key: string, value: string) {
await AsyncStorage.setItem(key, value);
},
async removeItem(key: string) {
await AsyncStorage.removeItem(key);
},
};
// Initialize with custom storage
initializeAuth("beauty.tradly.co", "production", undefined, {
web: false, // Use custom storage, not web
storage: storage, // Your AsyncStorage adapter
});With Error Handling:
import AsyncStorage from "@react-native-async-storage/async-storage";
import { AuthStorage } from "@tradly/auth";
const reactNativeStorage: AuthStorage = {
async getItem(key: string): Promise<string | null> {
try {
return await AsyncStorage.getItem(key);
} catch (e) {
console.warn("Failed to get from AsyncStorage:", e);
return null;
}
},
async setItem(key: string, value: string): Promise<void> {
try {
await AsyncStorage.setItem(key, value);
} catch (e) {
console.warn("Failed to set in AsyncStorage:", e);
}
},
async removeItem(key: string): Promise<void> {
try {
await AsyncStorage.removeItem(key);
} catch (e) {
console.warn("Failed to remove from AsyncStorage:", e);
}
},
};- Initialize in your app (if using the simple example above, this is already done):
import { initializeAuth } from "@tradly/auth";
// In App.tsx or root component (if using error-handled version)
useEffect(() => {
initializeAuth("beauty.tradly.co", "production", undefined, {
web: false, // Use custom storage, not web localStorage/cookies
storage: reactNativeStorage, // Your React Native storage adapter
});
}, []);Usage
After initialization, use all auth functions normally - keys are automatically managed:
import { emailLogin, getUserProfile, logout } from "@tradly/auth";
// Login - keys automatically stored in AsyncStorage
const response = await emailLogin("[email protected]", "password123");
if (response.status) {
// Get user profile - auth key automatically retrieved
const profile = await getUserProfile();
console.log("User:", profile.data);
}
// Logout - clears all keys from AsyncStorage
await logout();Key Features for React Native
- ✅ Automatic Key Management - Auth keys, refresh keys, UUID, and PK keys are automatically stored/retrieved from AsyncStorage
- ✅ No Manual Key Passing - You don't need to pass
authKeyorpkKeyto API calls - ✅ Persistent Storage - All keys persist across app restarts
- ✅ Same API as Web - Use the exact same functions as web applications
Storage Keys Used
The SDK stores the following keys in AsyncStorage:
${domain}_auth_key- User authentication key${domain}_refresh_key- Refresh token${domain}_firebase_token- Firebase token (if used)${domain}_uuid- Unique user identifier${domain}_user_info- User profile data (JSON)${domain}_pk_key_${env}- PK key (encrypted)tradly_auth_configs- Configuration datatradly_auth_current_domain- Current active domain
Next.js Integration
The SDK supports both server-only usage and hybrid (server + client) usage:
1. Server-only usage (no client initialization)
Use this when:
- All auth-dependent logic runs on the server (server components, route handlers, server actions).
- You read cookies on the server and pass data down to client components as props.
In this case you do not need any client-side initialization component.
// app/layout.tsx (Server Component)
import { initializeAuth, setAuthKeySource } from "@tradly/auth";
import { cookies } from "next/headers";
const DOMAIN = "beauty.tradly.co";
// Initialize on server side (for server components)
initializeAuth(DOMAIN, "production");
// Set up cookie reading for server components
setAuthKeySource({
getAuthKey: () => {
const cookieStore = cookies();
return cookieStore.get(`${DOMAIN}_auth_key`)?.value || null;
},
getUUID: () => {
const cookieStore = cookies();
return cookieStore.get(`${DOMAIN}_uuid`)?.value || null;
},
getDomain: () => DOMAIN,
});
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html>
<body>{children}</body>
</html>
);
}In this setup:
initializeAuthconfigures domain/env/base URL.setAuthKeySourcetells the SDK how to readauth_key/uuidfrom Next.js server cookies.- Server components can safely call
emailLogin,getUserProfile, etc. without any client initializer.
2. Hybrid usage (server + client initialization)
Use this when:
- You have client components that need to call SDK methods directly in the browser (e.g. login forms, sign-up forms, profile pages).
- You want the SDK to create and manage cookies in the browser (UUID, auth key, refresh key, PK key).
In this case you should still initialize on the server and add the
client-side <AuthClientInit /> helper:
// app/layout.tsx (Server Component)
import { initializeAuth, setAuthKeySource } from "@tradly/auth";
import { cookies } from "next/headers";
import { AuthClientInit } from "@tradly/auth/examples/nextjs-client-init";
const DOMAIN = "beauty.tradly.co";
// Initialize on server side (for server components)
initializeAuth(DOMAIN, "production");
// Set up cookie reading for server components
setAuthKeySource({
getAuthKey: () => {
const cookieStore = cookies();
return cookieStore.get(`${DOMAIN}_auth_key`)?.value || null;
},
getUUID: () => {
const cookieStore = cookies();
return cookieStore.get(`${DOMAIN}_uuid`)?.value || null;
},
getDomain: () => DOMAIN,
});
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html>
<body>
{/* Client-side initialization - ensures UUID & PK key are created
and kept in sync in the browser */}
<AuthClientInit
domain={DOMAIN}
env="production"
/>
{children}
</body>
</html>
);
}Here:
- Server components can still use the SDK via
setAuthKeySource. - Client components can also call SDK functions (like
emailLogin) and rely on browser APIs (cookies, localStorage).
✅ Server-side only – just initializeAuth + setAuthKeySource
✅ Server + client – initializeAuth + setAuthKeySource +
AuthClientInit
✅ Works in Server Components – via setAuthKeySource
✅ Works in Client Components – via browser-based initialization
License
ISC
Repository
https://github.com/TRADLY-PLATFORM
