pathao-merchant-sdk 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -13,6 +13,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
13
 
14
14
  ## [Unreleased]
15
15
 
16
+ ## [2.0.2] - 2025-12-08
17
+
18
+ ### Added
19
+ - **Factory methods**: `PathaoApiService.fromEnv()` and `PathaoApiService.fromConfig()` for convenient initialization patterns
20
+ - **Debug logging**: Optional `debug` flag in constructor options to log all HTTP requests and responses
21
+ - **Configurable circuit breaker**: `circuitBreaker` option to customize failure threshold and timeout
22
+ - **Comprehensive error handling examples** in README with `PathaoApiError` usage patterns
23
+ - **Advanced options documentation** for factory methods and configuration
24
+
25
+ ### Changed
26
+ - **Breaking**: Deferred configuration validation to first API call instead of constructor throw. SDK now initializes successfully even without credentials, and throws `PathaoApiError` when attempting an API call with missing config.
27
+ - Removed config duplication in constructor (axios create config now uses resolved config values).
28
+ - Constructor now accepts optional `options` parameter: `new PathaoApiService(config, { debug?, circuitBreaker? })`
29
+ - Constructor no longer throws upfront, allowing graceful error handling at first API usage.
30
+
31
+ ### Fixed
32
+ - `ResolvedPathaoConfig` internal type ensures `timeout` is always a number.
33
+ - Tests updated to reflect deferred validation behavior.
34
+ - Circuit breaker now properly resets on successful requests and maintains configurable thresholds.
35
+
36
+ ### Verified
37
+ - `npm test` passes with 22/22 tests.
38
+ - Build succeeds (CJS/ESM/DTS).
39
+
40
+ ## [2.0.1] - 2025-12-05
41
+
42
+ ### Changed
43
+ - Added `PathaoApiError` with structured fields (`status`, `code`, `type`, `errors`, `validation`, `responseData`) and updated all SDK methods to throw it.
44
+
45
+ ### Verified
46
+ - `npm test` (jest) passes.
47
+
16
48
  ## [1.2.0] - 2024-12-05
17
49
 
18
50
  ### Fixed
package/README.md CHANGED
@@ -164,6 +164,56 @@ const pathao = new PathaoApiService({
164
164
  });
165
165
  ```
166
166
 
167
+ #### Factory Methods
168
+
169
+ The SDK provides convenient factory methods for common initialization patterns:
170
+
171
+ ```typescript
172
+ // Create from environment variables
173
+ const pathao = PathaoApiService.fromEnv();
174
+
175
+ // Create from environment with additional options
176
+ const pathao = PathaoApiService.fromEnv({
177
+ debug: true, // Enable debug logging
178
+ circuitBreaker: {
179
+ threshold: 10, // Number of failures before opening circuit (default: 5)
180
+ timeout: 120000 // Timeout before attempting to close circuit (default: 60000ms)
181
+ }
182
+ });
183
+
184
+ // Create from explicit config
185
+ const pathao = PathaoApiService.fromConfig({
186
+ baseURL: 'https://api-hermes.pathao.com',
187
+ clientId: 'client-id',
188
+ clientSecret: 'client-secret',
189
+ username: 'username',
190
+ password: 'password',
191
+ timeout: 5000
192
+ }, {
193
+ debug: true,
194
+ circuitBreaker: { threshold: 8 }
195
+ });
196
+ ```
197
+
198
+ #### Advanced Options
199
+
200
+ ```typescript
201
+ const pathao = new PathaoApiService(config, {
202
+ debug: false, // Enable detailed debug logging (default: false)
203
+ circuitBreaker: {
204
+ threshold: 5, // Failures before opening circuit (default: 5)
205
+ timeout: 60000 // Wait time before retry (default: 60000ms = 1 min)
206
+ }
207
+ });
208
+ ```
209
+
210
+ When `debug` is enabled, the SDK logs all HTTP requests and responses:
211
+
212
+ ```
213
+ [Pathao SDK] GET /aladdin/api/v1/stores { headers: {...}, data: {...} }
214
+ [Pathao SDK] Response 200 { url: '...', data: {...} }
215
+ ```
216
+
167
217
  ### Order Management
168
218
 
169
219
  #### Create Order
@@ -297,17 +347,61 @@ enum ItemType {
297
347
 
298
348
  ## Error Handling
299
349
 
300
- The SDK provides comprehensive error handling with detailed error messages:
350
+ The SDK provides comprehensive error handling through the `PathaoApiError` class, which extends Error with additional properties for detailed error information:
301
351
 
302
352
  ```typescript
353
+ import { PathaoApiService, PathaoApiError } from 'pathao-merchant-sdk';
354
+
355
+ const pathao = new PathaoApiService({
356
+ clientId: process.env.PATHAO_CLIENT_ID,
357
+ clientSecret: process.env.PATHAO_CLIENT_SECRET,
358
+ username: process.env.PATHAO_USERNAME,
359
+ password: process.env.PATHAO_PASSWORD
360
+ });
361
+
303
362
  try {
304
363
  const order = await pathao.createOrder(orderData);
364
+ console.log('Order created:', order.data.consignment_id);
365
+ } catch (error) {
366
+ // Check if it's a PathaoApiError (structured error from Pathao API)
367
+ if (error instanceof PathaoApiError) {
368
+ console.error('Pathao API Error:', {
369
+ status: error.status, // HTTP status code
370
+ code: error.code, // Pathao error code
371
+ type: error.type, // Error type (e.g., 'ValidationException')
372
+ message: error.message, // Error message
373
+ errors: error.errors, // Field-level errors
374
+ validation: error.validation // Validation errors
375
+ });
376
+ } else {
377
+ console.error('Unexpected error:', error.message);
378
+ }
379
+ }
380
+ ```
381
+
382
+ ### Error Properties
383
+
384
+ - **status**: HTTP status code (e.g., 400, 401, 422)
385
+ - **code**: Pathao API error code for programmatic handling
386
+ - **type**: Error type string (e.g., 'ValidationException', 'AuthenticationException')
387
+ - **errors**: Object with field-level error messages
388
+ - **validation**: Object with validation error messages
389
+ - **message**: Human-readable error message
390
+
391
+ ### Configuration Validation
392
+
393
+ Configuration validation is deferred until the first API call to allow gradual setup:
394
+
395
+ ```typescript
396
+ // This won't throw immediately
397
+ const pathao = new PathaoApiService({});
398
+
399
+ // This will throw PathaoApiError if credentials are missing
400
+ try {
401
+ await pathao.getStores();
305
402
  } catch (error) {
306
- console.error('Order creation failed:', error.message);
307
-
308
- // Check if it's a Pathao API error
309
- if (error.response?.data) {
310
- console.error('API Error:', error.response.data);
403
+ if (error instanceof PathaoApiError) {
404
+ console.error('Configuration error:', error.validation);
311
405
  }
312
406
  }
313
407
  ```
package/dist/index.d.mts CHANGED
@@ -205,6 +205,26 @@ declare enum ItemType {
205
205
  * - City, zone, and area management
206
206
  */
207
207
 
208
+ declare class PathaoApiError extends Error {
209
+ status: number | undefined;
210
+ code: number | undefined;
211
+ type: string | undefined;
212
+ errors: Record<string, string[]> | undefined;
213
+ validation: Record<string, string[]> | undefined;
214
+ responseData: unknown;
215
+ constructor(message: string, options?: {
216
+ status?: number | undefined;
217
+ code?: number | undefined;
218
+ type?: string | undefined;
219
+ errors?: Record<string, string[]> | undefined;
220
+ validation?: Record<string, string[]> | undefined;
221
+ responseData?: unknown;
222
+ });
223
+ }
224
+ interface CircuitBreakerConfig {
225
+ threshold?: number;
226
+ timeout?: number;
227
+ }
208
228
  declare class PathaoApiService {
209
229
  private pathaoClient;
210
230
  private accessToken;
@@ -214,14 +234,21 @@ declare class PathaoApiService {
214
234
  private isAuthenticating;
215
235
  private authPromise;
216
236
  private requestQueue;
237
+ private hasValidated;
238
+ private debug;
217
239
  private circuitBreaker;
218
- constructor(config: PathaoConfig);
240
+ constructor(config: PathaoConfig, options?: {
241
+ debug?: boolean;
242
+ circuitBreaker?: CircuitBreakerConfig;
243
+ });
244
+ private validateConfiguration;
219
245
  private ensureAuthenticated;
220
246
  private performAuthentication;
221
247
  private processRequestQueue;
222
248
  private authenticate;
223
249
  private refreshAccessToken;
224
250
  private getErrorMessage;
251
+ private toPathaoApiError;
225
252
  private handleCircuitBreaker;
226
253
  createOrder(orderData: PathaoOrderRequest): Promise<PathaoOrderResponse>;
227
254
  createStore(storeData: PathaoStoreRequest): Promise<PathaoStoreCreateResponse>;
@@ -247,6 +274,14 @@ declare class PathaoApiService {
247
274
  static validateContactNumber(phone: string): boolean;
248
275
  static validateStoreAddress(address: string): boolean;
249
276
  clearAuth(): void;
277
+ static fromEnv(options?: {
278
+ debug?: boolean;
279
+ circuitBreaker?: CircuitBreakerConfig;
280
+ }): PathaoApiService;
281
+ static fromConfig(config: PathaoConfig, options?: {
282
+ debug?: boolean;
283
+ circuitBreaker?: CircuitBreakerConfig;
284
+ }): PathaoApiService;
250
285
  }
251
286
 
252
- export { DeliveryType, ItemType, PathaoApiService, type PathaoAreaResponse, type PathaoAuthResponse, type PathaoCityResponse, type PathaoConfig, type PathaoError, type PathaoOrderRequest, type PathaoOrderResponse, type PathaoOrderStatusResponse, type PathaoPriceRequest, type PathaoPriceResponse, type PathaoStore, type PathaoStoreCreateResponse, type PathaoStoreListResponse, type PathaoStoreRequest, type PathaoZoneResponse };
287
+ export { DeliveryType, ItemType, PathaoApiError, PathaoApiService, type PathaoAreaResponse, type PathaoAuthResponse, type PathaoCityResponse, type PathaoConfig, type PathaoError, type PathaoOrderRequest, type PathaoOrderResponse, type PathaoOrderStatusResponse, type PathaoPriceRequest, type PathaoPriceResponse, type PathaoStore, type PathaoStoreCreateResponse, type PathaoStoreListResponse, type PathaoStoreRequest, type PathaoZoneResponse };
package/dist/index.d.ts CHANGED
@@ -205,6 +205,26 @@ declare enum ItemType {
205
205
  * - City, zone, and area management
206
206
  */
207
207
 
208
+ declare class PathaoApiError extends Error {
209
+ status: number | undefined;
210
+ code: number | undefined;
211
+ type: string | undefined;
212
+ errors: Record<string, string[]> | undefined;
213
+ validation: Record<string, string[]> | undefined;
214
+ responseData: unknown;
215
+ constructor(message: string, options?: {
216
+ status?: number | undefined;
217
+ code?: number | undefined;
218
+ type?: string | undefined;
219
+ errors?: Record<string, string[]> | undefined;
220
+ validation?: Record<string, string[]> | undefined;
221
+ responseData?: unknown;
222
+ });
223
+ }
224
+ interface CircuitBreakerConfig {
225
+ threshold?: number;
226
+ timeout?: number;
227
+ }
208
228
  declare class PathaoApiService {
209
229
  private pathaoClient;
210
230
  private accessToken;
@@ -214,14 +234,21 @@ declare class PathaoApiService {
214
234
  private isAuthenticating;
215
235
  private authPromise;
216
236
  private requestQueue;
237
+ private hasValidated;
238
+ private debug;
217
239
  private circuitBreaker;
218
- constructor(config: PathaoConfig);
240
+ constructor(config: PathaoConfig, options?: {
241
+ debug?: boolean;
242
+ circuitBreaker?: CircuitBreakerConfig;
243
+ });
244
+ private validateConfiguration;
219
245
  private ensureAuthenticated;
220
246
  private performAuthentication;
221
247
  private processRequestQueue;
222
248
  private authenticate;
223
249
  private refreshAccessToken;
224
250
  private getErrorMessage;
251
+ private toPathaoApiError;
225
252
  private handleCircuitBreaker;
226
253
  createOrder(orderData: PathaoOrderRequest): Promise<PathaoOrderResponse>;
227
254
  createStore(storeData: PathaoStoreRequest): Promise<PathaoStoreCreateResponse>;
@@ -247,6 +274,14 @@ declare class PathaoApiService {
247
274
  static validateContactNumber(phone: string): boolean;
248
275
  static validateStoreAddress(address: string): boolean;
249
276
  clearAuth(): void;
277
+ static fromEnv(options?: {
278
+ debug?: boolean;
279
+ circuitBreaker?: CircuitBreakerConfig;
280
+ }): PathaoApiService;
281
+ static fromConfig(config: PathaoConfig, options?: {
282
+ debug?: boolean;
283
+ circuitBreaker?: CircuitBreakerConfig;
284
+ }): PathaoApiService;
250
285
  }
251
286
 
252
- export { DeliveryType, ItemType, PathaoApiService, type PathaoAreaResponse, type PathaoAuthResponse, type PathaoCityResponse, type PathaoConfig, type PathaoError, type PathaoOrderRequest, type PathaoOrderResponse, type PathaoOrderStatusResponse, type PathaoPriceRequest, type PathaoPriceResponse, type PathaoStore, type PathaoStoreCreateResponse, type PathaoStoreListResponse, type PathaoStoreRequest, type PathaoZoneResponse };
287
+ export { DeliveryType, ItemType, PathaoApiError, PathaoApiService, type PathaoAreaResponse, type PathaoAuthResponse, type PathaoCityResponse, type PathaoConfig, type PathaoError, type PathaoOrderRequest, type PathaoOrderResponse, type PathaoOrderStatusResponse, type PathaoPriceRequest, type PathaoPriceResponse, type PathaoStore, type PathaoStoreCreateResponse, type PathaoStoreListResponse, type PathaoStoreRequest, type PathaoZoneResponse };