semaphoreco 1.0.2 → 1.0.3

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 CHANGED
@@ -144,22 +144,36 @@ var HttpClient = class {
144
144
  maxRetries = this.maxRetries,
145
145
  onRetry = this.onRetry
146
146
  } = options;
147
- const url = `${this.baseUrl}${path}`;
147
+ let url = `${this.baseUrl}${path}`;
148
+ if (method === "GET") {
149
+ const urlObj = new URL(url);
150
+ urlObj.searchParams.set("apikey", this.apiKey);
151
+ url = urlObj.toString();
152
+ }
148
153
  const sanitizedUrl = sanitizeUrl(url);
149
154
  const requestContext = {
150
155
  url: sanitizedUrl,
151
156
  method
152
157
  };
158
+ let requestBody;
159
+ if (method === "POST" && body) {
160
+ requestBody = new URLSearchParams();
161
+ requestBody.set("apikey", this.apiKey);
162
+ for (const [key, value] of Object.entries(body)) {
163
+ if (value !== void 0 && value !== null) {
164
+ requestBody.set(key, String(value));
165
+ }
166
+ }
167
+ }
153
168
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
154
169
  try {
155
170
  const response = await fetch(url, {
156
171
  method,
157
172
  headers: {
158
- "Content-Type": "application/json",
159
- "Authorization": `Bearer ${this.apiKey}`,
173
+ ...method === "POST" ? { "Content-Type": "application/x-www-form-urlencoded" } : {},
160
174
  ...headers
161
175
  },
162
- body: body ? JSON.stringify(body) : void 0,
176
+ body: requestBody,
163
177
  signal: AbortSignal.timeout(timeout)
164
178
  });
165
179
  if (!response.ok) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/errors.ts","../src/http/client.ts","../src/resources/messages.ts","../src/resources/otp.ts","../src/resources/account.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { RequestContext } from '../types/http.js';\n\n/**\n * Base error class for all Semaphore API errors.\n * Extend this for specific error types.\n */\nexport class SemaphoreError extends Error {\n public readonly statusCode?: number;\n public readonly code?: string;\n\n constructor(message: string, statusCode?: number, code?: string) {\n super(message);\n this.statusCode = statusCode;\n this.code = code;\n this.name = 'SemaphoreError';\n // Required for proper instanceof checks with Error subclasses\n Object.setPrototypeOf(this, SemaphoreError.prototype);\n }\n}\n\n/**\n * Thrown when the API key is invalid or missing.\n */\nexport class AuthenticationError extends SemaphoreError {\n constructor(message: string = 'Invalid or missing API key') {\n super(message, 401, 'authentication_error');\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\n/**\n * Thrown when rate limits are exceeded.\n * Check `retryAfter` for seconds to wait before retrying.\n */\nexport class RateLimitError extends SemaphoreError {\n public readonly retryAfter?: number;\n\n constructor(\n message: string = 'Rate limit exceeded',\n retryAfter?: number\n ) {\n super(message, 429, 'rate_limit_error');\n this.retryAfter = retryAfter;\n this.name = 'RateLimitError';\n Object.setPrototypeOf(this, RateLimitError.prototype);\n }\n}\n\n/**\n * Thrown when request parameters are invalid.\n */\nexport class ValidationError extends SemaphoreError {\n public readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message, 400, 'validation_error');\n this.field = field;\n this.name = 'ValidationError';\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\n/**\n * Thrown when a network error occurs (connection failure, DNS resolution, etc.).\n * The `request` property contains context about the failed request.\n * The `cause` property contains the underlying error if available.\n */\nexport class NetworkError extends SemaphoreError {\n public readonly request: RequestContext;\n public readonly cause?: Error;\n\n constructor(message: string, request: RequestContext, cause?: Error) {\n super(message, undefined, 'network_error');\n this.request = request;\n this.cause = cause;\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n\n/**\n * Thrown when a request times out.\n * The `request` property contains context about the timed-out request.\n * The `timeoutMs` property indicates the timeout duration that was exceeded.\n */\nexport class TimeoutError extends SemaphoreError {\n public readonly request: RequestContext;\n public readonly timeoutMs: number;\n\n constructor(message: string, request: RequestContext, timeoutMs: number) {\n super(message, undefined, 'timeout_error');\n this.request = request;\n this.timeoutMs = timeoutMs;\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n","import type { RequestContext, HttpRequestOptions, RetryOptions } from '../types/http.js';\nimport {\n SemaphoreError,\n AuthenticationError,\n RateLimitError,\n ValidationError,\n NetworkError,\n TimeoutError,\n} from '../errors/index.js';\n\n/**\n * Configuration for HttpClient.\n */\nexport interface HttpClientConfig {\n baseUrl: string;\n apiKey: string;\n timeout: number;\n maxRetries?: number;\n onRetry?: (attempt: number, delayMs: number) => void;\n}\n\n/**\n * Parse Retry-After header value to milliseconds.\n * Supports both seconds format (\"120\") and HTTP-date format (\"Wed, 21 Oct 2015 07:28:00 GMT\").\n *\n * @param header - The Retry-After header value\n * @param defaultMs - Default delay in milliseconds when header is missing or invalid\n * @returns Delay in milliseconds\n */\nexport function parseRetryAfter(header: string | null, defaultMs: number = 1000): number {\n if (!header) {\n return defaultMs;\n }\n\n // Format 1: delay-seconds (e.g., \"120\")\n const seconds = parseFloat(header);\n if (!isNaN(seconds) && seconds >= 0) {\n return Math.round(seconds * 1000);\n }\n\n // Format 2: http-date (e.g., \"Wed, 21 Oct 2015 07:28:00 GMT\")\n const date = new Date(header);\n if (!isNaN(date.getTime())) {\n const delayMs = date.getTime() - Date.now();\n return Math.max(0, delayMs);\n }\n\n return defaultMs;\n}\n\n/**\n * Remove sensitive information from URL for error messages.\n * Removes apikey query parameter if present.\n *\n * @param url - The URL to sanitize\n * @returns URL with sensitive parameters removed\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n urlObj.searchParams.delete('apikey');\n return urlObj.toString();\n } catch {\n // If URL parsing fails, return original (it may be a relative path)\n return url;\n }\n}\n\n/**\n * HTTP client with timeout and retry support for the Semaphore API.\n *\n * Features:\n * - Configurable timeout using AbortSignal.timeout()\n * - Automatic retry on 429 (rate limit) responses with Retry-After header support\n * - Maps HTTP status codes to typed error classes\n * - Includes sanitized request context in errors for debugging\n */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n private readonly onRetry?: (attempt: number, delayMs: number) => void;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n this.maxRetries = config.maxRetries ?? 3;\n this.onRetry = config.onRetry;\n }\n\n /**\n * Map HTTP response to appropriate error class.\n *\n * @param response - The HTTP response\n * @param bodyText - Response body text (first 500 chars)\n * @returns Appropriate error instance\n */\n private mapResponseToError(\n response: Response,\n bodyText: string\n ): SemaphoreError {\n const status = response.status;\n const truncatedBody = bodyText.length > 500 ? bodyText.slice(0, 500) + '...' : bodyText;\n const message = `HTTP ${status}: ${truncatedBody || response.statusText}`;\n\n if (status === 401) {\n return new AuthenticationError(message);\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n const retryAfterSeconds = retryAfter ? parseRetryAfter(retryAfter) / 1000 : undefined;\n return new RateLimitError(message, retryAfterSeconds);\n }\n\n if (status >= 400 && status < 500) {\n return new ValidationError(message);\n }\n\n // 500+ server errors\n return new SemaphoreError(message, status);\n }\n\n /**\n * Make an HTTP request to the Semaphore API.\n *\n * @param path - API path (e.g., \"/messages\")\n * @param options - Request and retry options\n * @returns Parsed JSON response\n * @throws {NetworkError} On connection failures\n * @throws {TimeoutError} On request timeout\n * @throws {AuthenticationError} On 401 responses\n * @throws {RateLimitError} On 429 responses (after retries exhausted)\n * @throws {ValidationError} On 4xx responses\n * @throws {SemaphoreError} On 5xx responses\n */\n async request<T>(\n path: string,\n options: HttpRequestOptions & RetryOptions = {}\n ): Promise<T> {\n const {\n method = 'GET',\n body,\n timeout = this.timeout,\n headers = {},\n maxRetries = this.maxRetries,\n onRetry = this.onRetry,\n } = options;\n\n const url = `${this.baseUrl}${path}`;\n const sanitizedUrl = sanitizeUrl(url);\n const requestContext: RequestContext = {\n url: sanitizedUrl,\n method,\n };\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: AbortSignal.timeout(timeout),\n });\n\n if (!response.ok) {\n // Read response body for error message\n let bodyText = '';\n try {\n bodyText = await response.text();\n } catch {\n // Ignore body read errors\n }\n\n // Handle 429 rate limit with retry\n if (response.status === 429 && attempt < maxRetries) {\n const retryAfter = response.headers.get('Retry-After');\n const delayMs = parseRetryAfter(retryAfter);\n onRetry?.(attempt, delayMs);\n await new Promise(resolve => setTimeout(resolve, delayMs));\n continue;\n }\n\n // Throw mapped error for all other cases\n throw this.mapResponseToError(response, bodyText);\n }\n\n // Parse successful response\n try {\n return await response.json() as T;\n } catch (parseError) {\n throw new SemaphoreError(\n `Failed to parse response JSON: ${parseError instanceof Error ? parseError.message : 'Unknown error'}`,\n response.status\n );\n }\n\n } catch (error) {\n // Re-throw our own errors\n if (error instanceof SemaphoreError) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Handle timeout errors from AbortSignal.timeout()\n if (error.name === 'TimeoutError') {\n throw new TimeoutError(\n `Request timed out after ${timeout}ms`,\n requestContext,\n timeout\n );\n }\n\n // Handle network errors (connection refused, DNS failure, etc.)\n throw new NetworkError(\n `Network error: ${error.message}`,\n requestContext,\n error\n );\n }\n\n // Re-throw unknown errors\n throw error;\n }\n }\n\n // All retries exhausted on 429\n throw new RateLimitError('Rate limit exceeded after max retries');\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type {\n SendMessageRequest,\n SendMessageResponse,\n BulkSendMessageResponse,\n MessageListRequest,\n Message,\n} from '../types/index.js';\n\n/**\n * Resource class for SMS message operations.\n *\n * Provides methods for sending messages, listing sent messages,\n * and retrieving message details by ID.\n *\n * @example\n * ```typescript\n * const client = new SemaphoreClient({ apiKey: 'your-api-key' });\n *\n * // Send a single message\n * const response = await client.messages.send({\n * number: '09171234567',\n * message: 'Hello!',\n * sendername: 'SEMAPHORE',\n * });\n * ```\n */\nexport class MessagesResource {\n /**\n * Create a new MessagesResource instance.\n *\n * @param http - HttpClient instance for making API requests\n */\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Send an SMS message to one or more recipients.\n *\n * When sending to multiple recipients (up to 1000), pass an array of numbers.\n * The API will return an array of responses, one for each recipient.\n *\n * @param params - Message parameters including recipient(s), message content, and sender name\n * @returns Single response for one recipient, array of responses for multiple recipients\n *\n * @example\n * ```typescript\n * // Send to single recipient\n * const response = await client.messages.send({\n * number: '09171234567',\n * message: 'Hello!',\n * sendername: 'SEMAPHORE',\n * });\n * console.log(response.message_id);\n *\n * // Send to multiple recipients (bulk)\n * const responses = await client.messages.send({\n * number: ['09171234567', '09181234567'],\n * message: 'Hello everyone!',\n * sendername: 'SEMAPHORE',\n * });\n * console.log(responses.length); // 2\n * ```\n */\n async send(\n params: SendMessageRequest\n ): Promise<SendMessageResponse | BulkSendMessageResponse> {\n // Convert number array to comma-separated string for API\n const number = Array.isArray(params.number)\n ? params.number.join(',')\n : params.number;\n\n const body = {\n number,\n message: params.message,\n sendername: params.sendername,\n };\n\n return this.http.request<SendMessageResponse | BulkSendMessageResponse>(\n '/messages',\n {\n method: 'POST',\n body,\n }\n );\n }\n\n /**\n * List sent messages with optional filtering.\n *\n * Supports pagination and filtering by date range, network, status, and sender name.\n *\n * @param params - Optional filter parameters\n * @returns Array of message objects\n *\n * @example\n * ```typescript\n * // List all messages\n * const messages = await client.messages.list();\n *\n * // List with filters\n * const filtered = await client.messages.list({\n * page: 1,\n * limit: 50,\n * status: 'Sent',\n * startDate: '2024-01-01',\n * endDate: '2024-01-31',\n * });\n * ```\n */\n async list(params?: MessageListRequest): Promise<Message[]> {\n const queryString = this.buildQueryString(params);\n return this.http.request<Message[]>(`/messages${queryString}`, {\n method: 'GET',\n });\n }\n\n /**\n * Get a specific message by ID.\n *\n * @param id - The message ID to retrieve\n * @returns The message object\n *\n * @example\n * ```typescript\n * const message = await client.messages.get(12345);\n * console.log(message.status); // 'Sent'\n * console.log(message.recipient); // '09171234567'\n * ```\n */\n async get(id: number): Promise<Message> {\n return this.http.request<Message>(`/messages/${id}`, {\n method: 'GET',\n });\n }\n\n /**\n * Build query string from optional MessageListRequest parameters.\n *\n * @param params - Optional filter parameters\n * @returns Query string including leading '?' if params exist, empty string otherwise\n */\n private buildQueryString(params?: MessageListRequest): string {\n if (!params) {\n return '';\n }\n\n const searchParams = new URLSearchParams();\n\n if (params.page !== undefined) {\n searchParams.set('page', String(params.page));\n }\n if (params.limit !== undefined) {\n searchParams.set('limit', String(params.limit));\n }\n if (params.startDate !== undefined) {\n searchParams.set('startDate', params.startDate);\n }\n if (params.endDate !== undefined) {\n searchParams.set('endDate', params.endDate);\n }\n if (params.network !== undefined) {\n searchParams.set('network', params.network);\n }\n if (params.status !== undefined) {\n searchParams.set('status', params.status);\n }\n if (params.sendername !== undefined) {\n searchParams.set('sendername', params.sendername);\n }\n\n const queryString = searchParams.toString();\n return queryString ? `?${queryString}` : '';\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type { SendOtpRequest, SendOtpResponse } from '../types/index.js';\n\n/**\n * Resource for sending OTP (One-Time Password) messages.\n *\n * OTP messages use a priority route with no rate limit.\n * Each message costs 2 credits per 160 characters.\n */\nexport class OtpResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Send an OTP message to a recipient.\n *\n * Uses priority route - no rate limit, 2 credits per 160-char message.\n * The API generates the OTP code and replaces the {otp} placeholder in your message.\n *\n * @param params - OTP parameters including recipient, message template, sender name\n * @returns Response including the generated OTP code\n *\n * @example\n * ```typescript\n * const response = await client.otp.send({\n * number: '+639171234567',\n * message: 'Your verification code is {otp}',\n * sendername: 'MyApp',\n * });\n * console.log('OTP sent:', response.code);\n * ```\n *\n * @example\n * ```typescript\n * // With custom code length\n * const response = await client.otp.send({\n * number: '+639171234567',\n * message: 'Your code is {otp}',\n * sendername: 'MyApp',\n * code_length: 4,\n * });\n * ```\n */\n async send(params: SendOtpRequest): Promise<SendOtpResponse> {\n return this.http.request<SendOtpResponse>('/otp', {\n method: 'POST',\n body: params,\n });\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type {\n AccountInfo,\n Transaction,\n TransactionListRequest,\n SenderName,\n} from '../types/index.js';\n\n/**\n * Resource for retrieving account information.\n */\nexport class AccountResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Get account information including credit balance.\n *\n * @returns Account info with balance\n *\n * @example\n * ```typescript\n * const info = await client.account.info();\n * console.log('Account:', info.account_name);\n * console.log('Balance:', info.credit_balance);\n * ```\n */\n async info(): Promise<AccountInfo> {\n return this.http.request<AccountInfo>('/account');\n }\n\n /**\n * Get transaction history.\n *\n * @param params - Optional pagination and date filter parameters\n * @returns Array of transactions\n *\n * @example\n * ```typescript\n * // Get all transactions\n * const transactions = await client.account.transactions();\n * ```\n *\n * @example\n * ```typescript\n * // Get paginated transactions with date range\n * const transactions = await client.account.transactions({\n * page: 1,\n * limit: 50,\n * startDate: '2026-01-01',\n * endDate: '2026-01-31',\n * });\n * ```\n */\n async transactions(params?: TransactionListRequest): Promise<Transaction[]> {\n const query = this.buildQueryString(params);\n return this.http.request<Transaction[]>(`/account/transactions${query}`);\n }\n\n /**\n * Get list of approved sender names.\n *\n * @returns Array of sender names with status\n *\n * @example\n * ```typescript\n * const senderNames = await client.account.senderNames();\n * for (const sender of senderNames) {\n * console.log(`${sender.name}: ${sender.status}`);\n * }\n * ```\n */\n async senderNames(): Promise<SenderName[]> {\n return this.http.request<SenderName[]>('/account/sendernames');\n }\n\n /**\n * Build query string from optional transaction list parameters.\n *\n * @param params - Optional filter parameters\n * @returns Query string (empty string or ?param1=value1&param2=value2)\n */\n private buildQueryString(params?: TransactionListRequest): string {\n if (!params) return '';\n\n const searchParams = new URLSearchParams();\n\n if (params.page !== undefined) searchParams.set('page', String(params.page));\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.startDate) searchParams.set('startDate', params.startDate);\n if (params.endDate) searchParams.set('endDate', params.endDate);\n\n const str = searchParams.toString();\n return str ? `?${str}` : '';\n }\n}\n","import { AuthenticationError } from './errors/index.js';\nimport { HttpClient } from './http/index.js';\nimport { MessagesResource } from './resources/messages.js';\nimport { OtpResource } from './resources/otp.js';\nimport { AccountResource } from './resources/account.js';\nimport type { SemaphoreClientOptions } from './types/common.js';\n\n/**\n * Semaphore API client for sending SMS and OTP messages.\n *\n * @example\n * ```typescript\n * // Send SMS\n * const client = new SemaphoreClient({ apiKey: 'your-api-key' });\n * await client.messages.send({\n * number: '+639171234567',\n * message: 'Hello!',\n * sendername: 'MyApp',\n * });\n *\n * // Check balance\n * const info = await client.account.info();\n * console.log('Balance:', info.credit_balance);\n * ```\n */\nexport class SemaphoreClient {\n /** @internal HTTP client used by resource classes. */\n protected readonly http: HttpClient;\n\n /** SMS message operations */\n readonly messages: MessagesResource;\n\n /** OTP message operations (priority route, no rate limit) */\n readonly otp: OtpResource;\n\n /** Account information operations */\n readonly account: AccountResource;\n\n constructor(options: SemaphoreClientOptions = {}) {\n // Environment variable fallback (cross-runtime compatible)\n let apiKey = options.apiKey;\n if (!apiKey && typeof process !== 'undefined' && process.env) {\n apiKey = process.env.SEMAPHORE_API_KEY;\n }\n\n // Fail fast on missing API key (constructor-time validation)\n if (!apiKey) {\n throw new AuthenticationError(\n 'Missing API key. Pass it to the constructor `new SemaphoreClient({ apiKey: \"...\" })` ' +\n 'or set the SEMAPHORE_API_KEY environment variable.'\n );\n }\n\n const baseUrl = options.baseUrl ?? 'https://api.semaphore.co/api/v4';\n const timeout = options.timeout ?? 30000;\n\n this.http = new HttpClient({\n baseUrl,\n apiKey,\n timeout,\n onRetry: options.onRetry,\n });\n\n // Instantiate resource classes with HTTP client access\n this.messages = new MessagesResource(this.http);\n this.otp = new OtpResource(this.http);\n this.account = new AccountResource(this.http);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors/errors.ts","../src/http/client.ts","../src/resources/messages.ts","../src/resources/otp.ts","../src/resources/account.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { RequestContext } from '../types/http.js';\n\n/**\n * Base error class for all Semaphore API errors.\n * Extend this for specific error types.\n */\nexport class SemaphoreError extends Error {\n public readonly statusCode?: number;\n public readonly code?: string;\n\n constructor(message: string, statusCode?: number, code?: string) {\n super(message);\n this.statusCode = statusCode;\n this.code = code;\n this.name = 'SemaphoreError';\n // Required for proper instanceof checks with Error subclasses\n Object.setPrototypeOf(this, SemaphoreError.prototype);\n }\n}\n\n/**\n * Thrown when the API key is invalid or missing.\n */\nexport class AuthenticationError extends SemaphoreError {\n constructor(message: string = 'Invalid or missing API key') {\n super(message, 401, 'authentication_error');\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\n/**\n * Thrown when rate limits are exceeded.\n * Check `retryAfter` for seconds to wait before retrying.\n */\nexport class RateLimitError extends SemaphoreError {\n public readonly retryAfter?: number;\n\n constructor(\n message: string = 'Rate limit exceeded',\n retryAfter?: number\n ) {\n super(message, 429, 'rate_limit_error');\n this.retryAfter = retryAfter;\n this.name = 'RateLimitError';\n Object.setPrototypeOf(this, RateLimitError.prototype);\n }\n}\n\n/**\n * Thrown when request parameters are invalid.\n */\nexport class ValidationError extends SemaphoreError {\n public readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message, 400, 'validation_error');\n this.field = field;\n this.name = 'ValidationError';\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\n/**\n * Thrown when a network error occurs (connection failure, DNS resolution, etc.).\n * The `request` property contains context about the failed request.\n * The `cause` property contains the underlying error if available.\n */\nexport class NetworkError extends SemaphoreError {\n public readonly request: RequestContext;\n public readonly cause?: Error;\n\n constructor(message: string, request: RequestContext, cause?: Error) {\n super(message, undefined, 'network_error');\n this.request = request;\n this.cause = cause;\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n\n/**\n * Thrown when a request times out.\n * The `request` property contains context about the timed-out request.\n * The `timeoutMs` property indicates the timeout duration that was exceeded.\n */\nexport class TimeoutError extends SemaphoreError {\n public readonly request: RequestContext;\n public readonly timeoutMs: number;\n\n constructor(message: string, request: RequestContext, timeoutMs: number) {\n super(message, undefined, 'timeout_error');\n this.request = request;\n this.timeoutMs = timeoutMs;\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n","import type { RequestContext, HttpRequestOptions, RetryOptions } from '../types/http.js';\nimport {\n SemaphoreError,\n AuthenticationError,\n RateLimitError,\n ValidationError,\n NetworkError,\n TimeoutError,\n} from '../errors/index.js';\n\n/**\n * Configuration for HttpClient.\n */\nexport interface HttpClientConfig {\n baseUrl: string;\n apiKey: string;\n timeout: number;\n maxRetries?: number;\n onRetry?: (attempt: number, delayMs: number) => void;\n}\n\n/**\n * Parse Retry-After header value to milliseconds.\n * Supports both seconds format (\"120\") and HTTP-date format (\"Wed, 21 Oct 2015 07:28:00 GMT\").\n *\n * @param header - The Retry-After header value\n * @param defaultMs - Default delay in milliseconds when header is missing or invalid\n * @returns Delay in milliseconds\n */\nexport function parseRetryAfter(header: string | null, defaultMs: number = 1000): number {\n if (!header) {\n return defaultMs;\n }\n\n // Format 1: delay-seconds (e.g., \"120\")\n const seconds = parseFloat(header);\n if (!isNaN(seconds) && seconds >= 0) {\n return Math.round(seconds * 1000);\n }\n\n // Format 2: http-date (e.g., \"Wed, 21 Oct 2015 07:28:00 GMT\")\n const date = new Date(header);\n if (!isNaN(date.getTime())) {\n const delayMs = date.getTime() - Date.now();\n return Math.max(0, delayMs);\n }\n\n return defaultMs;\n}\n\n/**\n * Remove sensitive information from URL for error messages.\n * Removes apikey query parameter if present.\n *\n * @param url - The URL to sanitize\n * @returns URL with sensitive parameters removed\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n urlObj.searchParams.delete('apikey');\n return urlObj.toString();\n } catch {\n // If URL parsing fails, return original (it may be a relative path)\n return url;\n }\n}\n\n/**\n * HTTP client with timeout and retry support for the Semaphore API.\n *\n * Features:\n * - Configurable timeout using AbortSignal.timeout()\n * - Automatic retry on 429 (rate limit) responses with Retry-After header support\n * - Maps HTTP status codes to typed error classes\n * - Includes sanitized request context in errors for debugging\n */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n private readonly onRetry?: (attempt: number, delayMs: number) => void;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n this.maxRetries = config.maxRetries ?? 3;\n this.onRetry = config.onRetry;\n }\n\n /**\n * Map HTTP response to appropriate error class.\n *\n * @param response - The HTTP response\n * @param bodyText - Response body text (first 500 chars)\n * @returns Appropriate error instance\n */\n private mapResponseToError(\n response: Response,\n bodyText: string\n ): SemaphoreError {\n const status = response.status;\n const truncatedBody = bodyText.length > 500 ? bodyText.slice(0, 500) + '...' : bodyText;\n const message = `HTTP ${status}: ${truncatedBody || response.statusText}`;\n\n if (status === 401) {\n return new AuthenticationError(message);\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n const retryAfterSeconds = retryAfter ? parseRetryAfter(retryAfter) / 1000 : undefined;\n return new RateLimitError(message, retryAfterSeconds);\n }\n\n if (status >= 400 && status < 500) {\n return new ValidationError(message);\n }\n\n // 500+ server errors\n return new SemaphoreError(message, status);\n }\n\n /**\n * Make an HTTP request to the Semaphore API.\n *\n * @param path - API path (e.g., \"/messages\")\n * @param options - Request and retry options\n * @returns Parsed JSON response\n * @throws {NetworkError} On connection failures\n * @throws {TimeoutError} On request timeout\n * @throws {AuthenticationError} On 401 responses\n * @throws {RateLimitError} On 429 responses (after retries exhausted)\n * @throws {ValidationError} On 4xx responses\n * @throws {SemaphoreError} On 5xx responses\n */\n async request<T>(\n path: string,\n options: HttpRequestOptions & RetryOptions = {}\n ): Promise<T> {\n const {\n method = 'GET',\n body,\n timeout = this.timeout,\n headers = {},\n maxRetries = this.maxRetries,\n onRetry = this.onRetry,\n } = options;\n\n // Build URL with apikey for GET requests\n let url = `${this.baseUrl}${path}`;\n if (method === 'GET') {\n const urlObj = new URL(url);\n urlObj.searchParams.set('apikey', this.apiKey);\n url = urlObj.toString();\n }\n\n const sanitizedUrl = sanitizeUrl(url);\n const requestContext: RequestContext = {\n url: sanitizedUrl,\n method,\n };\n\n // Build form-encoded body for POST requests\n let requestBody: URLSearchParams | undefined;\n if (method === 'POST' && body) {\n requestBody = new URLSearchParams();\n requestBody.set('apikey', this.apiKey);\n for (const [key, value] of Object.entries(body as Record<string, unknown>)) {\n if (value !== undefined && value !== null) {\n requestBody.set(key, String(value));\n }\n }\n }\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n method,\n headers: {\n ...(method === 'POST' ? { 'Content-Type': 'application/x-www-form-urlencoded' } : {}),\n ...headers,\n },\n body: requestBody,\n signal: AbortSignal.timeout(timeout),\n });\n\n if (!response.ok) {\n // Read response body for error message\n let bodyText = '';\n try {\n bodyText = await response.text();\n } catch {\n // Ignore body read errors\n }\n\n // Handle 429 rate limit with retry\n if (response.status === 429 && attempt < maxRetries) {\n const retryAfter = response.headers.get('Retry-After');\n const delayMs = parseRetryAfter(retryAfter);\n onRetry?.(attempt, delayMs);\n await new Promise(resolve => setTimeout(resolve, delayMs));\n continue;\n }\n\n // Throw mapped error for all other cases\n throw this.mapResponseToError(response, bodyText);\n }\n\n // Parse successful response\n try {\n return await response.json() as T;\n } catch (parseError) {\n throw new SemaphoreError(\n `Failed to parse response JSON: ${parseError instanceof Error ? parseError.message : 'Unknown error'}`,\n response.status\n );\n }\n\n } catch (error) {\n // Re-throw our own errors\n if (error instanceof SemaphoreError) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Handle timeout errors from AbortSignal.timeout()\n if (error.name === 'TimeoutError') {\n throw new TimeoutError(\n `Request timed out after ${timeout}ms`,\n requestContext,\n timeout\n );\n }\n\n // Handle network errors (connection refused, DNS failure, etc.)\n throw new NetworkError(\n `Network error: ${error.message}`,\n requestContext,\n error\n );\n }\n\n // Re-throw unknown errors\n throw error;\n }\n }\n\n // All retries exhausted on 429\n throw new RateLimitError('Rate limit exceeded after max retries');\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type {\n SendMessageRequest,\n SendMessageResponse,\n BulkSendMessageResponse,\n MessageListRequest,\n Message,\n} from '../types/index.js';\n\n/**\n * Resource class for SMS message operations.\n *\n * Provides methods for sending messages, listing sent messages,\n * and retrieving message details by ID.\n *\n * @example\n * ```typescript\n * const client = new SemaphoreClient({ apiKey: 'your-api-key' });\n *\n * // Send a single message\n * const response = await client.messages.send({\n * number: '09171234567',\n * message: 'Hello!',\n * sendername: 'SEMAPHORE',\n * });\n * ```\n */\nexport class MessagesResource {\n /**\n * Create a new MessagesResource instance.\n *\n * @param http - HttpClient instance for making API requests\n */\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Send an SMS message to one or more recipients.\n *\n * When sending to multiple recipients (up to 1000), pass an array of numbers.\n * The API will return an array of responses, one for each recipient.\n *\n * @param params - Message parameters including recipient(s), message content, and sender name\n * @returns Single response for one recipient, array of responses for multiple recipients\n *\n * @example\n * ```typescript\n * // Send to single recipient\n * const response = await client.messages.send({\n * number: '09171234567',\n * message: 'Hello!',\n * sendername: 'SEMAPHORE',\n * });\n * console.log(response.message_id);\n *\n * // Send to multiple recipients (bulk)\n * const responses = await client.messages.send({\n * number: ['09171234567', '09181234567'],\n * message: 'Hello everyone!',\n * sendername: 'SEMAPHORE',\n * });\n * console.log(responses.length); // 2\n * ```\n */\n async send(\n params: SendMessageRequest\n ): Promise<SendMessageResponse | BulkSendMessageResponse> {\n // Convert number array to comma-separated string for API\n const number = Array.isArray(params.number)\n ? params.number.join(',')\n : params.number;\n\n const body = {\n number,\n message: params.message,\n sendername: params.sendername,\n };\n\n return this.http.request<SendMessageResponse | BulkSendMessageResponse>(\n '/messages',\n {\n method: 'POST',\n body,\n }\n );\n }\n\n /**\n * List sent messages with optional filtering.\n *\n * Supports pagination and filtering by date range, network, status, and sender name.\n *\n * @param params - Optional filter parameters\n * @returns Array of message objects\n *\n * @example\n * ```typescript\n * // List all messages\n * const messages = await client.messages.list();\n *\n * // List with filters\n * const filtered = await client.messages.list({\n * page: 1,\n * limit: 50,\n * status: 'Sent',\n * startDate: '2024-01-01',\n * endDate: '2024-01-31',\n * });\n * ```\n */\n async list(params?: MessageListRequest): Promise<Message[]> {\n const queryString = this.buildQueryString(params);\n return this.http.request<Message[]>(`/messages${queryString}`, {\n method: 'GET',\n });\n }\n\n /**\n * Get a specific message by ID.\n *\n * @param id - The message ID to retrieve\n * @returns The message object\n *\n * @example\n * ```typescript\n * const message = await client.messages.get(12345);\n * console.log(message.status); // 'Sent'\n * console.log(message.recipient); // '09171234567'\n * ```\n */\n async get(id: number): Promise<Message> {\n return this.http.request<Message>(`/messages/${id}`, {\n method: 'GET',\n });\n }\n\n /**\n * Build query string from optional MessageListRequest parameters.\n *\n * @param params - Optional filter parameters\n * @returns Query string including leading '?' if params exist, empty string otherwise\n */\n private buildQueryString(params?: MessageListRequest): string {\n if (!params) {\n return '';\n }\n\n const searchParams = new URLSearchParams();\n\n if (params.page !== undefined) {\n searchParams.set('page', String(params.page));\n }\n if (params.limit !== undefined) {\n searchParams.set('limit', String(params.limit));\n }\n if (params.startDate !== undefined) {\n searchParams.set('startDate', params.startDate);\n }\n if (params.endDate !== undefined) {\n searchParams.set('endDate', params.endDate);\n }\n if (params.network !== undefined) {\n searchParams.set('network', params.network);\n }\n if (params.status !== undefined) {\n searchParams.set('status', params.status);\n }\n if (params.sendername !== undefined) {\n searchParams.set('sendername', params.sendername);\n }\n\n const queryString = searchParams.toString();\n return queryString ? `?${queryString}` : '';\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type { SendOtpRequest, SendOtpResponse } from '../types/index.js';\n\n/**\n * Resource for sending OTP (One-Time Password) messages.\n *\n * OTP messages use a priority route with no rate limit.\n * Each message costs 2 credits per 160 characters.\n */\nexport class OtpResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Send an OTP message to a recipient.\n *\n * Uses priority route - no rate limit, 2 credits per 160-char message.\n * The API generates the OTP code and replaces the {otp} placeholder in your message.\n *\n * @param params - OTP parameters including recipient, message template, sender name\n * @returns Response including the generated OTP code\n *\n * @example\n * ```typescript\n * const response = await client.otp.send({\n * number: '+639171234567',\n * message: 'Your verification code is {otp}',\n * sendername: 'MyApp',\n * });\n * console.log('OTP sent:', response.code);\n * ```\n *\n * @example\n * ```typescript\n * // With custom code length\n * const response = await client.otp.send({\n * number: '+639171234567',\n * message: 'Your code is {otp}',\n * sendername: 'MyApp',\n * code_length: 4,\n * });\n * ```\n */\n async send(params: SendOtpRequest): Promise<SendOtpResponse> {\n return this.http.request<SendOtpResponse>('/otp', {\n method: 'POST',\n body: params,\n });\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type {\n AccountInfo,\n Transaction,\n TransactionListRequest,\n SenderName,\n} from '../types/index.js';\n\n/**\n * Resource for retrieving account information.\n */\nexport class AccountResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Get account information including credit balance.\n *\n * @returns Account info with balance\n *\n * @example\n * ```typescript\n * const info = await client.account.info();\n * console.log('Account:', info.account_name);\n * console.log('Balance:', info.credit_balance);\n * ```\n */\n async info(): Promise<AccountInfo> {\n return this.http.request<AccountInfo>('/account');\n }\n\n /**\n * Get transaction history.\n *\n * @param params - Optional pagination and date filter parameters\n * @returns Array of transactions\n *\n * @example\n * ```typescript\n * // Get all transactions\n * const transactions = await client.account.transactions();\n * ```\n *\n * @example\n * ```typescript\n * // Get paginated transactions with date range\n * const transactions = await client.account.transactions({\n * page: 1,\n * limit: 50,\n * startDate: '2026-01-01',\n * endDate: '2026-01-31',\n * });\n * ```\n */\n async transactions(params?: TransactionListRequest): Promise<Transaction[]> {\n const query = this.buildQueryString(params);\n return this.http.request<Transaction[]>(`/account/transactions${query}`);\n }\n\n /**\n * Get list of approved sender names.\n *\n * @returns Array of sender names with status\n *\n * @example\n * ```typescript\n * const senderNames = await client.account.senderNames();\n * for (const sender of senderNames) {\n * console.log(`${sender.name}: ${sender.status}`);\n * }\n * ```\n */\n async senderNames(): Promise<SenderName[]> {\n return this.http.request<SenderName[]>('/account/sendernames');\n }\n\n /**\n * Build query string from optional transaction list parameters.\n *\n * @param params - Optional filter parameters\n * @returns Query string (empty string or ?param1=value1&param2=value2)\n */\n private buildQueryString(params?: TransactionListRequest): string {\n if (!params) return '';\n\n const searchParams = new URLSearchParams();\n\n if (params.page !== undefined) searchParams.set('page', String(params.page));\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.startDate) searchParams.set('startDate', params.startDate);\n if (params.endDate) searchParams.set('endDate', params.endDate);\n\n const str = searchParams.toString();\n return str ? `?${str}` : '';\n }\n}\n","import { AuthenticationError } from './errors/index.js';\nimport { HttpClient } from './http/index.js';\nimport { MessagesResource } from './resources/messages.js';\nimport { OtpResource } from './resources/otp.js';\nimport { AccountResource } from './resources/account.js';\nimport type { SemaphoreClientOptions } from './types/common.js';\n\n/**\n * Semaphore API client for sending SMS and OTP messages.\n *\n * @example\n * ```typescript\n * // Send SMS\n * const client = new SemaphoreClient({ apiKey: 'your-api-key' });\n * await client.messages.send({\n * number: '+639171234567',\n * message: 'Hello!',\n * sendername: 'MyApp',\n * });\n *\n * // Check balance\n * const info = await client.account.info();\n * console.log('Balance:', info.credit_balance);\n * ```\n */\nexport class SemaphoreClient {\n /** @internal HTTP client used by resource classes. */\n protected readonly http: HttpClient;\n\n /** SMS message operations */\n readonly messages: MessagesResource;\n\n /** OTP message operations (priority route, no rate limit) */\n readonly otp: OtpResource;\n\n /** Account information operations */\n readonly account: AccountResource;\n\n constructor(options: SemaphoreClientOptions = {}) {\n // Environment variable fallback (cross-runtime compatible)\n let apiKey = options.apiKey;\n if (!apiKey && typeof process !== 'undefined' && process.env) {\n apiKey = process.env.SEMAPHORE_API_KEY;\n }\n\n // Fail fast on missing API key (constructor-time validation)\n if (!apiKey) {\n throw new AuthenticationError(\n 'Missing API key. Pass it to the constructor `new SemaphoreClient({ apiKey: \"...\" })` ' +\n 'or set the SEMAPHORE_API_KEY environment variable.'\n );\n }\n\n const baseUrl = options.baseUrl ?? 'https://api.semaphore.co/api/v4';\n const timeout = options.timeout ?? 30000;\n\n this.http = new HttpClient({\n baseUrl,\n apiKey,\n timeout,\n onRetry: options.onRetry,\n });\n\n // Instantiate resource classes with HTTP client access\n this.messages = new MessagesResource(this.http);\n this.otp = new OtpResource(this.http);\n this.account = new AccountResource(this.http);\n }\n}\n"]}
package/dist/index.js CHANGED
@@ -142,22 +142,36 @@ var HttpClient = class {
142
142
  maxRetries = this.maxRetries,
143
143
  onRetry = this.onRetry
144
144
  } = options;
145
- const url = `${this.baseUrl}${path}`;
145
+ let url = `${this.baseUrl}${path}`;
146
+ if (method === "GET") {
147
+ const urlObj = new URL(url);
148
+ urlObj.searchParams.set("apikey", this.apiKey);
149
+ url = urlObj.toString();
150
+ }
146
151
  const sanitizedUrl = sanitizeUrl(url);
147
152
  const requestContext = {
148
153
  url: sanitizedUrl,
149
154
  method
150
155
  };
156
+ let requestBody;
157
+ if (method === "POST" && body) {
158
+ requestBody = new URLSearchParams();
159
+ requestBody.set("apikey", this.apiKey);
160
+ for (const [key, value] of Object.entries(body)) {
161
+ if (value !== void 0 && value !== null) {
162
+ requestBody.set(key, String(value));
163
+ }
164
+ }
165
+ }
151
166
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
152
167
  try {
153
168
  const response = await fetch(url, {
154
169
  method,
155
170
  headers: {
156
- "Content-Type": "application/json",
157
- "Authorization": `Bearer ${this.apiKey}`,
171
+ ...method === "POST" ? { "Content-Type": "application/x-www-form-urlencoded" } : {},
158
172
  ...headers
159
173
  },
160
- body: body ? JSON.stringify(body) : void 0,
174
+ body: requestBody,
161
175
  signal: AbortSignal.timeout(timeout)
162
176
  });
163
177
  if (!response.ok) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/errors.ts","../src/http/client.ts","../src/resources/messages.ts","../src/resources/otp.ts","../src/resources/account.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { RequestContext } from '../types/http.js';\n\n/**\n * Base error class for all Semaphore API errors.\n * Extend this for specific error types.\n */\nexport class SemaphoreError extends Error {\n public readonly statusCode?: number;\n public readonly code?: string;\n\n constructor(message: string, statusCode?: number, code?: string) {\n super(message);\n this.statusCode = statusCode;\n this.code = code;\n this.name = 'SemaphoreError';\n // Required for proper instanceof checks with Error subclasses\n Object.setPrototypeOf(this, SemaphoreError.prototype);\n }\n}\n\n/**\n * Thrown when the API key is invalid or missing.\n */\nexport class AuthenticationError extends SemaphoreError {\n constructor(message: string = 'Invalid or missing API key') {\n super(message, 401, 'authentication_error');\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\n/**\n * Thrown when rate limits are exceeded.\n * Check `retryAfter` for seconds to wait before retrying.\n */\nexport class RateLimitError extends SemaphoreError {\n public readonly retryAfter?: number;\n\n constructor(\n message: string = 'Rate limit exceeded',\n retryAfter?: number\n ) {\n super(message, 429, 'rate_limit_error');\n this.retryAfter = retryAfter;\n this.name = 'RateLimitError';\n Object.setPrototypeOf(this, RateLimitError.prototype);\n }\n}\n\n/**\n * Thrown when request parameters are invalid.\n */\nexport class ValidationError extends SemaphoreError {\n public readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message, 400, 'validation_error');\n this.field = field;\n this.name = 'ValidationError';\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\n/**\n * Thrown when a network error occurs (connection failure, DNS resolution, etc.).\n * The `request` property contains context about the failed request.\n * The `cause` property contains the underlying error if available.\n */\nexport class NetworkError extends SemaphoreError {\n public readonly request: RequestContext;\n public readonly cause?: Error;\n\n constructor(message: string, request: RequestContext, cause?: Error) {\n super(message, undefined, 'network_error');\n this.request = request;\n this.cause = cause;\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n\n/**\n * Thrown when a request times out.\n * The `request` property contains context about the timed-out request.\n * The `timeoutMs` property indicates the timeout duration that was exceeded.\n */\nexport class TimeoutError extends SemaphoreError {\n public readonly request: RequestContext;\n public readonly timeoutMs: number;\n\n constructor(message: string, request: RequestContext, timeoutMs: number) {\n super(message, undefined, 'timeout_error');\n this.request = request;\n this.timeoutMs = timeoutMs;\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n","import type { RequestContext, HttpRequestOptions, RetryOptions } from '../types/http.js';\nimport {\n SemaphoreError,\n AuthenticationError,\n RateLimitError,\n ValidationError,\n NetworkError,\n TimeoutError,\n} from '../errors/index.js';\n\n/**\n * Configuration for HttpClient.\n */\nexport interface HttpClientConfig {\n baseUrl: string;\n apiKey: string;\n timeout: number;\n maxRetries?: number;\n onRetry?: (attempt: number, delayMs: number) => void;\n}\n\n/**\n * Parse Retry-After header value to milliseconds.\n * Supports both seconds format (\"120\") and HTTP-date format (\"Wed, 21 Oct 2015 07:28:00 GMT\").\n *\n * @param header - The Retry-After header value\n * @param defaultMs - Default delay in milliseconds when header is missing or invalid\n * @returns Delay in milliseconds\n */\nexport function parseRetryAfter(header: string | null, defaultMs: number = 1000): number {\n if (!header) {\n return defaultMs;\n }\n\n // Format 1: delay-seconds (e.g., \"120\")\n const seconds = parseFloat(header);\n if (!isNaN(seconds) && seconds >= 0) {\n return Math.round(seconds * 1000);\n }\n\n // Format 2: http-date (e.g., \"Wed, 21 Oct 2015 07:28:00 GMT\")\n const date = new Date(header);\n if (!isNaN(date.getTime())) {\n const delayMs = date.getTime() - Date.now();\n return Math.max(0, delayMs);\n }\n\n return defaultMs;\n}\n\n/**\n * Remove sensitive information from URL for error messages.\n * Removes apikey query parameter if present.\n *\n * @param url - The URL to sanitize\n * @returns URL with sensitive parameters removed\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n urlObj.searchParams.delete('apikey');\n return urlObj.toString();\n } catch {\n // If URL parsing fails, return original (it may be a relative path)\n return url;\n }\n}\n\n/**\n * HTTP client with timeout and retry support for the Semaphore API.\n *\n * Features:\n * - Configurable timeout using AbortSignal.timeout()\n * - Automatic retry on 429 (rate limit) responses with Retry-After header support\n * - Maps HTTP status codes to typed error classes\n * - Includes sanitized request context in errors for debugging\n */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n private readonly onRetry?: (attempt: number, delayMs: number) => void;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n this.maxRetries = config.maxRetries ?? 3;\n this.onRetry = config.onRetry;\n }\n\n /**\n * Map HTTP response to appropriate error class.\n *\n * @param response - The HTTP response\n * @param bodyText - Response body text (first 500 chars)\n * @returns Appropriate error instance\n */\n private mapResponseToError(\n response: Response,\n bodyText: string\n ): SemaphoreError {\n const status = response.status;\n const truncatedBody = bodyText.length > 500 ? bodyText.slice(0, 500) + '...' : bodyText;\n const message = `HTTP ${status}: ${truncatedBody || response.statusText}`;\n\n if (status === 401) {\n return new AuthenticationError(message);\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n const retryAfterSeconds = retryAfter ? parseRetryAfter(retryAfter) / 1000 : undefined;\n return new RateLimitError(message, retryAfterSeconds);\n }\n\n if (status >= 400 && status < 500) {\n return new ValidationError(message);\n }\n\n // 500+ server errors\n return new SemaphoreError(message, status);\n }\n\n /**\n * Make an HTTP request to the Semaphore API.\n *\n * @param path - API path (e.g., \"/messages\")\n * @param options - Request and retry options\n * @returns Parsed JSON response\n * @throws {NetworkError} On connection failures\n * @throws {TimeoutError} On request timeout\n * @throws {AuthenticationError} On 401 responses\n * @throws {RateLimitError} On 429 responses (after retries exhausted)\n * @throws {ValidationError} On 4xx responses\n * @throws {SemaphoreError} On 5xx responses\n */\n async request<T>(\n path: string,\n options: HttpRequestOptions & RetryOptions = {}\n ): Promise<T> {\n const {\n method = 'GET',\n body,\n timeout = this.timeout,\n headers = {},\n maxRetries = this.maxRetries,\n onRetry = this.onRetry,\n } = options;\n\n const url = `${this.baseUrl}${path}`;\n const sanitizedUrl = sanitizeUrl(url);\n const requestContext: RequestContext = {\n url: sanitizedUrl,\n method,\n };\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: AbortSignal.timeout(timeout),\n });\n\n if (!response.ok) {\n // Read response body for error message\n let bodyText = '';\n try {\n bodyText = await response.text();\n } catch {\n // Ignore body read errors\n }\n\n // Handle 429 rate limit with retry\n if (response.status === 429 && attempt < maxRetries) {\n const retryAfter = response.headers.get('Retry-After');\n const delayMs = parseRetryAfter(retryAfter);\n onRetry?.(attempt, delayMs);\n await new Promise(resolve => setTimeout(resolve, delayMs));\n continue;\n }\n\n // Throw mapped error for all other cases\n throw this.mapResponseToError(response, bodyText);\n }\n\n // Parse successful response\n try {\n return await response.json() as T;\n } catch (parseError) {\n throw new SemaphoreError(\n `Failed to parse response JSON: ${parseError instanceof Error ? parseError.message : 'Unknown error'}`,\n response.status\n );\n }\n\n } catch (error) {\n // Re-throw our own errors\n if (error instanceof SemaphoreError) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Handle timeout errors from AbortSignal.timeout()\n if (error.name === 'TimeoutError') {\n throw new TimeoutError(\n `Request timed out after ${timeout}ms`,\n requestContext,\n timeout\n );\n }\n\n // Handle network errors (connection refused, DNS failure, etc.)\n throw new NetworkError(\n `Network error: ${error.message}`,\n requestContext,\n error\n );\n }\n\n // Re-throw unknown errors\n throw error;\n }\n }\n\n // All retries exhausted on 429\n throw new RateLimitError('Rate limit exceeded after max retries');\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type {\n SendMessageRequest,\n SendMessageResponse,\n BulkSendMessageResponse,\n MessageListRequest,\n Message,\n} from '../types/index.js';\n\n/**\n * Resource class for SMS message operations.\n *\n * Provides methods for sending messages, listing sent messages,\n * and retrieving message details by ID.\n *\n * @example\n * ```typescript\n * const client = new SemaphoreClient({ apiKey: 'your-api-key' });\n *\n * // Send a single message\n * const response = await client.messages.send({\n * number: '09171234567',\n * message: 'Hello!',\n * sendername: 'SEMAPHORE',\n * });\n * ```\n */\nexport class MessagesResource {\n /**\n * Create a new MessagesResource instance.\n *\n * @param http - HttpClient instance for making API requests\n */\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Send an SMS message to one or more recipients.\n *\n * When sending to multiple recipients (up to 1000), pass an array of numbers.\n * The API will return an array of responses, one for each recipient.\n *\n * @param params - Message parameters including recipient(s), message content, and sender name\n * @returns Single response for one recipient, array of responses for multiple recipients\n *\n * @example\n * ```typescript\n * // Send to single recipient\n * const response = await client.messages.send({\n * number: '09171234567',\n * message: 'Hello!',\n * sendername: 'SEMAPHORE',\n * });\n * console.log(response.message_id);\n *\n * // Send to multiple recipients (bulk)\n * const responses = await client.messages.send({\n * number: ['09171234567', '09181234567'],\n * message: 'Hello everyone!',\n * sendername: 'SEMAPHORE',\n * });\n * console.log(responses.length); // 2\n * ```\n */\n async send(\n params: SendMessageRequest\n ): Promise<SendMessageResponse | BulkSendMessageResponse> {\n // Convert number array to comma-separated string for API\n const number = Array.isArray(params.number)\n ? params.number.join(',')\n : params.number;\n\n const body = {\n number,\n message: params.message,\n sendername: params.sendername,\n };\n\n return this.http.request<SendMessageResponse | BulkSendMessageResponse>(\n '/messages',\n {\n method: 'POST',\n body,\n }\n );\n }\n\n /**\n * List sent messages with optional filtering.\n *\n * Supports pagination and filtering by date range, network, status, and sender name.\n *\n * @param params - Optional filter parameters\n * @returns Array of message objects\n *\n * @example\n * ```typescript\n * // List all messages\n * const messages = await client.messages.list();\n *\n * // List with filters\n * const filtered = await client.messages.list({\n * page: 1,\n * limit: 50,\n * status: 'Sent',\n * startDate: '2024-01-01',\n * endDate: '2024-01-31',\n * });\n * ```\n */\n async list(params?: MessageListRequest): Promise<Message[]> {\n const queryString = this.buildQueryString(params);\n return this.http.request<Message[]>(`/messages${queryString}`, {\n method: 'GET',\n });\n }\n\n /**\n * Get a specific message by ID.\n *\n * @param id - The message ID to retrieve\n * @returns The message object\n *\n * @example\n * ```typescript\n * const message = await client.messages.get(12345);\n * console.log(message.status); // 'Sent'\n * console.log(message.recipient); // '09171234567'\n * ```\n */\n async get(id: number): Promise<Message> {\n return this.http.request<Message>(`/messages/${id}`, {\n method: 'GET',\n });\n }\n\n /**\n * Build query string from optional MessageListRequest parameters.\n *\n * @param params - Optional filter parameters\n * @returns Query string including leading '?' if params exist, empty string otherwise\n */\n private buildQueryString(params?: MessageListRequest): string {\n if (!params) {\n return '';\n }\n\n const searchParams = new URLSearchParams();\n\n if (params.page !== undefined) {\n searchParams.set('page', String(params.page));\n }\n if (params.limit !== undefined) {\n searchParams.set('limit', String(params.limit));\n }\n if (params.startDate !== undefined) {\n searchParams.set('startDate', params.startDate);\n }\n if (params.endDate !== undefined) {\n searchParams.set('endDate', params.endDate);\n }\n if (params.network !== undefined) {\n searchParams.set('network', params.network);\n }\n if (params.status !== undefined) {\n searchParams.set('status', params.status);\n }\n if (params.sendername !== undefined) {\n searchParams.set('sendername', params.sendername);\n }\n\n const queryString = searchParams.toString();\n return queryString ? `?${queryString}` : '';\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type { SendOtpRequest, SendOtpResponse } from '../types/index.js';\n\n/**\n * Resource for sending OTP (One-Time Password) messages.\n *\n * OTP messages use a priority route with no rate limit.\n * Each message costs 2 credits per 160 characters.\n */\nexport class OtpResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Send an OTP message to a recipient.\n *\n * Uses priority route - no rate limit, 2 credits per 160-char message.\n * The API generates the OTP code and replaces the {otp} placeholder in your message.\n *\n * @param params - OTP parameters including recipient, message template, sender name\n * @returns Response including the generated OTP code\n *\n * @example\n * ```typescript\n * const response = await client.otp.send({\n * number: '+639171234567',\n * message: 'Your verification code is {otp}',\n * sendername: 'MyApp',\n * });\n * console.log('OTP sent:', response.code);\n * ```\n *\n * @example\n * ```typescript\n * // With custom code length\n * const response = await client.otp.send({\n * number: '+639171234567',\n * message: 'Your code is {otp}',\n * sendername: 'MyApp',\n * code_length: 4,\n * });\n * ```\n */\n async send(params: SendOtpRequest): Promise<SendOtpResponse> {\n return this.http.request<SendOtpResponse>('/otp', {\n method: 'POST',\n body: params,\n });\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type {\n AccountInfo,\n Transaction,\n TransactionListRequest,\n SenderName,\n} from '../types/index.js';\n\n/**\n * Resource for retrieving account information.\n */\nexport class AccountResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Get account information including credit balance.\n *\n * @returns Account info with balance\n *\n * @example\n * ```typescript\n * const info = await client.account.info();\n * console.log('Account:', info.account_name);\n * console.log('Balance:', info.credit_balance);\n * ```\n */\n async info(): Promise<AccountInfo> {\n return this.http.request<AccountInfo>('/account');\n }\n\n /**\n * Get transaction history.\n *\n * @param params - Optional pagination and date filter parameters\n * @returns Array of transactions\n *\n * @example\n * ```typescript\n * // Get all transactions\n * const transactions = await client.account.transactions();\n * ```\n *\n * @example\n * ```typescript\n * // Get paginated transactions with date range\n * const transactions = await client.account.transactions({\n * page: 1,\n * limit: 50,\n * startDate: '2026-01-01',\n * endDate: '2026-01-31',\n * });\n * ```\n */\n async transactions(params?: TransactionListRequest): Promise<Transaction[]> {\n const query = this.buildQueryString(params);\n return this.http.request<Transaction[]>(`/account/transactions${query}`);\n }\n\n /**\n * Get list of approved sender names.\n *\n * @returns Array of sender names with status\n *\n * @example\n * ```typescript\n * const senderNames = await client.account.senderNames();\n * for (const sender of senderNames) {\n * console.log(`${sender.name}: ${sender.status}`);\n * }\n * ```\n */\n async senderNames(): Promise<SenderName[]> {\n return this.http.request<SenderName[]>('/account/sendernames');\n }\n\n /**\n * Build query string from optional transaction list parameters.\n *\n * @param params - Optional filter parameters\n * @returns Query string (empty string or ?param1=value1&param2=value2)\n */\n private buildQueryString(params?: TransactionListRequest): string {\n if (!params) return '';\n\n const searchParams = new URLSearchParams();\n\n if (params.page !== undefined) searchParams.set('page', String(params.page));\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.startDate) searchParams.set('startDate', params.startDate);\n if (params.endDate) searchParams.set('endDate', params.endDate);\n\n const str = searchParams.toString();\n return str ? `?${str}` : '';\n }\n}\n","import { AuthenticationError } from './errors/index.js';\nimport { HttpClient } from './http/index.js';\nimport { MessagesResource } from './resources/messages.js';\nimport { OtpResource } from './resources/otp.js';\nimport { AccountResource } from './resources/account.js';\nimport type { SemaphoreClientOptions } from './types/common.js';\n\n/**\n * Semaphore API client for sending SMS and OTP messages.\n *\n * @example\n * ```typescript\n * // Send SMS\n * const client = new SemaphoreClient({ apiKey: 'your-api-key' });\n * await client.messages.send({\n * number: '+639171234567',\n * message: 'Hello!',\n * sendername: 'MyApp',\n * });\n *\n * // Check balance\n * const info = await client.account.info();\n * console.log('Balance:', info.credit_balance);\n * ```\n */\nexport class SemaphoreClient {\n /** @internal HTTP client used by resource classes. */\n protected readonly http: HttpClient;\n\n /** SMS message operations */\n readonly messages: MessagesResource;\n\n /** OTP message operations (priority route, no rate limit) */\n readonly otp: OtpResource;\n\n /** Account information operations */\n readonly account: AccountResource;\n\n constructor(options: SemaphoreClientOptions = {}) {\n // Environment variable fallback (cross-runtime compatible)\n let apiKey = options.apiKey;\n if (!apiKey && typeof process !== 'undefined' && process.env) {\n apiKey = process.env.SEMAPHORE_API_KEY;\n }\n\n // Fail fast on missing API key (constructor-time validation)\n if (!apiKey) {\n throw new AuthenticationError(\n 'Missing API key. Pass it to the constructor `new SemaphoreClient({ apiKey: \"...\" })` ' +\n 'or set the SEMAPHORE_API_KEY environment variable.'\n );\n }\n\n const baseUrl = options.baseUrl ?? 'https://api.semaphore.co/api/v4';\n const timeout = options.timeout ?? 30000;\n\n this.http = new HttpClient({\n baseUrl,\n apiKey,\n timeout,\n onRetry: options.onRetry,\n });\n\n // Instantiate resource classes with HTTP client access\n this.messages = new MessagesResource(this.http);\n this.otp = new OtpResource(this.http);\n this.account = new AccountResource(this.http);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors/errors.ts","../src/http/client.ts","../src/resources/messages.ts","../src/resources/otp.ts","../src/resources/account.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { RequestContext } from '../types/http.js';\n\n/**\n * Base error class for all Semaphore API errors.\n * Extend this for specific error types.\n */\nexport class SemaphoreError extends Error {\n public readonly statusCode?: number;\n public readonly code?: string;\n\n constructor(message: string, statusCode?: number, code?: string) {\n super(message);\n this.statusCode = statusCode;\n this.code = code;\n this.name = 'SemaphoreError';\n // Required for proper instanceof checks with Error subclasses\n Object.setPrototypeOf(this, SemaphoreError.prototype);\n }\n}\n\n/**\n * Thrown when the API key is invalid or missing.\n */\nexport class AuthenticationError extends SemaphoreError {\n constructor(message: string = 'Invalid or missing API key') {\n super(message, 401, 'authentication_error');\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\n/**\n * Thrown when rate limits are exceeded.\n * Check `retryAfter` for seconds to wait before retrying.\n */\nexport class RateLimitError extends SemaphoreError {\n public readonly retryAfter?: number;\n\n constructor(\n message: string = 'Rate limit exceeded',\n retryAfter?: number\n ) {\n super(message, 429, 'rate_limit_error');\n this.retryAfter = retryAfter;\n this.name = 'RateLimitError';\n Object.setPrototypeOf(this, RateLimitError.prototype);\n }\n}\n\n/**\n * Thrown when request parameters are invalid.\n */\nexport class ValidationError extends SemaphoreError {\n public readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message, 400, 'validation_error');\n this.field = field;\n this.name = 'ValidationError';\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\n/**\n * Thrown when a network error occurs (connection failure, DNS resolution, etc.).\n * The `request` property contains context about the failed request.\n * The `cause` property contains the underlying error if available.\n */\nexport class NetworkError extends SemaphoreError {\n public readonly request: RequestContext;\n public readonly cause?: Error;\n\n constructor(message: string, request: RequestContext, cause?: Error) {\n super(message, undefined, 'network_error');\n this.request = request;\n this.cause = cause;\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n\n/**\n * Thrown when a request times out.\n * The `request` property contains context about the timed-out request.\n * The `timeoutMs` property indicates the timeout duration that was exceeded.\n */\nexport class TimeoutError extends SemaphoreError {\n public readonly request: RequestContext;\n public readonly timeoutMs: number;\n\n constructor(message: string, request: RequestContext, timeoutMs: number) {\n super(message, undefined, 'timeout_error');\n this.request = request;\n this.timeoutMs = timeoutMs;\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n","import type { RequestContext, HttpRequestOptions, RetryOptions } from '../types/http.js';\nimport {\n SemaphoreError,\n AuthenticationError,\n RateLimitError,\n ValidationError,\n NetworkError,\n TimeoutError,\n} from '../errors/index.js';\n\n/**\n * Configuration for HttpClient.\n */\nexport interface HttpClientConfig {\n baseUrl: string;\n apiKey: string;\n timeout: number;\n maxRetries?: number;\n onRetry?: (attempt: number, delayMs: number) => void;\n}\n\n/**\n * Parse Retry-After header value to milliseconds.\n * Supports both seconds format (\"120\") and HTTP-date format (\"Wed, 21 Oct 2015 07:28:00 GMT\").\n *\n * @param header - The Retry-After header value\n * @param defaultMs - Default delay in milliseconds when header is missing or invalid\n * @returns Delay in milliseconds\n */\nexport function parseRetryAfter(header: string | null, defaultMs: number = 1000): number {\n if (!header) {\n return defaultMs;\n }\n\n // Format 1: delay-seconds (e.g., \"120\")\n const seconds = parseFloat(header);\n if (!isNaN(seconds) && seconds >= 0) {\n return Math.round(seconds * 1000);\n }\n\n // Format 2: http-date (e.g., \"Wed, 21 Oct 2015 07:28:00 GMT\")\n const date = new Date(header);\n if (!isNaN(date.getTime())) {\n const delayMs = date.getTime() - Date.now();\n return Math.max(0, delayMs);\n }\n\n return defaultMs;\n}\n\n/**\n * Remove sensitive information from URL for error messages.\n * Removes apikey query parameter if present.\n *\n * @param url - The URL to sanitize\n * @returns URL with sensitive parameters removed\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n urlObj.searchParams.delete('apikey');\n return urlObj.toString();\n } catch {\n // If URL parsing fails, return original (it may be a relative path)\n return url;\n }\n}\n\n/**\n * HTTP client with timeout and retry support for the Semaphore API.\n *\n * Features:\n * - Configurable timeout using AbortSignal.timeout()\n * - Automatic retry on 429 (rate limit) responses with Retry-After header support\n * - Maps HTTP status codes to typed error classes\n * - Includes sanitized request context in errors for debugging\n */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n private readonly onRetry?: (attempt: number, delayMs: number) => void;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n this.maxRetries = config.maxRetries ?? 3;\n this.onRetry = config.onRetry;\n }\n\n /**\n * Map HTTP response to appropriate error class.\n *\n * @param response - The HTTP response\n * @param bodyText - Response body text (first 500 chars)\n * @returns Appropriate error instance\n */\n private mapResponseToError(\n response: Response,\n bodyText: string\n ): SemaphoreError {\n const status = response.status;\n const truncatedBody = bodyText.length > 500 ? bodyText.slice(0, 500) + '...' : bodyText;\n const message = `HTTP ${status}: ${truncatedBody || response.statusText}`;\n\n if (status === 401) {\n return new AuthenticationError(message);\n }\n\n if (status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n const retryAfterSeconds = retryAfter ? parseRetryAfter(retryAfter) / 1000 : undefined;\n return new RateLimitError(message, retryAfterSeconds);\n }\n\n if (status >= 400 && status < 500) {\n return new ValidationError(message);\n }\n\n // 500+ server errors\n return new SemaphoreError(message, status);\n }\n\n /**\n * Make an HTTP request to the Semaphore API.\n *\n * @param path - API path (e.g., \"/messages\")\n * @param options - Request and retry options\n * @returns Parsed JSON response\n * @throws {NetworkError} On connection failures\n * @throws {TimeoutError} On request timeout\n * @throws {AuthenticationError} On 401 responses\n * @throws {RateLimitError} On 429 responses (after retries exhausted)\n * @throws {ValidationError} On 4xx responses\n * @throws {SemaphoreError} On 5xx responses\n */\n async request<T>(\n path: string,\n options: HttpRequestOptions & RetryOptions = {}\n ): Promise<T> {\n const {\n method = 'GET',\n body,\n timeout = this.timeout,\n headers = {},\n maxRetries = this.maxRetries,\n onRetry = this.onRetry,\n } = options;\n\n // Build URL with apikey for GET requests\n let url = `${this.baseUrl}${path}`;\n if (method === 'GET') {\n const urlObj = new URL(url);\n urlObj.searchParams.set('apikey', this.apiKey);\n url = urlObj.toString();\n }\n\n const sanitizedUrl = sanitizeUrl(url);\n const requestContext: RequestContext = {\n url: sanitizedUrl,\n method,\n };\n\n // Build form-encoded body for POST requests\n let requestBody: URLSearchParams | undefined;\n if (method === 'POST' && body) {\n requestBody = new URLSearchParams();\n requestBody.set('apikey', this.apiKey);\n for (const [key, value] of Object.entries(body as Record<string, unknown>)) {\n if (value !== undefined && value !== null) {\n requestBody.set(key, String(value));\n }\n }\n }\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n method,\n headers: {\n ...(method === 'POST' ? { 'Content-Type': 'application/x-www-form-urlencoded' } : {}),\n ...headers,\n },\n body: requestBody,\n signal: AbortSignal.timeout(timeout),\n });\n\n if (!response.ok) {\n // Read response body for error message\n let bodyText = '';\n try {\n bodyText = await response.text();\n } catch {\n // Ignore body read errors\n }\n\n // Handle 429 rate limit with retry\n if (response.status === 429 && attempt < maxRetries) {\n const retryAfter = response.headers.get('Retry-After');\n const delayMs = parseRetryAfter(retryAfter);\n onRetry?.(attempt, delayMs);\n await new Promise(resolve => setTimeout(resolve, delayMs));\n continue;\n }\n\n // Throw mapped error for all other cases\n throw this.mapResponseToError(response, bodyText);\n }\n\n // Parse successful response\n try {\n return await response.json() as T;\n } catch (parseError) {\n throw new SemaphoreError(\n `Failed to parse response JSON: ${parseError instanceof Error ? parseError.message : 'Unknown error'}`,\n response.status\n );\n }\n\n } catch (error) {\n // Re-throw our own errors\n if (error instanceof SemaphoreError) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Handle timeout errors from AbortSignal.timeout()\n if (error.name === 'TimeoutError') {\n throw new TimeoutError(\n `Request timed out after ${timeout}ms`,\n requestContext,\n timeout\n );\n }\n\n // Handle network errors (connection refused, DNS failure, etc.)\n throw new NetworkError(\n `Network error: ${error.message}`,\n requestContext,\n error\n );\n }\n\n // Re-throw unknown errors\n throw error;\n }\n }\n\n // All retries exhausted on 429\n throw new RateLimitError('Rate limit exceeded after max retries');\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type {\n SendMessageRequest,\n SendMessageResponse,\n BulkSendMessageResponse,\n MessageListRequest,\n Message,\n} from '../types/index.js';\n\n/**\n * Resource class for SMS message operations.\n *\n * Provides methods for sending messages, listing sent messages,\n * and retrieving message details by ID.\n *\n * @example\n * ```typescript\n * const client = new SemaphoreClient({ apiKey: 'your-api-key' });\n *\n * // Send a single message\n * const response = await client.messages.send({\n * number: '09171234567',\n * message: 'Hello!',\n * sendername: 'SEMAPHORE',\n * });\n * ```\n */\nexport class MessagesResource {\n /**\n * Create a new MessagesResource instance.\n *\n * @param http - HttpClient instance for making API requests\n */\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Send an SMS message to one or more recipients.\n *\n * When sending to multiple recipients (up to 1000), pass an array of numbers.\n * The API will return an array of responses, one for each recipient.\n *\n * @param params - Message parameters including recipient(s), message content, and sender name\n * @returns Single response for one recipient, array of responses for multiple recipients\n *\n * @example\n * ```typescript\n * // Send to single recipient\n * const response = await client.messages.send({\n * number: '09171234567',\n * message: 'Hello!',\n * sendername: 'SEMAPHORE',\n * });\n * console.log(response.message_id);\n *\n * // Send to multiple recipients (bulk)\n * const responses = await client.messages.send({\n * number: ['09171234567', '09181234567'],\n * message: 'Hello everyone!',\n * sendername: 'SEMAPHORE',\n * });\n * console.log(responses.length); // 2\n * ```\n */\n async send(\n params: SendMessageRequest\n ): Promise<SendMessageResponse | BulkSendMessageResponse> {\n // Convert number array to comma-separated string for API\n const number = Array.isArray(params.number)\n ? params.number.join(',')\n : params.number;\n\n const body = {\n number,\n message: params.message,\n sendername: params.sendername,\n };\n\n return this.http.request<SendMessageResponse | BulkSendMessageResponse>(\n '/messages',\n {\n method: 'POST',\n body,\n }\n );\n }\n\n /**\n * List sent messages with optional filtering.\n *\n * Supports pagination and filtering by date range, network, status, and sender name.\n *\n * @param params - Optional filter parameters\n * @returns Array of message objects\n *\n * @example\n * ```typescript\n * // List all messages\n * const messages = await client.messages.list();\n *\n * // List with filters\n * const filtered = await client.messages.list({\n * page: 1,\n * limit: 50,\n * status: 'Sent',\n * startDate: '2024-01-01',\n * endDate: '2024-01-31',\n * });\n * ```\n */\n async list(params?: MessageListRequest): Promise<Message[]> {\n const queryString = this.buildQueryString(params);\n return this.http.request<Message[]>(`/messages${queryString}`, {\n method: 'GET',\n });\n }\n\n /**\n * Get a specific message by ID.\n *\n * @param id - The message ID to retrieve\n * @returns The message object\n *\n * @example\n * ```typescript\n * const message = await client.messages.get(12345);\n * console.log(message.status); // 'Sent'\n * console.log(message.recipient); // '09171234567'\n * ```\n */\n async get(id: number): Promise<Message> {\n return this.http.request<Message>(`/messages/${id}`, {\n method: 'GET',\n });\n }\n\n /**\n * Build query string from optional MessageListRequest parameters.\n *\n * @param params - Optional filter parameters\n * @returns Query string including leading '?' if params exist, empty string otherwise\n */\n private buildQueryString(params?: MessageListRequest): string {\n if (!params) {\n return '';\n }\n\n const searchParams = new URLSearchParams();\n\n if (params.page !== undefined) {\n searchParams.set('page', String(params.page));\n }\n if (params.limit !== undefined) {\n searchParams.set('limit', String(params.limit));\n }\n if (params.startDate !== undefined) {\n searchParams.set('startDate', params.startDate);\n }\n if (params.endDate !== undefined) {\n searchParams.set('endDate', params.endDate);\n }\n if (params.network !== undefined) {\n searchParams.set('network', params.network);\n }\n if (params.status !== undefined) {\n searchParams.set('status', params.status);\n }\n if (params.sendername !== undefined) {\n searchParams.set('sendername', params.sendername);\n }\n\n const queryString = searchParams.toString();\n return queryString ? `?${queryString}` : '';\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type { SendOtpRequest, SendOtpResponse } from '../types/index.js';\n\n/**\n * Resource for sending OTP (One-Time Password) messages.\n *\n * OTP messages use a priority route with no rate limit.\n * Each message costs 2 credits per 160 characters.\n */\nexport class OtpResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Send an OTP message to a recipient.\n *\n * Uses priority route - no rate limit, 2 credits per 160-char message.\n * The API generates the OTP code and replaces the {otp} placeholder in your message.\n *\n * @param params - OTP parameters including recipient, message template, sender name\n * @returns Response including the generated OTP code\n *\n * @example\n * ```typescript\n * const response = await client.otp.send({\n * number: '+639171234567',\n * message: 'Your verification code is {otp}',\n * sendername: 'MyApp',\n * });\n * console.log('OTP sent:', response.code);\n * ```\n *\n * @example\n * ```typescript\n * // With custom code length\n * const response = await client.otp.send({\n * number: '+639171234567',\n * message: 'Your code is {otp}',\n * sendername: 'MyApp',\n * code_length: 4,\n * });\n * ```\n */\n async send(params: SendOtpRequest): Promise<SendOtpResponse> {\n return this.http.request<SendOtpResponse>('/otp', {\n method: 'POST',\n body: params,\n });\n }\n}\n","import type { HttpClient } from '../http/index.js';\nimport type {\n AccountInfo,\n Transaction,\n TransactionListRequest,\n SenderName,\n} from '../types/index.js';\n\n/**\n * Resource for retrieving account information.\n */\nexport class AccountResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Get account information including credit balance.\n *\n * @returns Account info with balance\n *\n * @example\n * ```typescript\n * const info = await client.account.info();\n * console.log('Account:', info.account_name);\n * console.log('Balance:', info.credit_balance);\n * ```\n */\n async info(): Promise<AccountInfo> {\n return this.http.request<AccountInfo>('/account');\n }\n\n /**\n * Get transaction history.\n *\n * @param params - Optional pagination and date filter parameters\n * @returns Array of transactions\n *\n * @example\n * ```typescript\n * // Get all transactions\n * const transactions = await client.account.transactions();\n * ```\n *\n * @example\n * ```typescript\n * // Get paginated transactions with date range\n * const transactions = await client.account.transactions({\n * page: 1,\n * limit: 50,\n * startDate: '2026-01-01',\n * endDate: '2026-01-31',\n * });\n * ```\n */\n async transactions(params?: TransactionListRequest): Promise<Transaction[]> {\n const query = this.buildQueryString(params);\n return this.http.request<Transaction[]>(`/account/transactions${query}`);\n }\n\n /**\n * Get list of approved sender names.\n *\n * @returns Array of sender names with status\n *\n * @example\n * ```typescript\n * const senderNames = await client.account.senderNames();\n * for (const sender of senderNames) {\n * console.log(`${sender.name}: ${sender.status}`);\n * }\n * ```\n */\n async senderNames(): Promise<SenderName[]> {\n return this.http.request<SenderName[]>('/account/sendernames');\n }\n\n /**\n * Build query string from optional transaction list parameters.\n *\n * @param params - Optional filter parameters\n * @returns Query string (empty string or ?param1=value1&param2=value2)\n */\n private buildQueryString(params?: TransactionListRequest): string {\n if (!params) return '';\n\n const searchParams = new URLSearchParams();\n\n if (params.page !== undefined) searchParams.set('page', String(params.page));\n if (params.limit !== undefined) searchParams.set('limit', String(params.limit));\n if (params.startDate) searchParams.set('startDate', params.startDate);\n if (params.endDate) searchParams.set('endDate', params.endDate);\n\n const str = searchParams.toString();\n return str ? `?${str}` : '';\n }\n}\n","import { AuthenticationError } from './errors/index.js';\nimport { HttpClient } from './http/index.js';\nimport { MessagesResource } from './resources/messages.js';\nimport { OtpResource } from './resources/otp.js';\nimport { AccountResource } from './resources/account.js';\nimport type { SemaphoreClientOptions } from './types/common.js';\n\n/**\n * Semaphore API client for sending SMS and OTP messages.\n *\n * @example\n * ```typescript\n * // Send SMS\n * const client = new SemaphoreClient({ apiKey: 'your-api-key' });\n * await client.messages.send({\n * number: '+639171234567',\n * message: 'Hello!',\n * sendername: 'MyApp',\n * });\n *\n * // Check balance\n * const info = await client.account.info();\n * console.log('Balance:', info.credit_balance);\n * ```\n */\nexport class SemaphoreClient {\n /** @internal HTTP client used by resource classes. */\n protected readonly http: HttpClient;\n\n /** SMS message operations */\n readonly messages: MessagesResource;\n\n /** OTP message operations (priority route, no rate limit) */\n readonly otp: OtpResource;\n\n /** Account information operations */\n readonly account: AccountResource;\n\n constructor(options: SemaphoreClientOptions = {}) {\n // Environment variable fallback (cross-runtime compatible)\n let apiKey = options.apiKey;\n if (!apiKey && typeof process !== 'undefined' && process.env) {\n apiKey = process.env.SEMAPHORE_API_KEY;\n }\n\n // Fail fast on missing API key (constructor-time validation)\n if (!apiKey) {\n throw new AuthenticationError(\n 'Missing API key. Pass it to the constructor `new SemaphoreClient({ apiKey: \"...\" })` ' +\n 'or set the SEMAPHORE_API_KEY environment variable.'\n );\n }\n\n const baseUrl = options.baseUrl ?? 'https://api.semaphore.co/api/v4';\n const timeout = options.timeout ?? 30000;\n\n this.http = new HttpClient({\n baseUrl,\n apiKey,\n timeout,\n onRetry: options.onRetry,\n });\n\n // Instantiate resource classes with HTTP client access\n this.messages = new MessagesResource(this.http);\n this.otp = new OtpResource(this.http);\n this.account = new AccountResource(this.http);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "semaphoreco",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "TypeScript/JavaScript client for Semaphore.co - Philippines SMS Gateway API for sending SMS and OTP messages",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -26,7 +26,9 @@
26
26
  "build": "tsup",
27
27
  "typecheck": "tsc --noEmit",
28
28
  "lint:package": "publint && attw --pack .",
29
- "prepublishOnly": "npm run build && npm run lint:package"
29
+ "prepublishOnly": "npm run build && npm run lint:package",
30
+ "test": "vitest run",
31
+ "test:watch": "vitest"
30
32
  },
31
33
  "keywords": [
32
34
  "semaphore",
@@ -59,7 +61,8 @@
59
61
  "@types/node": "^25.0.10",
60
62
  "publint": "^0.3.17",
61
63
  "tsup": "^8.5.1",
62
- "typescript": "^5.9.3"
64
+ "typescript": "^5.9.3",
65
+ "vitest": "^4.0.18"
63
66
  },
64
67
  "engines": {
65
68
  "node": ">=18.0.0"