pathao-merchant-sdk 2.3.2 → 3.0.1
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 +19 -0
- package/CONTRIBUTING.md +8 -8
- package/README.md +125 -3
- package/dist/index.d.mts +61 -25
- package/dist/index.d.ts +61 -25
- package/dist/index.js +154 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +151 -43
- package/dist/index.mjs.map +1 -1
- package/dist/status-xIApOisZ.d.mts +28 -0
- package/dist/status-xIApOisZ.d.ts +28 -0
- package/dist/webhooks.d.mts +26 -1
- package/dist/webhooks.d.ts +26 -1
- package/dist/webhooks.js +43 -2
- package/dist/webhooks.js.map +1 -1
- package/dist/webhooks.mjs +42 -3
- package/dist/webhooks.mjs.map +1 -1
- package/package.json +25 -7
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.0.1](https://github.com/Sifat07/pathao-merchant-sdk/compare/pathao-merchant-sdk-v3.0.0...pathao-merchant-sdk-v3.0.1) (2026-10-02)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* classify HTTP 402 as kind 'forbidden' ([be59179](https://github.com/Sifat07/pathao-merchant-sdk/commit/be59179fb669d74e6bef863f6f44390b9b7fb265))
|
|
14
|
+
* export ./package.json ([daddca4](https://github.com/Sifat07/pathao-merchant-sdk/commit/daddca47359c6fee6284a74a595e45e4968d4054))
|
|
15
|
+
|
|
16
|
+
## [3.0.0](https://github.com/Sifat07/pathao-merchant-sdk/compare/pathao-merchant-sdk-v2.3.2...pathao-merchant-sdk-v3.0.0) (2026-10-02)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### ⚠ BREAKING CHANGES
|
|
20
|
+
|
|
21
|
+
* new PathaoApiService(config) no longer reads PATHAO_* environment variables for missing fields or PATHAO_TIMEOUT. Pass every field explicitly, or use PathaoApiService.fromEnv().
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* close [#12](https://github.com/Sifat07/pathao-merchant-sdk/issues/12)–[#20](https://github.com/Sifat07/pathao-merchant-sdk/issues/20) (security, retries, webhooks, phones, explicit config, types, CI) ([#21](https://github.com/Sifat07/pathao-merchant-sdk/issues/21)) ([9702f72](https://github.com/Sifat07/pathao-merchant-sdk/commit/9702f724e8bc5fced2ec644d746d29b6242b0baf))
|
|
26
|
+
|
|
8
27
|
## [2.3.2](https://github.com/Sifat07/pathao-merchant-sdk/compare/pathao-merchant-sdk-v2.3.1...pathao-merchant-sdk-v2.3.2) (2026-09-23)
|
|
9
28
|
|
|
10
29
|
|
package/CONTRIBUTING.md
CHANGED
|
@@ -10,10 +10,9 @@ Thank you for your interest in contributing to the Pathao Merchant SDK! This doc
|
|
|
10
10
|
git clone https://github.com/YOUR_USERNAME/pathao-merchant-sdk.git
|
|
11
11
|
cd pathao-merchant-sdk
|
|
12
12
|
```
|
|
13
|
-
3. **Install dependencies
|
|
13
|
+
3. **Install dependencies** (the repo pins pnpm 10 via `packageManager`; `corepack enable` makes `pnpm` use it):
|
|
14
14
|
```bash
|
|
15
|
-
|
|
16
|
-
# or
|
|
15
|
+
corepack enable
|
|
17
16
|
pnpm install
|
|
18
17
|
```
|
|
19
18
|
|
|
@@ -37,9 +36,10 @@ git checkout -b fix/your-bug-fix
|
|
|
37
36
|
### 3. Run Tests
|
|
38
37
|
|
|
39
38
|
```bash
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
pnpm run lint
|
|
40
|
+
pnpm run type-check
|
|
41
|
+
pnpm test
|
|
42
|
+
pnpm run build
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
### 4. Commit Your Changes
|
|
@@ -159,8 +159,8 @@ What should happen
|
|
|
159
159
|
What actually happens
|
|
160
160
|
|
|
161
161
|
**Environment**
|
|
162
|
-
- SDK Version:
|
|
163
|
-
- Node Version:
|
|
162
|
+
- SDK Version: 3.0.0
|
|
163
|
+
- Node Version: 22.x
|
|
164
164
|
- OS: macOS/Windows/Linux
|
|
165
165
|
```
|
|
166
166
|
|
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ An **unofficial** TypeScript SDK for the [Pathao Courier Merchant API](https://m
|
|
|
28
28
|
- [Error Handling](#error-handling)
|
|
29
29
|
- [Webhooks](#webhooks)
|
|
30
30
|
- [TypeScript Types](#typescript-types)
|
|
31
|
+
- [Upgrading to 3.0.0](#upgrading-to-300)
|
|
31
32
|
- [Contributing](#contributing)
|
|
32
33
|
- [License](#license)
|
|
33
34
|
- [Changelog](#changelog)
|
|
@@ -124,6 +125,8 @@ PATHAO_PASSWORD=your-password
|
|
|
124
125
|
PATHAO_TIMEOUT=30000
|
|
125
126
|
```
|
|
126
127
|
|
|
128
|
+
Only `PathaoApiService.fromEnv()` reads these variables. `new PathaoApiService(config)`, `fromConfig()`, `sandbox()` and `production()` use exactly the config you pass, so a blank field fails validation instead of silently picking up another account's credentials from the environment (important when each tenant brings their own Pathao account).
|
|
129
|
+
|
|
127
130
|
If you use `dotenv`, load it before initializing the SDK:
|
|
128
131
|
|
|
129
132
|
```typescript
|
|
@@ -175,6 +178,7 @@ const pathao = new PathaoApiService(config, {
|
|
|
175
178
|
threshold: 5, // Failures before opening circuit (default: 5)
|
|
176
179
|
timeout: 60_000, // Ms before attempting to close circuit (default: 60000)
|
|
177
180
|
},
|
|
181
|
+
minRequestIntervalMs: 0, // Min gap between requests, queued (default: 0, off)
|
|
178
182
|
});
|
|
179
183
|
```
|
|
180
184
|
|
|
@@ -193,7 +197,7 @@ const order = await pathao.createOrder({
|
|
|
193
197
|
store_id: 12345, // Required — your store ID
|
|
194
198
|
merchant_order_id: "ORDER-001", // Optional — your internal tracking ID
|
|
195
199
|
recipient_name: "John Doe", // Required — 3–100 characters
|
|
196
|
-
recipient_phone: "01712345678", // Required —
|
|
200
|
+
recipient_phone: "01712345678", // Required — BD mobile; +880… / dashes are normalised before sending
|
|
197
201
|
recipient_secondary_phone: "01812345678", // Optional
|
|
198
202
|
recipient_address: "House 10, Road 5, Dhanmondi, Dhaka", // Required — 10–220 chars
|
|
199
203
|
recipient_city: 1, // Optional — auto-detected if omitted
|
|
@@ -338,7 +342,8 @@ All helpers are static and can be used before constructing the SDK:
|
|
|
338
342
|
```typescript
|
|
339
343
|
import { PathaoApiService } from "pathao-merchant-sdk";
|
|
340
344
|
|
|
341
|
-
PathaoApiService.validatePhoneNumber("
|
|
345
|
+
PathaoApiService.validatePhoneNumber("+8801712345678"); // true — BD mobile, 013–019
|
|
346
|
+
PathaoApiService.normalizePhoneNumber("+880 1712-345678"); // "01712345678" (null if invalid)
|
|
342
347
|
PathaoApiService.validateContactNumber("01712345678"); // true — same rules
|
|
343
348
|
PathaoApiService.validateAddress("House 10, Road 5, Dhanmondi, Dhaka"); // true — 10–220 chars
|
|
344
349
|
PathaoApiService.validateStoreAddress("House 10, Road 5, Dhanmondi"); // true — 15–120 chars
|
|
@@ -347,6 +352,8 @@ PathaoApiService.validateRecipientName("John Doe"); // true — 3–100 chars
|
|
|
347
352
|
PathaoApiService.validateStoreName("My Store"); // true — 3–50 chars
|
|
348
353
|
```
|
|
349
354
|
|
|
355
|
+
`createOrder` and `createBulkOrder` run the phone, name, address and weight checks before sending (a bulk failure names the index, e.g. `orders[3]: …`), and send the normalised phone numbers.
|
|
356
|
+
|
|
350
357
|
---
|
|
351
358
|
|
|
352
359
|
## Error Handling
|
|
@@ -360,6 +367,7 @@ try {
|
|
|
360
367
|
const order = await pathao.createOrder(orderData);
|
|
361
368
|
} catch (err) {
|
|
362
369
|
if (err instanceof PathaoApiError) {
|
|
370
|
+
console.error("Kind:", err.kind, "retryable:", err.retryable); // e.g. "validation", false
|
|
363
371
|
console.error("HTTP status:", err.status); // e.g. 422
|
|
364
372
|
console.error("Pathao code:", err.code); // Pathao internal error code
|
|
365
373
|
console.error("Type:", err.type); // e.g. "ValidationException"
|
|
@@ -370,6 +378,23 @@ try {
|
|
|
370
378
|
}
|
|
371
379
|
```
|
|
372
380
|
|
|
381
|
+
### Error kinds
|
|
382
|
+
|
|
383
|
+
Branch on `err.kind` instead of matching message text. `err.retryable` is `true` for `unavailable` and `rate_limited`.
|
|
384
|
+
|
|
385
|
+
| `kind` | When |
|
|
386
|
+
| -------------- | ----------------------------------------------------------- |
|
|
387
|
+
| `validation` | Rejected by the SDK before sending, or HTTP 400/422 |
|
|
388
|
+
| `config` | Missing/invalid `baseURL` or credentials |
|
|
389
|
+
| `auth` | HTTP 401 |
|
|
390
|
+
| `forbidden` | HTTP 403, or 402 (unpaid dues block new orders) |
|
|
391
|
+
| `not_found` | HTTP 404 |
|
|
392
|
+
| `rate_limited` | HTTP 429 |
|
|
393
|
+
| `unavailable` | 5xx, timeout, network failure, circuit breaker open |
|
|
394
|
+
| `unexpected` | Anything else; inspect `err.responseData` |
|
|
395
|
+
|
|
396
|
+
A retryable error on `createOrder` / `createBulkOrder` may still have booked the parcel. Look the order up before retrying a create.
|
|
397
|
+
|
|
373
398
|
### Common error scenarios
|
|
374
399
|
|
|
375
400
|
| Status | Cause |
|
|
@@ -384,7 +409,25 @@ try {
|
|
|
384
409
|
|
|
385
410
|
Pathao doesn't document its limits. Measured against its gateway (Sep 2026): **60 requests per rolling 60 seconds**, and the `429` carries **no `Retry-After` header**. The SDK therefore does not retry a `429` unless the server sends `Retry-After`; it throws `PathaoApiError` with `status: 429` so you can back off. 429s never open the circuit breaker.
|
|
386
411
|
|
|
387
|
-
For bulk work (e.g. polling `getOrderStatus` for many orders)
|
|
412
|
+
For bulk work (e.g. polling `getOrderStatus` for many orders) pass `minRequestIntervalMs: 1500`. The client then queues its requests (token grants and retries included) one every 1.5 s, about 40/min, leaving headroom for webhooks and other callers sharing the same credentials. Spacing is per instance: share one instance across the process.
|
|
413
|
+
|
|
414
|
+
Both numbers are exported: `PATHAO_RATE_LIMIT_PER_MINUTE` (60) and `PATHAO_STATUS_RETENTION_DAYS` (90, roughly how long `getOrderStatus` finds an order).
|
|
415
|
+
|
|
416
|
+
### Retries
|
|
417
|
+
|
|
418
|
+
The SDK retries a `5xx` up to twice, but only for requests that are safe to repeat: GETs, token grants and `calculatePrice`. `createOrder`, `createBulkOrder` and `createStore` are **never** retried, because a `5xx` (e.g. a gateway `504` in front of a slow success) doesn't mean the order wasn't booked. If you retry a create yourself, look the order up first, or you may book the parcel twice.
|
|
419
|
+
|
|
420
|
+
### Order lifecycle
|
|
421
|
+
|
|
422
|
+
Webhook events and `order_status_slug` describe the same journey. Despite its name, `order_status_slug` is a display label (`"Pending"`, `"In Transit"`, `"Return"`), and Pathao's own plugin spells the same states differently (`Pickup_Requested`, `At_the_Sorting_HUB`), so the SDK doesn't type it. `toLifecycleStatus` maps any of these spellings, or a webhook event (`order.pickup-requested`), to one of `created`, `picked_up`, `in_transit`, `out_for_delivery`, `delivered`, `partial`, `on_hold`, `returning`, `returned`, `cancelled`, or `unknown`.
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
import { toLifecycleStatus, isFinalLifecycleStatus } from "pathao-merchant-sdk"; // also exported from /webhooks
|
|
426
|
+
|
|
427
|
+
toLifecycleStatus("order.return-id-created"); // "returning" — not back yet, don't restock
|
|
428
|
+
toLifecycleStatus(info.data.order_status_slug);
|
|
429
|
+
isFinalLifecycleStatus("delivered"); // true
|
|
430
|
+
```
|
|
388
431
|
|
|
389
432
|
---
|
|
390
433
|
|
|
@@ -452,6 +495,12 @@ handler.on("error", (err) => {
|
|
|
452
495
|
console.error("Webhook error:", err.message);
|
|
453
496
|
});
|
|
454
497
|
|
|
498
|
+
// Payloads whose `event` isn't a known PathaoWebhookEvent arrive here, never
|
|
499
|
+
// under their own name (so a forged {"event":"error"} can't fire "error").
|
|
500
|
+
handler.on("unknown", (payload) => {
|
|
501
|
+
console.warn("Unrecognised Pathao event:", payload.event);
|
|
502
|
+
});
|
|
503
|
+
|
|
455
504
|
app.post(
|
|
456
505
|
"/webhooks/pathao",
|
|
457
506
|
express.raw({ type: "application/json" }),
|
|
@@ -558,6 +607,9 @@ All payloads also include `updated_at` (MySQL datetime) and `timestamp` (ISO 860
|
|
|
558
607
|
```typescript
|
|
559
608
|
import type {
|
|
560
609
|
PathaoConfig,
|
|
610
|
+
PathaoClientOptions,
|
|
611
|
+
PathaoErrorKind,
|
|
612
|
+
PathaoLifecycleStatus,
|
|
561
613
|
PathaoOrderRequest,
|
|
562
614
|
PathaoOrderResponse,
|
|
563
615
|
PathaoStoreRequest,
|
|
@@ -574,6 +626,7 @@ import type {
|
|
|
574
626
|
WebhookEventPayloadMap,
|
|
575
627
|
OrderDeliveredPayload,
|
|
576
628
|
OrderReturnIdCreatedPayload,
|
|
629
|
+
UnknownWebhookPayload,
|
|
577
630
|
PathaoWebhookEvent,
|
|
578
631
|
} from "pathao-merchant-sdk/webhooks";
|
|
579
632
|
|
|
@@ -583,6 +636,61 @@ type PaidPayload = WebhookEventPayloadMap[PathaoWebhookEvent.ORDER_PAID];
|
|
|
583
636
|
|
|
584
637
|
---
|
|
585
638
|
|
|
639
|
+
## Upgrading to 3.0.0
|
|
640
|
+
|
|
641
|
+
3.0.0 has **one breaking change**. Most apps need no code changes; check the table below if you catch specific errors or listen for unusual webhook events.
|
|
642
|
+
|
|
643
|
+
### Required: explicit config no longer reads environment variables
|
|
644
|
+
|
|
645
|
+
In 2.x, `new PathaoApiService(config)` (and `fromConfig()`, `sandbox()`, `production()`) filled any blank field from `PATHAO_*` environment variables and read `PATHAO_TIMEOUT`. In a multi-tenant app, a tenant with a blank field silently used the platform's own Pathao account. In 3.0.0 those constructors use **exactly** the config you pass. Only `fromEnv()` reads the environment.
|
|
646
|
+
|
|
647
|
+
**You are affected if** you leave config fields blank or omit them and rely on the environment to fill them in, or set `PATHAO_TIMEOUT` without using `fromEnv()`.
|
|
648
|
+
|
|
649
|
+
```typescript
|
|
650
|
+
// 2.x — blank fields came from PATHAO_* env vars
|
|
651
|
+
const pathao = new PathaoApiService({ baseURL: "https://api-hermes.pathao.com" } as PathaoConfig);
|
|
652
|
+
const sandbox = PathaoApiService.sandbox({ clientId: "", clientSecret: "", username: "", password: "" });
|
|
653
|
+
|
|
654
|
+
// 3.0.0 — either read everything from the environment...
|
|
655
|
+
const pathao = PathaoApiService.fromEnv(); // PATHAO_BASE_URL, _CLIENT_ID, _CLIENT_SECRET, _USERNAME, _PASSWORD, _TIMEOUT
|
|
656
|
+
|
|
657
|
+
// ...or pass every field yourself
|
|
658
|
+
const pathao = new PathaoApiService({
|
|
659
|
+
baseURL: process.env.PATHAO_BASE_URL!,
|
|
660
|
+
clientId: process.env.PATHAO_CLIENT_ID!,
|
|
661
|
+
clientSecret: process.env.PATHAO_CLIENT_SECRET!,
|
|
662
|
+
username: process.env.PATHAO_USERNAME!,
|
|
663
|
+
password: process.env.PATHAO_PASSWORD!,
|
|
664
|
+
timeout: 30_000,
|
|
665
|
+
});
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
If you already pass every field explicitly, nothing changes. A missing field now fails on the first API call with `PathaoApiError` (`kind: "config"`) instead of quietly using another account.
|
|
669
|
+
|
|
670
|
+
### Behaviour changes to check
|
|
671
|
+
|
|
672
|
+
| Change | Affects you if… | What to do |
|
|
673
|
+
| --- | --- | --- |
|
|
674
|
+
| `createOrder`, `createBulkOrder` and `createStore` are no longer auto-retried on `5xx` | You relied on the SDK to retry failed creates | Retry yourself, but look the order up first: a `5xx` may hide a booking that went through. See [Retries](#retries). |
|
|
675
|
+
| `createOrder` / `createBulkOrder` validate the secondary phone, recipient name (3–100) and address (10–220) before sending | You send data Pathao would have rejected with a `422` | Fix the data. The error is `PathaoApiError` with `kind: "validation"`; bulk errors name the order (`orders[2]: …`). |
|
|
676
|
+
| Phone numbers are normalised before sending, and only operator prefixes `013`–`019` are valid | You send `+880…` / `017-…` (now accepted), or `011…` / `012…` (now rejected; BTRC lists these as unused) | Nothing for real customers' numbers |
|
|
677
|
+
| Webhook events not in `PathaoWebhookEvent` are emitted as `'unknown'` | You call `handler.on("some.event")` for a name the SDK doesn't list | Listen on `'unknown'` and check `payload.event`. The `'webhook'` catch-all still fires for every event. |
|
|
678
|
+
| A webhook `event` must be a string | You process malformed payloads | Nothing; they now throw `PathaoWebhookError` |
|
|
679
|
+
| Any `3xx` response is an error (redirects are never followed) | Your `baseURL` points at something that redirects | Use the final URL |
|
|
680
|
+
| Some error messages were reworded (config errors, `formatPhoneNumber`) | You match on `err.message` | Switch to `err.kind` |
|
|
681
|
+
| ESM projects (`moduleResolution: node16`/`nodenext`) get the ESM type declarations | You worked around the old CJS-typed imports | Remove the workaround |
|
|
682
|
+
|
|
683
|
+
### New in 3.0.0 (optional)
|
|
684
|
+
|
|
685
|
+
- `err.kind` and `err.retryable` on `PathaoApiError` — see [Error kinds](#error-kinds)
|
|
686
|
+
- `toLifecycleStatus()` / `isFinalLifecycleStatus()` — see [Order lifecycle](#order-lifecycle)
|
|
687
|
+
- `minRequestIntervalMs` option — see [Rate limits](#rate-limits)
|
|
688
|
+
- `PathaoApiService.normalizePhoneNumber()`, `PATHAO_RATE_LIMIT_PER_MINUTE`, `PATHAO_STATUS_RETENTION_DAYS`
|
|
689
|
+
- `order_status` (optional) on order webhook payload types
|
|
690
|
+
- Debug logs no longer include token responses
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
586
694
|
## Contributing
|
|
587
695
|
|
|
588
696
|
Contributions are welcome. Please open an issue first for significant changes.
|
|
@@ -593,6 +701,8 @@ Contributions are welcome. Please open an issue first for significant changes.
|
|
|
593
701
|
|
|
594
702
|
## Development
|
|
595
703
|
|
|
704
|
+
The repo pins pnpm 10 via `packageManager`. Run `corepack enable` once so `pnpm` uses it; pnpm 11+ ignores the `pnpm` settings in `package.json` and `pnpm install --frozen-lockfile` fails.
|
|
705
|
+
|
|
596
706
|
```bash
|
|
597
707
|
pnpm install
|
|
598
708
|
pnpm run build # compile CJS + ESM + .d.ts
|
|
@@ -613,6 +723,18 @@ Open an issue on [GitHub](https://github.com/sifat07/pathao-merchant-sdk/issues)
|
|
|
613
723
|
|
|
614
724
|
## Changelog
|
|
615
725
|
|
|
726
|
+
Full history: [CHANGELOG.md](CHANGELOG.md).
|
|
727
|
+
|
|
728
|
+
### 3.0.0
|
|
729
|
+
|
|
730
|
+
- **Breaking:** explicit config no longer falls back to `PATHAO_*` env vars; use `fromEnv()` — see [Upgrading to 3.0.0](#upgrading-to-300)
|
|
731
|
+
- Order and store creation are never auto-retried on `5xx` (prevents duplicate consignments)
|
|
732
|
+
- Debug logs redact token responses; redirects are never followed
|
|
733
|
+
- Webhooks: unknown event names go to `'unknown'`, never to reserved EventEmitter events
|
|
734
|
+
- Phones normalised (`+880…` accepted); orders fully validated before sending
|
|
735
|
+
- `PathaoApiError.kind` / `.retryable`, `toLifecycleStatus()`, `minRequestIntervalMs`, rate/retention constants
|
|
736
|
+
- Correct ESM types; `/webhooks` resolves under `node10`; CI on pnpm 10 and Node 18–24
|
|
737
|
+
|
|
616
738
|
### 2.3.0 — 2026-04-16
|
|
617
739
|
|
|
618
740
|
- Replaced broken `pnpm audit` with OSV Scanner (scoped to production dependencies)
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
export { P as PATHAO_RATE_LIMIT_PER_MINUTE, a as PATHAO_STATUS_RETENTION_DAYS, b as PathaoLifecycleStatus, i as isFinalLifecycleStatus, t as toLifecycleStatus } from './status-xIApOisZ.mjs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Pathao Courier API Types
|
|
3
5
|
*
|
|
4
6
|
* Official API Details:
|
|
5
7
|
* - Authentication: OAuth2 with client_id, client_secret, username, password
|
|
6
8
|
* - All endpoints use /aladdin/api/v1/ prefix
|
|
7
|
-
* -
|
|
8
|
-
* - Timeout can be set via PATHAO_TIMEOUT environment variable or constructor config
|
|
9
|
+
* - Config is passed explicitly, or read from PATHAO_* env vars by fromEnv()
|
|
9
10
|
*/
|
|
10
11
|
interface PathaoAuthResponse {
|
|
11
12
|
token_type: string;
|
|
@@ -206,8 +207,8 @@ interface PathaoBulkOrderResponse {
|
|
|
206
207
|
* API Details (based on public documentation):
|
|
207
208
|
* - Authentication: OAuth2 with client_id, client_secret, username, password
|
|
208
209
|
* - All endpoints use /aladdin/api/v1/ prefix
|
|
209
|
-
* -
|
|
210
|
-
*
|
|
210
|
+
* - The constructor reads only the config it is given. Use fromEnv() to read
|
|
211
|
+
* PATHAO_* environment variables (including PATHAO_TIMEOUT).
|
|
211
212
|
*
|
|
212
213
|
* Features implemented:
|
|
213
214
|
* - Token-based authentication with refresh token support
|
|
@@ -218,7 +219,28 @@ interface PathaoBulkOrderResponse {
|
|
|
218
219
|
* - City, zone, and area management
|
|
219
220
|
*/
|
|
220
221
|
|
|
222
|
+
type PathaoErrorKind =
|
|
223
|
+
/** Input rejected, by this SDK before sending or by Pathao (HTTP 400/422). */
|
|
224
|
+
'validation'
|
|
225
|
+
/** Missing or wrong baseURL / credentials, caught before any request. */
|
|
226
|
+
| 'config'
|
|
227
|
+
/** Rejected credentials or token (HTTP 401). */
|
|
228
|
+
| 'auth'
|
|
229
|
+
/**
|
|
230
|
+
* The account may not do this right now: HTTP 403, or 402 when Pathao
|
|
231
|
+
* refuses new orders until the merchant pays outstanding dues.
|
|
232
|
+
*/
|
|
233
|
+
| 'forbidden'
|
|
234
|
+
/** Unknown consignment, store or resource (HTTP 404). */
|
|
235
|
+
| 'not_found'
|
|
236
|
+
/** HTTP 429. Back off; see PATHAO_RATE_LIMIT_PER_MINUTE. */
|
|
237
|
+
| 'rate_limited'
|
|
238
|
+
/** 5xx, timeout, network failure or open circuit breaker. */
|
|
239
|
+
| 'unavailable'
|
|
240
|
+
/** A response this SDK doesn't understand. Inspect `responseData`. */
|
|
241
|
+
| 'unexpected';
|
|
221
242
|
declare class PathaoApiError extends Error {
|
|
243
|
+
kind: PathaoErrorKind;
|
|
222
244
|
status: number | undefined;
|
|
223
245
|
code: number | undefined;
|
|
224
246
|
type: string | undefined;
|
|
@@ -232,12 +254,31 @@ declare class PathaoApiError extends Error {
|
|
|
232
254
|
errors?: Record<string, string[]> | undefined;
|
|
233
255
|
validation?: Record<string, string[]> | undefined;
|
|
234
256
|
responseData?: unknown;
|
|
257
|
+
kind?: PathaoErrorKind | undefined;
|
|
235
258
|
});
|
|
259
|
+
/**
|
|
260
|
+
* True for transient failures (`unavailable`, `rate_limited`). For
|
|
261
|
+
* createOrder / createBulkOrder a 5xx may hide a booking that went through:
|
|
262
|
+
* look the order up before retrying a create.
|
|
263
|
+
*/
|
|
264
|
+
get retryable(): boolean;
|
|
236
265
|
}
|
|
237
266
|
interface CircuitBreakerConfig {
|
|
238
267
|
threshold?: number;
|
|
239
268
|
timeout?: number;
|
|
240
269
|
}
|
|
270
|
+
interface PathaoClientOptions {
|
|
271
|
+
/** Log requests and responses (tokens and Authorization redacted). */
|
|
272
|
+
debug?: boolean;
|
|
273
|
+
circuitBreaker?: CircuitBreakerConfig;
|
|
274
|
+
/**
|
|
275
|
+
* Minimum gap between requests from this instance, in ms. Requests queue
|
|
276
|
+
* instead of tripping Pathao's 60/min limit (PATHAO_RATE_LIMIT_PER_MINUTE).
|
|
277
|
+
* 1500 keeps one instance near 40/min, leaving headroom for other callers
|
|
278
|
+
* sharing the credentials. Default 0 (no spacing).
|
|
279
|
+
*/
|
|
280
|
+
minRequestIntervalMs?: number;
|
|
281
|
+
}
|
|
241
282
|
declare class PathaoApiService {
|
|
242
283
|
private pathaoClient;
|
|
243
284
|
private accessToken;
|
|
@@ -248,11 +289,10 @@ declare class PathaoApiService {
|
|
|
248
289
|
private authPromise;
|
|
249
290
|
private hasValidated;
|
|
250
291
|
private debug;
|
|
292
|
+
private minRequestIntervalMs;
|
|
293
|
+
private nextRequestAt;
|
|
251
294
|
private circuitBreaker;
|
|
252
|
-
constructor(config: PathaoConfig, options?:
|
|
253
|
-
debug?: boolean;
|
|
254
|
-
circuitBreaker?: CircuitBreakerConfig;
|
|
255
|
-
});
|
|
295
|
+
constructor(config: PathaoConfig, options?: PathaoClientOptions);
|
|
256
296
|
private validateConfiguration;
|
|
257
297
|
private ensureAuthenticated;
|
|
258
298
|
private performAuthentication;
|
|
@@ -261,6 +301,7 @@ declare class PathaoApiService {
|
|
|
261
301
|
private getErrorMessage;
|
|
262
302
|
private toPathaoApiError;
|
|
263
303
|
private handleCircuitBreaker;
|
|
304
|
+
private waitForRequestSlot;
|
|
264
305
|
private delay;
|
|
265
306
|
createOrder(orderData: PathaoOrderRequest): Promise<PathaoOrderResponse>;
|
|
266
307
|
createStore(storeData: PathaoStoreRequest): Promise<PathaoStoreCreateResponse>;
|
|
@@ -272,6 +313,13 @@ declare class PathaoApiService {
|
|
|
272
313
|
getAreas(zoneId: number): Promise<PathaoAreaResponse>;
|
|
273
314
|
getOrderStatus(consignmentId: string): Promise<PathaoOrderStatusResponse>;
|
|
274
315
|
createBulkOrder(orders: PathaoOrderRequest[]): Promise<PathaoBulkOrderResponse>;
|
|
316
|
+
private static prepareOrder;
|
|
317
|
+
/**
|
|
318
|
+
* Normalise a Bangladeshi mobile number to 01XXXXXXXXX. Accepts +8801…,
|
|
319
|
+
* 8801… and 01…, with spaces, dashes, dots or parentheses. Returns null for
|
|
320
|
+
* anything that isn't a BD mobile number (operator prefixes 013–019).
|
|
321
|
+
*/
|
|
322
|
+
static normalizePhoneNumber(phone: string): string | null;
|
|
275
323
|
static validatePhoneNumber(phone: string): boolean;
|
|
276
324
|
static formatPhoneNumber(phone: string): string;
|
|
277
325
|
static validateAddress(address: string): boolean;
|
|
@@ -282,22 +330,10 @@ declare class PathaoApiService {
|
|
|
282
330
|
static validateContactNumber(phone: string): boolean;
|
|
283
331
|
static validateStoreAddress(address: string): boolean;
|
|
284
332
|
clearAuth(): void;
|
|
285
|
-
static fromEnv(options?:
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
static fromConfig(config: PathaoConfig, options?: {
|
|
290
|
-
debug?: boolean;
|
|
291
|
-
circuitBreaker?: CircuitBreakerConfig;
|
|
292
|
-
}): PathaoApiService;
|
|
293
|
-
static sandbox(credentials: Omit<PathaoConfig, 'baseURL'>, options?: {
|
|
294
|
-
debug?: boolean;
|
|
295
|
-
circuitBreaker?: CircuitBreakerConfig;
|
|
296
|
-
}): PathaoApiService;
|
|
297
|
-
static production(credentials: Omit<PathaoConfig, 'baseURL'>, options?: {
|
|
298
|
-
debug?: boolean;
|
|
299
|
-
circuitBreaker?: CircuitBreakerConfig;
|
|
300
|
-
}): PathaoApiService;
|
|
333
|
+
static fromEnv(options?: PathaoClientOptions): PathaoApiService;
|
|
334
|
+
static fromConfig(config: PathaoConfig, options?: PathaoClientOptions): PathaoApiService;
|
|
335
|
+
static sandbox(credentials: Omit<PathaoConfig, 'baseURL'>, options?: PathaoClientOptions): PathaoApiService;
|
|
336
|
+
static production(credentials: Omit<PathaoConfig, 'baseURL'>, options?: PathaoClientOptions): PathaoApiService;
|
|
301
337
|
}
|
|
302
338
|
|
|
303
|
-
export { type CircuitBreakerConfig, DeliveryType, ItemType, PathaoApiError, PathaoApiService, type PathaoAreaResponse, type PathaoAuthResponse, type PathaoBulkOrderResponse, 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 };
|
|
339
|
+
export { type CircuitBreakerConfig, DeliveryType, ItemType, PathaoApiError, PathaoApiService, type PathaoAreaResponse, type PathaoAuthResponse, type PathaoBulkOrderResponse, type PathaoCityResponse, type PathaoClientOptions, type PathaoConfig, type PathaoError, type PathaoErrorKind, 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
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
export { P as PATHAO_RATE_LIMIT_PER_MINUTE, a as PATHAO_STATUS_RETENTION_DAYS, b as PathaoLifecycleStatus, i as isFinalLifecycleStatus, t as toLifecycleStatus } from './status-xIApOisZ.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Pathao Courier API Types
|
|
3
5
|
*
|
|
4
6
|
* Official API Details:
|
|
5
7
|
* - Authentication: OAuth2 with client_id, client_secret, username, password
|
|
6
8
|
* - All endpoints use /aladdin/api/v1/ prefix
|
|
7
|
-
* -
|
|
8
|
-
* - Timeout can be set via PATHAO_TIMEOUT environment variable or constructor config
|
|
9
|
+
* - Config is passed explicitly, or read from PATHAO_* env vars by fromEnv()
|
|
9
10
|
*/
|
|
10
11
|
interface PathaoAuthResponse {
|
|
11
12
|
token_type: string;
|
|
@@ -206,8 +207,8 @@ interface PathaoBulkOrderResponse {
|
|
|
206
207
|
* API Details (based on public documentation):
|
|
207
208
|
* - Authentication: OAuth2 with client_id, client_secret, username, password
|
|
208
209
|
* - All endpoints use /aladdin/api/v1/ prefix
|
|
209
|
-
* -
|
|
210
|
-
*
|
|
210
|
+
* - The constructor reads only the config it is given. Use fromEnv() to read
|
|
211
|
+
* PATHAO_* environment variables (including PATHAO_TIMEOUT).
|
|
211
212
|
*
|
|
212
213
|
* Features implemented:
|
|
213
214
|
* - Token-based authentication with refresh token support
|
|
@@ -218,7 +219,28 @@ interface PathaoBulkOrderResponse {
|
|
|
218
219
|
* - City, zone, and area management
|
|
219
220
|
*/
|
|
220
221
|
|
|
222
|
+
type PathaoErrorKind =
|
|
223
|
+
/** Input rejected, by this SDK before sending or by Pathao (HTTP 400/422). */
|
|
224
|
+
'validation'
|
|
225
|
+
/** Missing or wrong baseURL / credentials, caught before any request. */
|
|
226
|
+
| 'config'
|
|
227
|
+
/** Rejected credentials or token (HTTP 401). */
|
|
228
|
+
| 'auth'
|
|
229
|
+
/**
|
|
230
|
+
* The account may not do this right now: HTTP 403, or 402 when Pathao
|
|
231
|
+
* refuses new orders until the merchant pays outstanding dues.
|
|
232
|
+
*/
|
|
233
|
+
| 'forbidden'
|
|
234
|
+
/** Unknown consignment, store or resource (HTTP 404). */
|
|
235
|
+
| 'not_found'
|
|
236
|
+
/** HTTP 429. Back off; see PATHAO_RATE_LIMIT_PER_MINUTE. */
|
|
237
|
+
| 'rate_limited'
|
|
238
|
+
/** 5xx, timeout, network failure or open circuit breaker. */
|
|
239
|
+
| 'unavailable'
|
|
240
|
+
/** A response this SDK doesn't understand. Inspect `responseData`. */
|
|
241
|
+
| 'unexpected';
|
|
221
242
|
declare class PathaoApiError extends Error {
|
|
243
|
+
kind: PathaoErrorKind;
|
|
222
244
|
status: number | undefined;
|
|
223
245
|
code: number | undefined;
|
|
224
246
|
type: string | undefined;
|
|
@@ -232,12 +254,31 @@ declare class PathaoApiError extends Error {
|
|
|
232
254
|
errors?: Record<string, string[]> | undefined;
|
|
233
255
|
validation?: Record<string, string[]> | undefined;
|
|
234
256
|
responseData?: unknown;
|
|
257
|
+
kind?: PathaoErrorKind | undefined;
|
|
235
258
|
});
|
|
259
|
+
/**
|
|
260
|
+
* True for transient failures (`unavailable`, `rate_limited`). For
|
|
261
|
+
* createOrder / createBulkOrder a 5xx may hide a booking that went through:
|
|
262
|
+
* look the order up before retrying a create.
|
|
263
|
+
*/
|
|
264
|
+
get retryable(): boolean;
|
|
236
265
|
}
|
|
237
266
|
interface CircuitBreakerConfig {
|
|
238
267
|
threshold?: number;
|
|
239
268
|
timeout?: number;
|
|
240
269
|
}
|
|
270
|
+
interface PathaoClientOptions {
|
|
271
|
+
/** Log requests and responses (tokens and Authorization redacted). */
|
|
272
|
+
debug?: boolean;
|
|
273
|
+
circuitBreaker?: CircuitBreakerConfig;
|
|
274
|
+
/**
|
|
275
|
+
* Minimum gap between requests from this instance, in ms. Requests queue
|
|
276
|
+
* instead of tripping Pathao's 60/min limit (PATHAO_RATE_LIMIT_PER_MINUTE).
|
|
277
|
+
* 1500 keeps one instance near 40/min, leaving headroom for other callers
|
|
278
|
+
* sharing the credentials. Default 0 (no spacing).
|
|
279
|
+
*/
|
|
280
|
+
minRequestIntervalMs?: number;
|
|
281
|
+
}
|
|
241
282
|
declare class PathaoApiService {
|
|
242
283
|
private pathaoClient;
|
|
243
284
|
private accessToken;
|
|
@@ -248,11 +289,10 @@ declare class PathaoApiService {
|
|
|
248
289
|
private authPromise;
|
|
249
290
|
private hasValidated;
|
|
250
291
|
private debug;
|
|
292
|
+
private minRequestIntervalMs;
|
|
293
|
+
private nextRequestAt;
|
|
251
294
|
private circuitBreaker;
|
|
252
|
-
constructor(config: PathaoConfig, options?:
|
|
253
|
-
debug?: boolean;
|
|
254
|
-
circuitBreaker?: CircuitBreakerConfig;
|
|
255
|
-
});
|
|
295
|
+
constructor(config: PathaoConfig, options?: PathaoClientOptions);
|
|
256
296
|
private validateConfiguration;
|
|
257
297
|
private ensureAuthenticated;
|
|
258
298
|
private performAuthentication;
|
|
@@ -261,6 +301,7 @@ declare class PathaoApiService {
|
|
|
261
301
|
private getErrorMessage;
|
|
262
302
|
private toPathaoApiError;
|
|
263
303
|
private handleCircuitBreaker;
|
|
304
|
+
private waitForRequestSlot;
|
|
264
305
|
private delay;
|
|
265
306
|
createOrder(orderData: PathaoOrderRequest): Promise<PathaoOrderResponse>;
|
|
266
307
|
createStore(storeData: PathaoStoreRequest): Promise<PathaoStoreCreateResponse>;
|
|
@@ -272,6 +313,13 @@ declare class PathaoApiService {
|
|
|
272
313
|
getAreas(zoneId: number): Promise<PathaoAreaResponse>;
|
|
273
314
|
getOrderStatus(consignmentId: string): Promise<PathaoOrderStatusResponse>;
|
|
274
315
|
createBulkOrder(orders: PathaoOrderRequest[]): Promise<PathaoBulkOrderResponse>;
|
|
316
|
+
private static prepareOrder;
|
|
317
|
+
/**
|
|
318
|
+
* Normalise a Bangladeshi mobile number to 01XXXXXXXXX. Accepts +8801…,
|
|
319
|
+
* 8801… and 01…, with spaces, dashes, dots or parentheses. Returns null for
|
|
320
|
+
* anything that isn't a BD mobile number (operator prefixes 013–019).
|
|
321
|
+
*/
|
|
322
|
+
static normalizePhoneNumber(phone: string): string | null;
|
|
275
323
|
static validatePhoneNumber(phone: string): boolean;
|
|
276
324
|
static formatPhoneNumber(phone: string): string;
|
|
277
325
|
static validateAddress(address: string): boolean;
|
|
@@ -282,22 +330,10 @@ declare class PathaoApiService {
|
|
|
282
330
|
static validateContactNumber(phone: string): boolean;
|
|
283
331
|
static validateStoreAddress(address: string): boolean;
|
|
284
332
|
clearAuth(): void;
|
|
285
|
-
static fromEnv(options?:
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
static fromConfig(config: PathaoConfig, options?: {
|
|
290
|
-
debug?: boolean;
|
|
291
|
-
circuitBreaker?: CircuitBreakerConfig;
|
|
292
|
-
}): PathaoApiService;
|
|
293
|
-
static sandbox(credentials: Omit<PathaoConfig, 'baseURL'>, options?: {
|
|
294
|
-
debug?: boolean;
|
|
295
|
-
circuitBreaker?: CircuitBreakerConfig;
|
|
296
|
-
}): PathaoApiService;
|
|
297
|
-
static production(credentials: Omit<PathaoConfig, 'baseURL'>, options?: {
|
|
298
|
-
debug?: boolean;
|
|
299
|
-
circuitBreaker?: CircuitBreakerConfig;
|
|
300
|
-
}): PathaoApiService;
|
|
333
|
+
static fromEnv(options?: PathaoClientOptions): PathaoApiService;
|
|
334
|
+
static fromConfig(config: PathaoConfig, options?: PathaoClientOptions): PathaoApiService;
|
|
335
|
+
static sandbox(credentials: Omit<PathaoConfig, 'baseURL'>, options?: PathaoClientOptions): PathaoApiService;
|
|
336
|
+
static production(credentials: Omit<PathaoConfig, 'baseURL'>, options?: PathaoClientOptions): PathaoApiService;
|
|
301
337
|
}
|
|
302
338
|
|
|
303
|
-
export { type CircuitBreakerConfig, DeliveryType, ItemType, PathaoApiError, PathaoApiService, type PathaoAreaResponse, type PathaoAuthResponse, type PathaoBulkOrderResponse, 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 };
|
|
339
|
+
export { type CircuitBreakerConfig, DeliveryType, ItemType, PathaoApiError, PathaoApiService, type PathaoAreaResponse, type PathaoAuthResponse, type PathaoBulkOrderResponse, type PathaoCityResponse, type PathaoClientOptions, type PathaoConfig, type PathaoError, type PathaoErrorKind, type PathaoOrderRequest, type PathaoOrderResponse, type PathaoOrderStatusResponse, type PathaoPriceRequest, type PathaoPriceResponse, type PathaoStore, type PathaoStoreCreateResponse, type PathaoStoreListResponse, type PathaoStoreRequest, type PathaoZoneResponse };
|