{"_id":"@dealer-finance/sdk","name":"@dealer-finance/sdk","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@dealer-finance/sdk","version":"0.0.1","description":"TypeScript SDK for Dealer Finance Group API","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./resources/auth":{"types":"./dist/resources/auth.d.ts","import":"./dist/resources/auth.js","require":"./dist/resources/auth.cjs"},"./resources/users":{"types":"./dist/resources/users.d.ts","import":"./dist/resources/users.js","require":"./dist/resources/users.cjs"},"./resources/loans":{"types":"./dist/resources/loans.d.ts","import":"./dist/resources/loans.js","require":"./dist/resources/loans.cjs"},"./resources/partners":{"types":"./dist/resources/partners.d.ts","import":"./dist/resources/partners.js","require":"./dist/resources/partners.cjs"},"./resources/files":{"types":"./dist/resources/files.d.ts","import":"./dist/resources/files.js","require":"./dist/resources/files.cjs"}},"sideEffects":false,"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest","test:ui":"vitest --ui","test:unit":"vitest --run --exclude='**/e2e/**'","test:e2e":"vitest --run tests/e2e","test:coverage":"vitest --coverage","typecheck":"tsc --noEmit","lint":"eslint src --ext .ts","prepublishOnly":"pnpm run build"},"keywords":["dealer-finance","sdk","typescript","api-client","http-client"],"author":{"name":"Dealer Finance Group"},"license":"MIT","peerDependencies":{"axios":"^1.6.0"},"dependencies":{"zod":"^3.22.4"},"devDependencies":{"@types/node":"^20.10.0","@vitest/ui":"^1.0.4","axios":"^1.6.2","axios-mock-adapter":"^1.22.0","happy-dom":"^20.0.10","tsup":"^8.0.1","typescript":"^5.3.3","vitest":"^1.0.4"},"repository":{"type":"git","url":"git+https://github.com/dealer-finance/dealer-backend.git","directory":"sdk/js"},"_id":"@dealer-finance/sdk@0.0.1","bugs":{"url":"https://github.com/dealer-finance/dealer-backend/issues"},"homepage":"https://github.com/dealer-finance/dealer-backend#readme","_nodeVersion":"24.9.0","_npmVersion":"11.6.0","dist":{"integrity":"sha512-TU4tqNaV9CBwXX5RzOtDCsaG1mRjmlTmkkn357v6UsSNZ7HpPJQjbmNjkEKqMuPo4m7eQ65vbKcW+X1rR689bg==","shasum":"8ece0b64f35846d61660288749f87e723bfa9361","tarball":"https://registry.npmjs.org/@dealer-finance/sdk/-/sdk-0.0.1.tgz","fileCount":72,"unpackedSize":291591,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFa/6RyrHxCUWv7O/io+VLionMyEwnNGUKHLF4LyNy2wAiEA+3hnHSx4zI98qoCAytCmoDxe8WYvgvNZ118/sCHC8qU="}]},"_npmUser":{"name":"justin96","email":"justin.le.1105@gmail.com"},"directories":{},"maintainers":[{"name":"justin96","email":"justin.le.1105@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.0.1_1763513473118_0.8877876305470178"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-19T00:51:13.026Z","0.0.1":"2025-11-19T00:51:13.344Z","modified":"2025-11-19T00:51:13.670Z"},"maintainers":[{"name":"justin96","email":"justin.le.1105@gmail.com"}],"description":"TypeScript SDK for Dealer Finance Group API","homepage":"https://github.com/dealer-finance/dealer-backend#readme","keywords":["dealer-finance","sdk","typescript","api-client","http-client"],"repository":{"type":"git","url":"git+https://github.com/dealer-finance/dealer-backend.git","directory":"sdk/js"},"author":{"name":"Dealer Finance Group"},"bugs":{"url":"https://github.com/dealer-finance/dealer-backend/issues"},"license":"MIT","readme":"# @dealer-finance/sdk\n\nTypeScript SDK for Dealer Finance Group API - A production-ready, type-safe client library for JavaScript/TypeScript applications.\n\n## Features\n\n- 🎯 **TypeScript-First**: Full type safety with excellent IntelliSense support\n- 🔄 **Automatic Token Refresh**: Seamless authentication handling with auto-retry on token expiration\n- 🔁 **Smart Retry Logic**: Exponential backoff with jitter for failed requests\n- 📦 **Tree-Shakeable**: Optimized bundle size with code splitting\n- 🌐 **Universal**: Works in Browser, Node.js, and SSR environments\n- 🔌 **Extensible**: Plugin system for custom behavior and logging\n- 📊 **Progress Tracking**: Built-in upload progress for file operations\n- ⚡ **Modern**: Built with latest TypeScript (ES2022+) and Vitest\n- ✅ **Battle-Tested**: 56 passing E2E tests against production API\n\n## Installation\n\n```bash\nnpm install @dealer-finance/sdk axios\n# or\nyarn add @dealer-finance/sdk axios\n# or\npnpm add @dealer-finance/sdk axios\n```\n\n> **Note**: `axios` is a peer dependency and must be installed separately.\n\n## Quick Start\n\n```typescript\nimport { DealerFinanceSDK } from '@dealer-finance/sdk';\n\n// Initialize the SDK\nconst sdk = new DealerFinanceSDK({\n  baseURL: 'https://api.dealer.techlabx.dev/v1',\n});\n\n// Login\nconst response = await sdk.auth.login({\n  email: 'user@example.com',\n  password: 'Demo123!',\n});\n\nconsole.log('Access Token:', response.accessToken);\nconsole.log('User:', response.user);\n\n// Get user profile\nconst profile = await sdk.users.getProfile();\nconsole.log('Profile:', profile);\n\n// List loans with pagination\nconst loans = await sdk.loans.list({ limit: 10 });\nconsole.log('Loans:', loans.data);\nconsole.log('Pagination:', loans.meta);\n\n// Iterate through all loans automatically\nfor await (const loan of sdk.loans.listAll({ status: 'ACTIVE' })) {\n  console.log('Loan:', loan);\n}\n\n// Logout\nawait sdk.auth.logout();\n```\n\n## Configuration\n\n### Basic Configuration\n\n```typescript\nconst sdk = new DealerFinanceSDK({\n  baseURL: 'https://api.dealer.techlabx.dev/v1',\n  timeout: 30000, // 30 seconds\n  debug: false,\n  tokenStorage: 'memory', // or 'localStorage', 'sessionStorage'\n});\n```\n\n### Fluent Configuration API\n\n```typescript\nconst sdk = new DealerFinanceSDK({ baseURL: 'https://api.dealer.techlabx.dev/v1' })\n  .withTimeout(30000)\n  .withDebug(true)\n  .withTokenStorage('localStorage')\n  .withRetry({\n    maxRetries: 3,\n    baseDelay: 1000,\n    backoff: 'exponential',\n  })\n  .onTokenExpired(() => {\n    console.log('Token expired, redirecting to login...');\n    window.location.href = '/login';\n  });\n```\n\n### Configuration Options\n\n```typescript\ninterface SDKConfig {\n  // Required\n  baseURL: string; // API base URL\n\n  // Optional\n  timeout?: number; // Request timeout in ms (default: 30000)\n  tokenStorage?: 'localStorage' | 'sessionStorage' | 'memory' | 'cookie';\n  retry?: {\n    maxRetries: number; // Default: 3\n    backoff: 'exponential' | 'linear' | 'constant'; // Default: 'exponential'\n    baseDelay: number; // Default: 1000ms\n    maxDelay: number; // Default: 30000ms\n    jitter: boolean; // Default: true\n    retryableStatusCodes: number[]; // Default: [408, 429, 500, 502, 503, 504]\n  };\n  debug?: boolean; // Enable debug logging (default: false)\n  headers?: Record<string, string>; // Custom headers\n\n  // Lifecycle Hooks\n  onTokenExpired?: () => void | Promise<void>;\n  onUnauthorized?: (error: AuthError) => void | Promise<void>;\n  onRequest?: (config: AxiosRequestConfig) => void | Promise<void>;\n  onResponse?: (response: any) => void | Promise<void>;\n  onError?: (error: SDKError) => void | Promise<void>;\n}\n```\n\n## API Resources\n\n### Authentication (`sdk.auth`)\n\n```typescript\n// Login\nconst response = await sdk.auth.login({\n  email: 'user@example.com',\n  password: 'Demo123!',\n});\n\n// Register\nconst response = await sdk.auth.register({\n  email: 'newuser@example.com',\n  password: 'Demo123!',\n  firstName: 'John',\n  lastName: 'Doe',\n  role: 'CLIENT', // Optional: 'ADMIN', 'BROKER', 'CLIENT'\n});\n\n// Logout\nawait sdk.auth.logout();\n\n// Refresh token\nconst tokens = await sdk.auth.refreshToken();\n\n// Password reset flow\nawait sdk.auth.requestPasswordReset({ email: 'user@example.com' });\nawait sdk.auth.resetPassword({ \n  token: 'reset-token',\n  newPassword: 'NewDemo123!' \n});\n\n// Email verification\nawait sdk.auth.verifyEmail({ token: 'verification-token' });\nawait sdk.auth.resendVerificationEmail();\n```\n\n### Users (`sdk.users`)\n\n```typescript\n// Get current user profile\nconst profile = await sdk.users.getProfile();\n\n// Update profile\nconst updated = await sdk.users.updateProfile({\n  firstName: 'John',\n  lastName: 'Doe',\n  phoneNumber: '+61412345678',\n});\n\n// List users (admin only)\nconst users = await sdk.users.list({\n  page: 1,\n  limit: 10,\n  search: 'john',\n  role: 'BROKER',\n  status: 'ACTIVE',\n});\n\n// Iterate all users (admin only)\nfor await (const user of sdk.users.listAll({ role: 'BROKER' })) {\n  console.log(user);\n}\n\n// Get user by ID (admin only)\nconst user = await sdk.users.get('user-id');\n\n// Update user (admin only)\nconst updated = await sdk.users.updateUser('user-id', {\n  status: 'INACTIVE',\n});\n\n// Delete user (admin only)\nawait sdk.users.remove('user-id');\n```\n\n### Loans (`sdk.loans`)\n\n```typescript\n// Create loan\nconst loan = await sdk.loans.create({\n  loanAmount: 50000,\n  loanTerm: 60,\n  interestRate: 5.5,\n  purpose: 'CAR_PURCHASE',\n  // ... other fields\n});\n\n// Get loan by ID\nconst loan = await sdk.loans.get('loan-id');\n\n// List loans\nconst loans = await sdk.loans.list({\n  page: 1,\n  limit: 10,\n  status: 'ACTIVE',\n  partnerId: 'partner-id',\n});\n\n// Iterate all loans\nfor await (const loan of sdk.loans.listAll({ status: 'ACTIVE' })) {\n  console.log(loan);\n}\n\n// Update loan\nconst updated = await sdk.loans.update('loan-id', {\n  status: 'APPROVED',\n  notes: 'Approved by broker',\n});\n\n// Assign broker to loan\nconst assigned = await sdk.loans.assignBroker('loan-id', 'broker-id');\n\n// Delete loan\nawait sdk.loans.remove('loan-id');\n```\n\n### Partners (`sdk.partners`)\n\n```typescript\n// Create partner\nconst partner = await sdk.partners.create({\n  firstName: 'Jane',\n  lastName: 'Smith',\n  email: 'jane@example.com',\n  phoneNumber: '+61498765432',\n  // ... other fields\n});\n\n// Get partner by ID\nconst partner = await sdk.partners.get('partner-id');\n\n// List partners\nconst partners = await sdk.partners.list({\n  page: 1,\n  limit: 10,\n  search: 'smith',\n});\n\n// Iterate all partners\nfor await (const partner of sdk.partners.listAll()) {\n  console.log(partner);\n}\n\n// Update partner\nconst updated = await sdk.partners.update('partner-id', {\n  phoneNumber: '+61412345678',\n});\n\n// Delete partner\nawait sdk.partners.remove('partner-id');\n```\n\n### Files (`sdk.files`)\n\n```typescript\n// Upload file with progress tracking\nconst file = new File(['content'], 'document.pdf', { type: 'application/pdf' });\n\nconst uploaded = await sdk.files.upload(file, {\n  onUploadProgress: (progress) => {\n    console.log(`Upload progress: ${progress.percentage}%`);\n    console.log(`Uploaded: ${progress.loaded} / ${progress.total} bytes`);\n  },\n});\n\nconsole.log('File ID:', uploaded.id);\nconsole.log('File URL:', uploaded.url);\n\n// Download file\nconst blob = await sdk.files.download('file-id');\n\n// Delete file\nawait sdk.files.remove('file-id');\n```\n\n## Pagination\n\nThe SDK supports two types of pagination:\n\n### Cursor-Based Pagination (Default)\n\n```typescript\nconst response = await sdk.loans.list({ limit: 10 });\n\nconsole.log(response.data); // Array of loans\nconsole.log(response.meta.hasNextPage); // boolean\nconsole.log(response.meta.nextCursor); // string | null\nconsole.log(response.meta.hasPreviousPage); // boolean\nconsole.log(response.meta.previousCursor); // string | null\n```\n\n### Offset-Based Pagination\n\n```typescript\nconst response = await sdk.loans.list({ page: 2, limit: 10 });\n\nconsole.log(response.data); // Array of loans\nconsole.log(response.meta.page); // 2\nconsole.log(response.meta.limit); // 10\nconsole.log(response.meta.total); // Total count (if available)\n```\n\n### Auto-Pagination\n\n```typescript\n// Automatically fetches all pages\nfor await (const loan of sdk.loans.listAll({ status: 'ACTIVE' })) {\n  console.log(loan);\n  // Process each loan individually\n}\n```\n\n## Error Handling\n\n```typescript\nimport {\n  AuthError,\n  ValidationError,\n  NetworkError,\n  NotFoundError,\n  ServerError,\n} from '@dealer-finance/sdk';\n\ntry {\n  await sdk.auth.login(credentials);\n} catch (error) {\n  if (error instanceof AuthError) {\n    // 401 Unauthorized\n    console.error('Authentication failed:', error.message);\n  } else if (error instanceof ValidationError) {\n    // 400 Bad Request\n    console.error('Validation failed:', error.details);\n  } else if (error instanceof NotFoundError) {\n    // 404 Not Found\n    console.error('Resource not found:', error.message);\n  } else if (error instanceof NetworkError) {\n    // Network/Connection errors\n    console.error('Network error:', error.message);\n  } else if (error instanceof ServerError) {\n    // 500 Internal Server Error\n    console.error('Server error:', error.message);\n  }\n}\n```\n\n### Error Properties\n\n```typescript\nerror.message; // Error message\nerror.statusCode; // HTTP status code\nerror.traceId; // Request trace ID for debugging\nerror.timestamp; // Error timestamp\nerror.isRetryable; // Whether the error can be retried\n```\n\n## Plugins\n\n### Logger Plugin\n\n```typescript\nimport { DealerFinanceSDK, LoggerPlugin } from '@dealer-finance/sdk';\n\nconst sdk = new DealerFinanceSDK({\n  baseURL: 'https://api.dealer.techlabx.dev/v1',\n}).use(new LoggerPlugin(true)); // Enable debug logging\n\n// Logs all requests and responses\nawait sdk.auth.login({ email: 'user@example.com', password: 'Demo123!' });\n// [2025-11-18T14:00:00.000Z] → Request: POST /auth/login\n// [2025-11-18T14:00:00.362Z] ← Response: 200 POST /auth/login\n```\n\n### Custom Plugin\n\n```typescript\nimport type { Plugin } from '@dealer-finance/sdk';\n\nclass CustomPlugin implements Plugin {\n  name = 'custom';\n  version = '1.0.0';\n\n  onRequest(config) {\n    console.log('Before request:', config.url);\n    return config;\n  }\n\n  onResponse(response) {\n    console.log('After response:', response.status);\n    return response;\n  }\n\n  onError(error) {\n    console.error('Request error:', error.message);\n    return error;\n  }\n}\n\nsdk.use(new CustomPlugin());\n```\n\n## Advanced Usage\n\n### Abort Requests\n\n```typescript\nconst controller = new AbortController();\n\n// Pass signal to request\nconst promise = sdk.loans.list({ limit: 10 }, controller.signal);\n\n// Cancel request\ncontroller.abort();\n\ntry {\n  await promise;\n} catch (error) {\n  console.log('Request cancelled');\n}\n```\n\n### Token Management\n\n```typescript\n// Get token storage\nconst storage = sdk.getAxiosInstance().defaults.headers.common;\n\n// Manual token refresh\nawait sdk.auth.refreshToken();\n\n// Clear tokens\nawait sdk.destroy();\n```\n\n## TypeScript Support\n\nFull TypeScript support with type definitions for all APIs:\n\n```typescript\nimport type {\n  User,\n  Loan,\n  Partner,\n  UserRole,\n  LoanStatus,\n  PaginatedResponse,\n} from '@dealer-finance/sdk';\n\n// All types are exported and available\nconst user: User = await sdk.users.getProfile();\nconst loans: PaginatedResponse<Loan> = await sdk.loans.list();\n```\n\n## Development\n\n```bash\n# Install dependencies\npnpm install\n\n# Run unit tests\npnpm test:unit\n\n# Run E2E tests (requires production API)\npnpm test:e2e\n\n# Run all tests with coverage\npnpm test:coverage\n\n# Build for production\npnpm build\n\n# Watch mode for development\npnpm dev\n\n# Type checking\npnpm typecheck\n```\n\n## Testing\n\nThe SDK includes comprehensive E2E tests against production API:\n\n- ✅ 18 Authentication tests (login, register, logout, password reset)\n- ✅ 15 User management tests (profile, CRUD operations, pagination)\n- ✅ 12 Multi-role tests (admin, broker, client permissions)\n- ✅ 16 SDK features tests (plugins, config, lifecycle hooks)\n\nRun tests:\n\n```bash\n# Run E2E tests\nE2E_API_URL=https://api.dealer.techlabx.dev/v1 pnpm test:e2e\n\n# Run with debug mode\nE2E_DEBUG=true pnpm test:e2e\n```\n\n## Browser Support\n\n- Chrome/Edge (latest)\n- Firefox (latest)\n- Safari (latest)\n- Node.js 18+\n\n## License\n\nMIT © Dealer Finance Group\n\n## Support\n\nFor issues and feature requests, please open an issue on GitHub.\n\n## Changelog\n\n### 0.0.1 (2025-11-18)\n\n- 🎉 Initial beta release\n- ✅ Full TypeScript support\n- 🔐 Authentication & authorization\n- 📦 User, Loan, Partner, File management\n- 📄 Pagination (cursor & offset-based)\n- 🔄 Auto-retry with exponential backoff\n- 🔌 Plugin system\n- ✅ Comprehensive E2E tests (56 passing)\n","readmeFilename":"README.md","_rev":"1-38d9ee5eac30560f906007a0c979847d"}