From 8e30626252b1a6b36685e21be89752b597772e9a Mon Sep 17 00:00:00 2001 From: nutcas3 Date: Fri, 17 Apr 2026 17:54:35 +0300 Subject: [PATCH] feat: Add TypeScript SDK with fetch-based HTTP client and comprehensive Telecom Platform API integration - Add package.json with @telecom-platform/sdk 1.0.0, TypeScript 6.0.3, ESLint 10.2.0, Jest 30.3.0 - Add SDKConfig singleton with 30s timeout, 3 retries, 1s retry delay defaults and WebSocket URL support - Add HttpClient with fetch API, exponential backoff retry logic, Bearer token authentication, timeout handling - Add subscriber management: getSubscriber, listSubscribers with pagination/status --- sdk/typescript/README.md | 312 ++++++++++++++++++++++++++++++ sdk/typescript/package.json | 38 ++++ sdk/typescript/src/config.ts | 69 +++++++ sdk/typescript/src/http-client.ts | 131 +++++++++++++ sdk/typescript/src/index.ts | 10 + sdk/typescript/src/subscribers.ts | 193 ++++++++++++++++++ sdk/typescript/src/telecom-sdk.ts | 201 +++++++++++++++++++ sdk/typescript/src/types.ts | 245 +++++++++++++++++++++++ sdk/typescript/tsconfig.json | 31 +++ 9 files changed, 1230 insertions(+) create mode 100644 sdk/typescript/README.md create mode 100644 sdk/typescript/package.json create mode 100644 sdk/typescript/src/config.ts create mode 100644 sdk/typescript/src/http-client.ts create mode 100644 sdk/typescript/src/index.ts create mode 100644 sdk/typescript/src/subscribers.ts create mode 100644 sdk/typescript/src/telecom-sdk.ts create mode 100644 sdk/typescript/src/types.ts create mode 100644 sdk/typescript/tsconfig.json diff --git a/sdk/typescript/README.md b/sdk/typescript/README.md new file mode 100644 index 0000000..34c7dec --- /dev/null +++ b/sdk/typescript/README.md @@ -0,0 +1,312 @@ +# Telecom Platform TypeScript SDK + +A comprehensive TypeScript SDK for integrating with the Telecom Platform API. This SDK provides a clean, type-safe interface for managing subscribers, monitoring usage, handling payments, and receiving real-time updates. + +## Installation + +```bash +npm install @telecom-platform/sdk +# or +yarn add @telecom-platform/sdk +# or +pnpm add @telecom-platform/sdk +``` + +## Quick Start + +```typescript +import { TelecomSDK } from '@telecom-platform/sdk'; + +// Initialize the SDK +const sdk = TelecomSDK.initialize({ + baseURL: 'https://api.telecom-platform.com', + apiKey: 'your-api-key', + websocketURL: 'wss://ws.telecom-platform.com', + enableLogging: true, +}); + +// Connect to WebSocket for real-time updates +await sdk.connectWebSocket(); + +// Subscribe to usage updates for a subscriber +sdk.subscribeToUsage('123456789012345'); + +// Listen for usage updates +sdk.onUsageUpdate((update) => { + console.log('Usage update:', update); +}); + +// Subscribe to alerts +sdk.subscribeToAlerts(); + +// Listen for alerts +sdk.onAlert((alert) => { + console.log('Alert:', alert); +}); + +// List subscribers +const subscribers = await sdk.subscribersService.listSubscribers({ + page: 1, + pageSize: 20, + status: 'active', +}); + +console.log('Subscribers:', subscribers); +``` + +## API Reference + +### Initialization + +```typescript +const sdk = TelecomSDK.initialize({ + baseURL: string, // API base URL (required) + apiKey?: string, // API key (optional) + timeout?: number, // Request timeout in ms (default: 30000) + retryAttempts?: number, // Number of retry attempts (default: 3) + retryDelay?: number, // Retry delay in ms (default: 1000) + enableLogging?: boolean, // Enable debug logging (default: false) + websocketURL?: string, // WebSocket URL for real-time updates +}); +``` + +### Subscriber Management + +```typescript +// List subscribers +const subscribers = await sdk.subscribersService.listSubscribers({ + page: 1, + pageSize: 20, + status: 'active', + organizationId: 'org-123', + search: 'John Doe', +}); + +// Get subscriber by ID +const subscriber = await sdk.subscribersService.getSubscriber(123); + +// Get subscriber by IMSI +const subscriber = await sdk.subscribersService.getSubscriberByImsi('123456789012345'); + +// Create new subscriber +const newSubscriber = await sdk.subscribersService.createSubscriber({ + msisdn: '+1234567890', + firstName: 'John', + lastName: 'Doe', + email: 'john.doe@example.com', + planId: 1, +}); + +// Update subscriber +const updated = await sdk.subscribersService.updateSubscriber(123, { + firstName: 'Jane', + email: 'jane.doe@example.com', +}); + +// Delete subscriber +await sdk.subscribersService.deleteSubscriber(123); + +// Suspend subscriber +await sdk.subscribersService.suspendSubscriber(123); + +// Activate subscriber +await sdk.subscribersService.activateSubscriber(123); + +// Terminate subscriber +await sdk.subscribersService.terminateSubscriber(123); +``` + +### Account Management + +```typescript +// Get subscriber account +const account = await sdk.subscribersService.getSubscriberAccount('123456789012345'); + +// Top up balance +const updatedAccount = await sdk.subscribersService.topUpBalance('123456789012345', { + amount: 1000, // $10.00 in cents + paymentMethodId: 'pm_123', +}); + +// Get usage statistics +const stats = await sdk.subscribersService.getUsageStats('123456789012345', 'monthly'); + +// Get real-time usage +const realtime = await sdk.subscribersService.getRealTimeUsage('123456789012345'); +``` + +### eSIM Management + +```typescript +// Provision eSIM profile +const esim = await sdk.subscribersService.provisionESIM('123456789012345'); + +// Activate eSIM profile +await sdk.subscribersService.activateESIM('123456789012345', esim.profileId); + +// Deactivate eSIM profile +await sdk.subscribersService.deactivateESIM('123456789012345', esim.profileId); + +// Get eSIM status +const status = await sdk.subscribersService.getESIMStatus('123456789012345'); +``` + +### Billing & Invoices + +```typescript +// Get subscriber invoices +const invoices = await sdk.subscribersService.getInvoices('123456789012345'); + +// Get specific invoice +const invoice = await sdk.subscribersService.getInvoice('inv_123'); + +// Download invoice PDF +const pdfBlob = await sdk.subscribersService.downloadInvoicePDF('inv_123'); +``` + +### Real-time Updates + +```typescript +// Connect to WebSocket +await sdk.connectWebSocket(); + +// Subscribe to usage updates +sdk.subscribeToUsage('123456789012345'); + +// Subscribe to alerts +sdk.subscribeToAlerts(); + +// Listen for usage updates +sdk.onUsageUpdate((update) => { + console.log(`Data used: ${update.dataUsed} bytes`); + console.log(`Cost: $${update.cost / 100}`); +}); + +// Listen for alerts +sdk.onAlert((alert) => { + console.log(`Alert: ${alert.message}`); + if (alert.severity === 'critical') { + // Handle critical alert + } +}); + +// Custom event handlers +sdk.onWebSocketEvent('custom_event', (message) => { + console.log('Custom event:', message); +}); + +// Check connection status +if (sdk.isWebSocketConnected) { + console.log('WebSocket is connected'); +} + +// Disconnect +sdk.disconnectWebSocket(); +``` + +### System Monitoring + +```typescript +// Get system statistics +const stats = await sdk.getSystemStats(); +console.log('Active sessions:', stats.activeSessions); +console.log('Total accounts:', stats.totalAccounts); + +// Get health status +const health = await sdk.getHealthStatus(); +console.log('Redis connected:', health.redisConnected); + +// Test connection +const test = await sdk.testConnection(); +console.log('API status:', test.status); +``` + +## Error Handling + +The SDK provides comprehensive error handling with detailed error information: + +```typescript +try { + const subscriber = await sdk.subscribersService.getSubscriber(123); +} catch (error) { + console.error('Error:', error.code); + console.error('Message:', error.message); + console.error('Details:', error.details); + console.error('Timestamp:', error.timestamp); +} +``` + +## Configuration Updates + +You can update the SDK configuration at runtime: + +```typescript +// Update API key +sdk.setApiKey('new-api-key'); + +// Update base URL +sdk.setBaseURL('https://new-api.telecom-platform.com'); + +// Enable/disable logging +sdk.setLogging(true); + +// Get current configuration +const config = sdk.getConfig(); +console.log('Current config:', config); +``` + +## TypeScript Support + +The SDK is fully typed with TypeScript. All methods have proper type definitions and IntelliSense support: + +```typescript +import { Subscriber, SubscriberStatus, UsageType } from '@telecom-platform/sdk'; + +// Types are automatically inferred +const subscriber: Subscriber = await sdk.subscribersService.getSubscriber(123); +const status: SubscriberStatus = subscriber.status; +``` + +## Browser Support + +The SDK works in modern browsers that support: +- ES2020 features +- WebSocket API +- Fetch API + +For older browsers, you may need to include appropriate polyfills. + +## Node.js Usage + +The SDK also works in Node.js environments: + +```typescript +import { TelecomSDK } from '@telecom-platform/sdk'; + +// Node.js WebSocket polyfill may be required +global.WebSocket = require('ws'); + +const sdk = TelecomSDK.initialize({ + baseURL: 'https://api.telecom-platform.com', + apiKey: process.env.API_KEY, +}); +``` + +## Examples + +See the `examples/` directory for complete examples of: +- Basic subscriber management +- Real-time usage monitoring +- eSIM provisioning +- Billing integration +- Custom dashboard implementation + +## Support + +- Documentation: [https://docs.telecom-platform.com/sdk](https://docs.telecom-platform.com/sdk) +- Issues: [GitHub Issues](https://github.com/telecom-platform/sdk/issues) +- Support: support@telecom-platform.com + +## License + +MIT License - see LICENSE file for details. diff --git a/sdk/typescript/package.json b/sdk/typescript/package.json new file mode 100644 index 0000000..cd0d657 --- /dev/null +++ b/sdk/typescript/package.json @@ -0,0 +1,38 @@ +{ + "name": "@telecom-platform/sdk", + "version": "1.0.0", + "description": "TypeScript SDK for Telecom Platform API", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc", + "dev": "tsc --watch", + "test": "jest", + "lint": "eslint src/**/*.ts", + "prepublishOnly": "npm run build" + }, + "keywords": ["telecom", "api", "sdk", "typescript"], + "author": "Telecom Platform Team", + "license": "MIT", + "dependencies": {}, + "devDependencies": { + "@types/node": "^25.6.0", + "@typescript-eslint/eslint-plugin": "^8.58.2", + "@typescript-eslint/parser": "^8.58.2", + "eslint": "^10.2.0", + "jest": "^30.3.0", + "typescript": "^6.0.3" + }, + "files": [ + "dist/**/*", + "README.md" + ], + "repository": { + "type": "git", + "url": "https://github.com/telecom-platform/sdk.git" + }, + "bugs": { + "url": "https://github.com/telecom-platform/sdk/issues" + }, + "homepage": "https://github.com/telecom-platform/sdk#readme" +} diff --git a/sdk/typescript/src/config.ts b/sdk/typescript/src/config.ts new file mode 100644 index 0000000..c96f7e2 --- /dev/null +++ b/sdk/typescript/src/config.ts @@ -0,0 +1,69 @@ +export interface TelecomSDKConfig { + baseURL: string; + apiKey?: string; + timeout?: number; + retryAttempts?: number; + retryDelay?: number; + enableLogging?: boolean; + websocketURL?: string; +} + +export class SDKConfig { + private static instance: SDKConfig; + private config: TelecomSDKConfig; + + private constructor(config: TelecomSDKConfig) { + this.config = { + timeout: 30000, + retryAttempts: 3, + retryDelay: 1000, + enableLogging: false, + ...config + }; + } + + public static initialize(config: TelecomSDKConfig): void { + if (!SDKConfig.instance) { + SDKConfig.instance = new SDKConfig(config); + } + } + + public static getInstance(): SDKConfig { + if (!SDKConfig.instance) { + throw new Error('SDKConfig not initialized. Call SDKConfig.initialize() first.'); + } + return SDKConfig.instance; + } + + public get baseURL(): string { + return this.config.baseURL; + } + + public get apiKey(): string | undefined { + return this.config.apiKey; + } + + public get timeout(): number { + return this.config.timeout!; + } + + public get retryAttempts(): number { + return this.config.retryAttempts!; + } + + public get retryDelay(): number { + return this.config.retryDelay!; + } + + public get enableLogging(): boolean { + return this.config.enableLogging!; + } + + public get websocketURL(): string | undefined { + return this.config.websocketURL; + } + + public updateConfig(updates: Partial): void { + this.config = { ...this.config, ...updates }; + } +} diff --git a/sdk/typescript/src/http-client.ts b/sdk/typescript/src/http-client.ts new file mode 100644 index 0000000..c67c4a2 --- /dev/null +++ b/sdk/typescript/src/http-client.ts @@ -0,0 +1,131 @@ +import { Error as SdkError } from './types'; +import { SDKConfig } from './config'; + +export class HttpClient { + private config: SDKConfig; + + constructor() { + this.config = SDKConfig.getInstance(); + } + + private get headers(): Record { + const h: Record = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }; + if (this.config.apiKey) { + h['Authorization'] = `Bearer ${this.config.apiKey}`; + } + return h; + } + + private buildURL(path: string, params?: Record): string { + const url = new URL(path, this.config.baseURL); + if (params) { + Object.entries(params).forEach(([k, v]) => { + if (v !== undefined && v !== null) { + url.searchParams.set(k, String(v)); + } + }); + } + return url.toString(); + } + + private async fetchWithRetry(url: string, init: RequestInit, attempt = 0): Promise { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), this.config.timeout); + try { + if (this.config.enableLogging) { + console.log(`[SDK] ${init.method ?? 'GET'} ${url}`); + } + + const response = await fetch(url, { ...init, signal: controller.signal }); + + if (this.config.enableLogging) { + console.log(`[SDK] Response ${response.status}`); + } + + if (!response.ok && this.shouldRetry(response.status) && attempt < this.config.retryAttempts) { + await new Promise(r => setTimeout(r, this.config.retryDelay * Math.pow(2, attempt))); + return this.fetchWithRetry(url, init, attempt + 1); + } + + return response; + } catch (err) { + if (attempt < this.config.retryAttempts && !(err instanceof DOMException)) { + await new Promise(r => setTimeout(r, this.config.retryDelay * Math.pow(2, attempt))); + return this.fetchWithRetry(url, init, attempt + 1); + } + throw err; + } finally { + clearTimeout(timeout); + } + } + + private shouldRetry(status: number): boolean { + return status >= 500 || status === 429; + } + + private async handleResponse(response: Response): Promise { + if (!response.ok) { + let body: any = {}; + try { body = await response.json(); } catch { /* empty */ } + const err: SdkError = { + code: body.code ?? `HTTP_${response.status}`, + message: body.message ?? response.statusText, + details: body.details, + timestamp: new Date().toISOString(), + }; + throw err; + } + return response.json() as Promise; + } + + async get(url: string, params?: Record): Promise { + const response = await this.fetchWithRetry( + this.buildURL(url, params), + { method: 'GET', headers: this.headers }, + ); + return this.handleResponse(response); + } + + async post(url: string, data?: unknown): Promise { + const response = await this.fetchWithRetry( + this.buildURL(url), + { method: 'POST', headers: this.headers, body: data ? JSON.stringify(data) : null }, + ); + return this.handleResponse(response); + } + + async put(url: string, data?: unknown): Promise { + const response = await this.fetchWithRetry( + this.buildURL(url), + { method: 'PUT', headers: this.headers, body: data ? JSON.stringify(data) : null }, + ); + return this.handleResponse(response); + } + + async patch(url: string, data?: unknown): Promise { + const response = await this.fetchWithRetry( + this.buildURL(url), + { method: 'PATCH', headers: this.headers, body: data ? JSON.stringify(data) : null }, + ); + return this.handleResponse(response); + } + + async delete(url: string): Promise { + const response = await this.fetchWithRetry( + this.buildURL(url), + { method: 'DELETE', headers: this.headers }, + ); + return this.handleResponse(response); + } + + setApiKey(apiKey: string): void { + this.config.updateConfig({ apiKey }); + } + + setBaseURL(baseURL: string): void { + this.config.updateConfig({ baseURL }); + } +} diff --git a/sdk/typescript/src/index.ts b/sdk/typescript/src/index.ts new file mode 100644 index 0000000..d48089a --- /dev/null +++ b/sdk/typescript/src/index.ts @@ -0,0 +1,10 @@ +// Main entry point for the Telecom Platform TypeScript SDK + +export { TelecomSDK } from './telecom-sdk'; +export { SDKConfig, TelecomSDKConfig } from './config'; +export { HttpClient } from './http-client'; +export { SubscribersService } from './subscribers'; +export { WebSocketClient } from './websocket'; + +// Export all types +export * from './types'; diff --git a/sdk/typescript/src/subscribers.ts b/sdk/typescript/src/subscribers.ts new file mode 100644 index 0000000..c6f8716 --- /dev/null +++ b/sdk/typescript/src/subscribers.ts @@ -0,0 +1,193 @@ +import { HttpClient } from './http-client'; +import { + Subscriber, + CreateSubscriberRequest, + UpdateSubscriberRequest, + ListSubscribersRequest, + PaginatedResponse, + SubscriberAccount, + TopUpRequest, + Invoice, + ProfileStatus, +} from './types'; + +export class SubscribersService { + private http: HttpClient; + + constructor(http: HttpClient) { + this.http = http; + } + + /** + * List all subscribers with pagination and filtering + */ + async listSubscribers(request?: ListSubscribersRequest): Promise> { + const params = { + page: request?.page || 1, + pageSize: request?.pageSize || 20, + status: request?.status, + organizationId: request?.organizationId, + search: request?.search, + }; + + return this.http.get>('/api/subscribers', params); + } + + /** + * Get a specific subscriber by ID + */ + async getSubscriber(id: number): Promise { + return this.http.get(`/api/subscribers/${id}`); + } + + /** + * Get a subscriber by IMSI + */ + async getSubscriberByImsi(imsi: string): Promise { + return this.http.get(`/api/subscribers/imsi/${imsi}`); + } + + /** + * Create a new subscriber + */ + async createSubscriber(request: CreateSubscriberRequest): Promise { + return this.http.post('/api/subscribers', request); + } + + /** + * Update an existing subscriber + */ + async updateSubscriber(id: number, request: UpdateSubscriberRequest): Promise { + return this.http.put(`/api/subscribers/${id}`, request); + } + + /** + * Delete a subscriber + */ + async deleteSubscriber(id: number): Promise { + await this.http.delete(`/api/subscribers/${id}`); + } + + /** + * Get subscriber account information + */ + async getSubscriberAccount(imsi: string): Promise { + return this.http.get(`/api/subscribers/${imsi}/account`); + } + + /** + * Top up subscriber balance + */ + async topUpBalance(imsi: string, request: TopUpRequest): Promise { + return this.http.post(`/api/subscribers/${imsi}/top-up`, request); + } + + /** + * Suspend a subscriber + */ + async suspendSubscriber(id: number): Promise { + return this.http.post(`/api/subscribers/${id}/suspend`); + } + + /** + * Activate a subscriber + */ + async activateSubscriber(id: number): Promise { + return this.http.post(`/api/subscribers/${id}/activate`); + } + + /** + * Terminate a subscriber + */ + async terminateSubscriber(id: number): Promise { + return this.http.post(`/api/subscribers/${id}/terminate`); + } + + /** + * Provision eSIM profile for subscriber + */ + async provisionESIM(imsi: string): Promise<{ profileId: string; activationCode: string }> { + return this.http.post<{ profileId: string; activationCode: string }>(`/api/subscribers/${imsi}/esim/provision`); + } + + /** + * Activate eSIM profile + */ + async activateESIM(imsi: string, profileId: string): Promise { + return this.http.post(`/api/subscribers/${imsi}/esim/activate`, { profileId }); + } + + /** + * Deactivate eSIM profile + */ + async deactivateESIM(imsi: string, profileId: string): Promise { + return this.http.post(`/api/subscribers/${imsi}/esim/deactivate`, { profileId }); + } + + /** + * Get eSIM profile status + */ + async getESIMStatus(imsi: string): Promise { + return this.http.get(`/api/subscribers/${imsi}/esim/status`); + } + + /** + * Get subscriber invoices + */ + async getInvoices(imsi: string, page = 1, pageSize = 20): Promise> { + return this.http.get>(`/api/subscribers/${imsi}/invoices`, { + page, + pageSize, + }); + } + + /** + * Get specific invoice + */ + async getInvoice(invoiceId: string): Promise { + return this.http.get(`/api/invoices/${invoiceId}`); + } + + /** + * Download invoice PDF + */ + async downloadInvoicePDF(invoiceId: string): Promise { + const response = await this.http.get(`/api/invoices/${invoiceId}/pdf`); + return response as any; // Return blob for PDF download + } + + /** + * Get subscriber usage statistics + */ + async getUsageStats(imsi: string, period: 'daily' | 'weekly' | 'monthly' = 'monthly'): Promise<{ + dataUsage: number; + voiceUsage: number; + smsUsage: number; + cost: number; + period: string; + }> { + return this.http.get(`/api/subscribers/${imsi}/usage/stats`, { period }); + } + + /** + * Get real-time usage data + */ + async getRealTimeUsage(imsi: string): Promise<{ + currentSession: { + sessionId: string; + startTime: string; + dataUsed: number; + voiceUsed: number; + smsUsed: number; + cost: number; + } | null; + todayUsage: { + dataUsed: number; + voiceUsed: number; + smsUsed: number; + cost: number; + }; + }> { + return this.http.get(`/api/subscribers/${imsi}/usage/realtime`); + } +} diff --git a/sdk/typescript/src/telecom-sdk.ts b/sdk/typescript/src/telecom-sdk.ts new file mode 100644 index 0000000..6579b62 --- /dev/null +++ b/sdk/typescript/src/telecom-sdk.ts @@ -0,0 +1,201 @@ +import { SDKConfig, TelecomSDKConfig } from './config'; +import { HttpClient } from './http-client'; +import { SubscribersService } from './subscribers'; +import { WebSocketClient, WebSocketEventHandler } from './websocket'; +import { SystemStats, HealthStatus, Alert, RealTimeUsageUpdate, WebSocketMessage } from './types'; + +export class TelecomSDK { + private static instance: TelecomSDK; + private http: HttpClient; + private ws: WebSocketClient; + private subscribers: SubscribersService; + + private constructor() { + this.http = new HttpClient(); + this.ws = new WebSocketClient(); + this.subscribers = new SubscribersService(this.http); + } + + /** + * Initialize the SDK with configuration + */ + static initialize(config: TelecomSDKConfig): TelecomSDK { + if (!TelecomSDK.instance) { + SDKConfig.initialize(config); + TelecomSDK.instance = new TelecomSDK(); + } + return TelecomSDK.instance; + } + + /** + * Get the singleton instance + */ + static getInstance(): TelecomSDK { + if (!TelecomSDK.instance) { + throw new Error('TelecomSDK not initialized. Call TelecomSDK.initialize() first.'); + } + return TelecomSDK.instance; + } + + /** + * Subscribers service + */ + get subscribersService(): SubscribersService { + return this.subscribers; + } + + /** + * Connect to WebSocket for real-time updates + */ + async connectWebSocket(): Promise { + await this.ws.connect(); + } + + /** + * Disconnect from WebSocket + */ + disconnectWebSocket(): void { + this.ws.disconnect(); + } + + /** + * Check if WebSocket is connected + */ + get isWebSocketConnected(): boolean { + return this.ws.isConnected; + } + + /** + * Subscribe to real-time usage updates + */ + subscribeToUsage(imsi: string): void { + this.ws.subscribeToUsage(imsi); + } + + /** + * Unsubscribe from usage updates + */ + unsubscribeFromUsage(imsi: string): void { + this.ws.unsubscribeFromUsage(imsi); + } + + /** + * Subscribe to alerts + */ + subscribeToAlerts(): void { + this.ws.subscribeToAlerts(); + } + + /** + * Unsubscribe from alerts + */ + unsubscribeFromAlerts(): void { + this.ws.unsubscribeFromAlerts(); + } + + /** + * Add WebSocket event handler + */ + onWebSocketEvent(eventType: string, handler: WebSocketEventHandler): void { + this.ws.on(eventType, handler); + } + + /** + * Remove WebSocket event handler + */ + offWebSocketEvent(eventType: string, handler: WebSocketEventHandler): void { + this.ws.off(eventType, handler); + } + + /** + * Get system statistics + */ + async getSystemStats(): Promise { + return this.http.get('/api/system/stats'); + } + + /** + * Get system health status + */ + async getHealthStatus(): Promise { + return this.http.get('/api/system/health'); + } + + /** + * Test API connection + */ + async testConnection(): Promise<{ status: string; timestamp: string }> { + return this.http.get('/api/test'); + } + + /** + * Update API key + */ + setApiKey(apiKey: string): void { + this.http.setApiKey(apiKey); + } + + /** + * Update base URL + */ + setBaseURL(baseURL: string): void { + this.http.setBaseURL(baseURL); + } + + /** + * Enable/disable logging + */ + setLogging(enabled: boolean): void { + SDKConfig.getInstance().updateConfig({ enableLogging: enabled }); + } + + /** + * Get current configuration + */ + getConfig(): TelecomSDKConfig { + const config = SDKConfig.getInstance(); + const result: TelecomSDKConfig = { + baseURL: config.baseURL, + timeout: config.timeout, + retryAttempts: config.retryAttempts, + retryDelay: config.retryDelay, + enableLogging: config.enableLogging, + }; + if (config.apiKey !== undefined) result.apiKey = config.apiKey; + if (config.websocketURL !== undefined) result.websocketURL = config.websocketURL; + return result; + } + + /** + * Convenience method for usage updates + */ + onUsageUpdate(callback: (update: RealTimeUsageUpdate) => void): void { + this.onWebSocketEvent('usage_update', (message: WebSocketMessage) => { + callback(message.data as RealTimeUsageUpdate); + }); + } + + /** + * Convenience method for alerts + */ + onAlert(callback: (alert: Alert) => void): void { + this.onWebSocketEvent('alert', (message: WebSocketMessage) => { + callback(message.data as Alert); + }); + } + + /** + * Cleanup resources + */ + destroy(): void { + this.disconnectWebSocket(); + // Clear any other resources if needed + } +} + +// Export types for external use +export * from './types'; +export * from './config'; +export { WebSocketClient } from './websocket'; +export { HttpClient } from './http-client'; +export { SubscribersService } from './subscribers'; diff --git a/sdk/typescript/src/types.ts b/sdk/typescript/src/types.ts new file mode 100644 index 0000000..e3f9e10 --- /dev/null +++ b/sdk/typescript/src/types.ts @@ -0,0 +1,245 @@ +export interface Subscriber { + id: number; + imsi: string; + msisdn: string; + firstName: string; + lastName: string; + email: string; + organizationId?: string; + planId: number; + euiccId?: string; + profileId?: string; + profileStatus: ProfileStatus; + status: SubscriberStatus; + balance: number; + dataLimit: number; + dataUsed: number; + voiceLimit: number; + voiceUsed: number; + smsLimit: number; + smsUsed: number; + createdAt: string; + updatedAt: string; +} + +export enum SubscriberStatus { + Active = 'active', + Inactive = 'inactive', + Suspended = 'suspended', + Terminated = 'terminated', + Provisioning = 'provisioning' +} + +export enum ProfileStatus { + Active = 'active', + Inactive = 'inactive', + Downloading = 'downloading', + Failed = 'failed' +} + +export interface CreateSubscriberRequest { + msisdn: string; + firstName: string; + lastName: string; + email: string; + organizationId?: string; + planId: number; + euiccId?: string; +} + +export interface UpdateSubscriberRequest { + firstName?: string; + lastName?: string; + email?: string; + organizationId?: string; + planId?: number; +} + +export interface SubscriberAccount { + imsi: string; + balance: number; + dataLimit: number; + dataUsed: number; + voiceLimit: number; + voiceUsed: number; + smsLimit: number; + smsUsed: number; + status: SubscriberStatus; + lastUpdated: string; +} + +export interface UsageEvent { + imsi: string; + sessionId: string; + usageType: UsageType; + volume: number; + timestamp: string; + rate: number; + cost: number; +} + +export enum UsageType { + Data = 'data', + Voice = 'voice', + SMS = 'sms' +} + +export interface RatingPlan { + planId: string; + name: string; + dataRate: number; + voiceRate: number; + smsRate: number; + monthlyFee: number; + dataLimit: number; + voiceLimit: number; + smsLimit: number; +} + +export interface ChargingSession { + sessionId: string; + imsi: string; + startTime: string; + endTime?: string; + dataBytes: number; + voiceSeconds: number; + smsCount: number; + totalCost: number; + status: SessionStatus; +} + +export enum SessionStatus { + Active = 'active', + Completed = 'completed', + Terminated = 'terminated' +} + +export interface SystemStats { + activeSessions: number; + totalAccounts: number; + blockedUsers: number; + lowBalanceAlerts: number; + uptime: number; +} + +export interface HealthStatus { + redisConnected: boolean; + activeSync: boolean; + lastSync: string; + memoryUsage: number; +} + +export interface ApiResponse { + data: T; + message: string; + success: boolean; + code: number; +} + +export interface PaginatedResponse { + data: T[]; + total: number; + page: number; + pageSize: number; + totalPages: number; +} + +export interface ListSubscribersRequest { + page?: number; + pageSize?: number; + status?: SubscriberStatus; + organizationId?: string; + search?: string; +} + +export interface TopUpRequest { + amount: number; + paymentMethodId?: string; +} + +export interface PaymentMethod { + id: string; + type: PaymentMethodType; + last4: string; + expiryMonth: number; + expiryYear: number; + brand: string; + isDefault: boolean; +} + +export enum PaymentMethodType { + CreditCard = 'credit_card', + BankAccount = 'bank_account' +} + +export interface Invoice { + id: string; + subscriberId: number; + amount: number; + currency: string; + status: InvoiceStatus; + dueDate: string; + createdAt: string; + lineItems: InvoiceLineItem[]; +} + +export enum InvoiceStatus { + Draft = 'draft', + Pending = 'pending', + Paid = 'paid', + Overdue = 'overdue', + Cancelled = 'cancelled' +} + +export interface InvoiceLineItem { + description: string; + quantity: number; + unitPrice: number; + amount: number; +} + +export interface WebSocketMessage { + type: string; + data: any; + timestamp: string; +} + +export interface RealTimeUsageUpdate { + imsi: string; + dataUsed: number; + voiceUsed: number; + smsUsed: number; + cost: number; + timestamp: string; +} + +export interface Alert { + id: string; + type: AlertType; + severity: AlertSeverity; + message: string; + subscriberId?: number; + timestamp: string; + resolved: boolean; +} + +export enum AlertType { + LowBalance = 'low_balance', + HighUsage = 'high_usage', + PaymentFailed = 'payment_failed', + SystemError = 'system_error' +} + +export enum AlertSeverity { + Low = 'low', + Medium = 'medium', + High = 'high', + Critical = 'critical' +} + +export interface Error { + code: string; + message: string; + details?: any; + timestamp: string; +} diff --git a/sdk/typescript/tsconfig.json b/sdk/typescript/tsconfig.json new file mode 100644 index 0000000..5fbaa01 --- /dev/null +++ b/sdk/typescript/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["ES2020", "DOM"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "removeComments": false, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "exactOptionalPropertyTypes": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts" + ] +}