@lonca/trendyol 0.11.0 → 0.11.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/README.md +18 -33
- package/dist/{client-BZeFAlrp.d.cts → client-CCA1P7sb.d.cts} +4 -16
- package/dist/{client-BZeFAlrp.d.ts → client-CCA1P7sb.d.ts} +4 -16
- package/dist/index.cjs +16 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +17 -108
- package/dist/index.js.map +1 -1
- package/dist/testing.cjs +16 -107
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +17 -108
- package/dist/testing.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,35 +8,38 @@
|
|
|
8
8
|
|
|
9
9
|
Type-safe TypeScript SDK for the [Trendyol Marketplace API](https://developers.trendyol.com).
|
|
10
10
|
|
|
11
|
-
>
|
|
11
|
+
> [!IMPORTANT]
|
|
12
|
+
> **Unofficial.** This is an independent, community-maintained SDK. It is not affiliated with, endorsed by, or supported by Trendyol. "Trendyol" and related names are trademarks of their respective owners.
|
|
13
|
+
|
|
14
|
+
> **Trendyol surface complete.** 16 resources spanning catalog, orders, claims, finance, webhooks, and Export Center, plus a `parseWebhookEvent` helper for inbound event handling. Every endpoint a non-AutoFT non-V1 seller can hit is covered. See the [npm badge](https://www.npmjs.com/package/@lonca/trendyol) above for the current release.
|
|
12
15
|
|
|
13
16
|
## Coverage
|
|
14
17
|
|
|
15
|
-
Each entry is a method on the client.
|
|
18
|
+
Each entry is a method on the client.
|
|
16
19
|
|
|
17
20
|
| Resource | Methods |
|
|
18
21
|
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
-
| `brands` | `list()`, `search(name)`
|
|
20
|
-
| `categories` | `list()`, `getAttributes(id)`, `getAttributeValues(catId, attrId)
|
|
22
|
+
| `brands` | `list()`, `search(name)` |
|
|
23
|
+
| `categories` | `list()`, `getAttributes(id)`, `getAttributeValues(catId, attrId)`, `getByBarcodes(barcodes)` (AutoFT) |
|
|
21
24
|
| `suppliers` | `getAddresses({forceRefresh?})` (1-hour cache; rate-limited 1 req/hour on Trendyol) |
|
|
22
|
-
| `products` read | `list({...})`
|
|
23
|
-
| `products` write | `create(items)`, `updateContent(items)`, `updateVariants(items)`, `updateUnapproved(items)
|
|
25
|
+
| `products` read | `list({...})`, `listInventoryAndPrice({...})` (lightweight stock + price), `listUnapproved({...})`, `getBase(barcode)`, `getBuyboxInfo(barcodes)`, `getBatchStatus(id)` |
|
|
26
|
+
| `products` write | `create(items)`, `updateContent(items)`, `updateVariants(items)`, `updateUnapproved(items)`, `updateDeliveryInfo(items)` |
|
|
24
27
|
| `products` life | `delete(barcodes)`, `archive(barcodes)`, `unarchive(barcodes)`, `unlock(barcodes)` |
|
|
25
|
-
| `inventory` | `update(items)`
|
|
26
|
-
| `orders` read | `list({...})
|
|
28
|
+
| `inventory` | `update(items)` (stock + price, async batch) |
|
|
29
|
+
| `orders` read | `list({...})`, `listStream({...})` (opaque cursor for >10K), `getCargoInvoiceItems(serial, {...})` |
|
|
27
30
|
| `orders` write | `updatePackageStatus(id, {...})`, `cancelPackageItem(id, {...})`, `extendDeliveryDate(id, 1\|2\|3)`, `processAlternativeDelivery(id, {...})` |
|
|
28
31
|
| `orders` split | `splitPackage`, `splitPackageByQuantity`, `multiSplitPackage`, `splitMultiPackagesByQuantity` (4 variants) |
|
|
29
32
|
| `orders` cargo | `changeCargoProvider(id, code)`, `manualDeliverByPackageId(id)`, `manualDeliverByTrackingNumber(trk)`, `markDeliveredByService(id)` |
|
|
30
33
|
| `orders` ops | `updateBoxInfo(id, {...})`, `updateLaborCosts(id, items)`, `updateWarehouse(id, warehouseId)` |
|
|
31
34
|
| `orders` returns | `manualReturnByPackageId(id)`, `manualReturnByTrackingNumber(trk)`, `getCompensationTickets({...})` (TEX) |
|
|
32
|
-
| `claims` | `create({...})`, `createIssue(id, {...})` (multipart), `approveLineItems(id, {...})`, `list({...})`, `getIssueReasons()
|
|
35
|
+
| `claims` | `create({...})`, `createIssue(id, {...})` (multipart), `approveLineItems(id, {...})`, `list({...})`, `getIssueReasons()`, `getItemAudits(itemId)` |
|
|
33
36
|
| `webhooks` | `create({...})`, `list()`, `update(id, {...})`, `delete(id)`, `activate(id)`, `deactivate(id)` |
|
|
34
|
-
| `questions` | `get(id)`, `list({...})
|
|
37
|
+
| `questions` | `get(id)`, `list({...})`, `answer(id, text)` |
|
|
35
38
|
| `invoices` | `uploadFile({shipmentPackageId, file, ...})` (multipart), `sendLink({...})`, `deleteLink({...})` |
|
|
36
|
-
| `finance` | `getSettlements({...})`, `getOtherFinancials({...})` — both return typed `FinancialTransaction[]`
|
|
37
|
-
| `labels` | `createCommon(trackingNumber, {format: 'ZPL', ...})`, `getCommon(trackingNumber)`
|
|
39
|
+
| `finance` | `getSettlements({...})`, `getOtherFinancials({...})` — both return typed `FinancialTransaction[]` |
|
|
40
|
+
| `labels` | `createCommon(trackingNumber, {format: 'ZPL', ...})`, `getCommon(trackingNumber)` |
|
|
38
41
|
| `testOrders` | `create({...})`, `updateStatus(id, status)`, `setClaimsWaitingInAction()` — **STAGE-only utility** |
|
|
39
|
-
| `locations` | `getCountries()
|
|
42
|
+
| `locations` | `getCountries()`, `getTurkeyCities()`, `getTurkeyDistricts(cityCode)`, `getTurkeyNeighborhoods(cityCode, districtCode)`, `getAzerbaijanCities()`, `getAzerbaijanDistricts(...)`, `getCitiesByCountry/getDistrictsByCity(...)` |
|
|
40
43
|
| `exportCenter` | `listProducts({...})`, `createProducts(items)`, `updatePrices(items)`, `updateStocks(items)`, `getBatchStatus(batchId)`, `listPackagesV2/V3({...})`, `getPackageItems({packageId, ...})`, `getCategoryAttributes(id)`, `getCareInstructions()`, `getCompositions()`, `getOrigins()` — **Trendyol Export Center / İhracat Merkezi** |
|
|
41
44
|
| `videos` | `create({contentId, url, ...})`, `list({id?, sellerIntegrationStatus?, ...})` — product-page video upload + status |
|
|
42
45
|
| **top-level** | `parseWebhookEvent(rawBody)`, `normalizeShipmentPackage(rawNode)` — for inbound webhook handlers |
|
|
@@ -238,6 +241,7 @@ await client.suppliers.getAddresses({ forceRefresh: true });
|
|
|
238
241
|
|
|
239
242
|
// products — read
|
|
240
243
|
await client.products.list({ barcode: 'BC1' });
|
|
244
|
+
await client.products.listInventoryAndPrice({ status: 'onSale', limit: 100 }); // stock + price only
|
|
241
245
|
await client.products.listUnapproved({ limit: 50 });
|
|
242
246
|
await client.products.getBase('BC1');
|
|
243
247
|
await client.products.getBuyboxInfo(['BC1', 'BC2']); // max 10 per call
|
|
@@ -379,25 +383,6 @@ const status = await client.products.getBatchStatus(batchRequestId);
|
|
|
379
383
|
|
|
380
384
|
**Important:** Trendyol's overall batch `status` can lag at `PROCESSING` even after each `items[].status` has settled. Trust the per-item status, or re-read the affected products via `list({ barcode })` / `getBase(barcode)` to verify the change landed. Batch results are retained for **4 hours** on Trendyol's side.
|
|
381
385
|
|
|
382
|
-
## Discovery-first wire fixes
|
|
383
|
-
|
|
384
|
-
`@lonca/trendyol` was built by hitting the live Trendyol STAGE for every endpoint before writing types. Places where the official OpenAPI spec disagrees with the live wire are normalized automatically:
|
|
385
|
-
|
|
386
|
-
- `categories.getAttributeValues`: spec says `attributeValueName`, wire returns `attributeValue` → SDK normalizes to `{ id, name }`
|
|
387
|
-
- `products.listUnapproved`: spec says `media: [{url}]`, wire returns `images: [{url}]` → SDK exposes `images: string[]`
|
|
388
|
-
- `products.getBuyboxInfo`: wire returns extra `secondBuyboxPrice` / `thirdBuyboxPrice` fields beyond spec → both surfaced
|
|
389
|
-
- `products.updateUnapproved`: spec marks only `barcode` required, but live endpoint returns HTTP 500 (`TypeError`) when too many optional fields are omitted → documented in JSDoc
|
|
390
|
-
- `brands.search`: docs claim case-sensitive exact match, live is substring + case-insensitive → documented in JSDoc
|
|
391
|
-
- `getBatchRequestResult`: returns `PROCESSING + empty items` for unknown batch IDs (not 404)
|
|
392
|
-
- `orders.listStream` returns package ID as `id`, regular `orders.list` returns it as `shipmentPackageId` → normalizer accepts both
|
|
393
|
-
- `orders.updateLaborCosts`: body is a **raw array** (no `{ items: [...] }` envelope) — only endpoint in the surface that does this
|
|
394
|
-
- `getCompensationTickets`: spec says `{ data: { items: [] } }`, but SDK also accepts `{ data: [] }` and `{ content: [] }` defensively
|
|
395
|
-
- `labels.getCommon`: response is `{ data: [{ label, format }] }` → SDK surfaces `labels[]` for ergonomic access
|
|
396
|
-
- `finance.*`: both `getSettlements` and `getOtherFinancials` share the same `FinancialTransaction` wire schema → unified typed surface
|
|
397
|
-
- `webhooks.list`: SDK accepts 3 envelope shapes (`[]` raw, `{ webhooks: [] }`, `{ content: [] }`) and 3 active-flag spellings (`active`, `isActive`, `status: 'ACTIVE'`)
|
|
398
|
-
|
|
399
|
-
Each fix is pinned by a regression mock test using the exact STAGE shape.
|
|
400
|
-
|
|
401
386
|
## Authentication
|
|
402
387
|
|
|
403
388
|
Trendyol uses HTTP Basic Auth. Get your `sellerId`, `apiKey`, and `apiSecret` from the [Trendyol Partner Panel → Account Info → Integration Information](https://partner.trendyol.com/account/info?tab=integrationInformation) (master-user only).
|
|
@@ -413,7 +398,7 @@ Trendyol uses HTTP Basic Auth. Get your `sellerId`, `apiKey`, and `apiSecret` fr
|
|
|
413
398
|
|
|
414
399
|
## Built-in robustness
|
|
415
400
|
|
|
416
|
-
- **
|
|
401
|
+
- **Idempotency-aware retry with exponential backoff** — reads (`GET`) retry on 429 (honoring `Retry-After`), 5xx, and network/timeout errors. Writes (`POST`/`PUT`/`DELETE`) retry **only** on 429, which the server rejects before processing; ambiguous 5xx/network/timeout failures on a write are not replayed, so a transient error can't duplicate an order action or stock/price push. A `Retry-After: 0` no longer collapses backoff to an immediate retry.
|
|
417
402
|
- **Per-endpoint rate limiting** (token bucket) sized to Trendyol's documented limits — see defaults below; override per resource
|
|
418
403
|
- **Per-request correlation ID** — every call gets a UUID surfaced in log messages and the `x-correlationid` header for Trendyol-side log tracing
|
|
419
404
|
- **Structured errors** via `@lonca/core` (`AuthError`, `RateLimitError`, `NotFoundError`, `ServerError`, `ValidationError`, `NetworkError`, `TimeoutError`)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Logger, TokenBucketRateLimiter, CursorPaginationParams, CursorPage, OffsetPaginationParams } from '@lonca/core';
|
|
1
|
+
import { Logger, BaseRequestOptions, TokenBucketRateLimiter, CursorPaginationParams, CursorPage, OffsetPaginationParams } from '@lonca/core';
|
|
2
2
|
|
|
3
3
|
declare const BASE_URLS: {
|
|
4
4
|
readonly prod: "https://apigw.trendyol.com";
|
|
@@ -18,34 +18,22 @@ interface TransportConfig {
|
|
|
18
18
|
/** Override the underlying `fetch` (tests inject a mock). */
|
|
19
19
|
fetch?: typeof fetch;
|
|
20
20
|
}
|
|
21
|
-
interface RequestOptions {
|
|
21
|
+
interface RequestOptions extends BaseRequestOptions {
|
|
22
22
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
23
23
|
/** Path beginning with `/` (e.g., `/sapigw/brands`). */
|
|
24
24
|
path: string;
|
|
25
25
|
query?: Record<string, string | number | boolean | undefined>;
|
|
26
|
-
body?: unknown;
|
|
27
|
-
signal?: AbortSignal;
|
|
28
|
-
/**
|
|
29
|
-
* Extra per-request headers merged over the default header set (caller
|
|
30
|
-
* headers win). Used for endpoint-specific headers like `storeFrontCode`.
|
|
31
|
-
*/
|
|
32
|
-
headers?: Record<string, string>;
|
|
33
|
-
/** Per-endpoint rate limiter; acquire one token before each attempt. */
|
|
34
|
-
rateLimiter?: TokenBucketRateLimiter;
|
|
35
26
|
}
|
|
36
27
|
declare class TrendyolTransport {
|
|
37
28
|
private readonly config;
|
|
38
29
|
private readonly baseUrl;
|
|
39
|
-
private readonly
|
|
40
|
-
private readonly timeoutMs;
|
|
41
|
-
private readonly fetchImpl;
|
|
30
|
+
private readonly requester;
|
|
42
31
|
constructor(config: TransportConfig);
|
|
43
32
|
/** Seller ID this transport is configured with. Resources read it for path-building. */
|
|
44
33
|
get sellerId(): number;
|
|
45
34
|
request<T>(opts: RequestOptions): Promise<T>;
|
|
46
35
|
private buildUrl;
|
|
47
36
|
private buildHeaders;
|
|
48
|
-
private composeSignal;
|
|
49
37
|
}
|
|
50
38
|
|
|
51
39
|
/**
|
|
@@ -89,7 +77,7 @@ declare class BrandsResource {
|
|
|
89
77
|
* `createProducts` and don't want to page through the full `list()`
|
|
90
78
|
* (1000 brands per page).
|
|
91
79
|
*
|
|
92
|
-
* **
|
|
80
|
+
* **Wire fact (verified STAGE 2026-05-25):** Trendyol's
|
|
93
81
|
* doc claims this is a case-sensitive *exact* match, but live behaviour
|
|
94
82
|
* is **substring + case-insensitive** — `search('Trendyol')` returns
|
|
95
83
|
* 17 hits including `TRENDYOLMILLA`, `trendyol vavist`, `Trendyol Üyelik`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Logger, TokenBucketRateLimiter, CursorPaginationParams, CursorPage, OffsetPaginationParams } from '@lonca/core';
|
|
1
|
+
import { Logger, BaseRequestOptions, TokenBucketRateLimiter, CursorPaginationParams, CursorPage, OffsetPaginationParams } from '@lonca/core';
|
|
2
2
|
|
|
3
3
|
declare const BASE_URLS: {
|
|
4
4
|
readonly prod: "https://apigw.trendyol.com";
|
|
@@ -18,34 +18,22 @@ interface TransportConfig {
|
|
|
18
18
|
/** Override the underlying `fetch` (tests inject a mock). */
|
|
19
19
|
fetch?: typeof fetch;
|
|
20
20
|
}
|
|
21
|
-
interface RequestOptions {
|
|
21
|
+
interface RequestOptions extends BaseRequestOptions {
|
|
22
22
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
23
23
|
/** Path beginning with `/` (e.g., `/sapigw/brands`). */
|
|
24
24
|
path: string;
|
|
25
25
|
query?: Record<string, string | number | boolean | undefined>;
|
|
26
|
-
body?: unknown;
|
|
27
|
-
signal?: AbortSignal;
|
|
28
|
-
/**
|
|
29
|
-
* Extra per-request headers merged over the default header set (caller
|
|
30
|
-
* headers win). Used for endpoint-specific headers like `storeFrontCode`.
|
|
31
|
-
*/
|
|
32
|
-
headers?: Record<string, string>;
|
|
33
|
-
/** Per-endpoint rate limiter; acquire one token before each attempt. */
|
|
34
|
-
rateLimiter?: TokenBucketRateLimiter;
|
|
35
26
|
}
|
|
36
27
|
declare class TrendyolTransport {
|
|
37
28
|
private readonly config;
|
|
38
29
|
private readonly baseUrl;
|
|
39
|
-
private readonly
|
|
40
|
-
private readonly timeoutMs;
|
|
41
|
-
private readonly fetchImpl;
|
|
30
|
+
private readonly requester;
|
|
42
31
|
constructor(config: TransportConfig);
|
|
43
32
|
/** Seller ID this transport is configured with. Resources read it for path-building. */
|
|
44
33
|
get sellerId(): number;
|
|
45
34
|
request<T>(opts: RequestOptions): Promise<T>;
|
|
46
35
|
private buildUrl;
|
|
47
36
|
private buildHeaders;
|
|
48
|
-
private composeSignal;
|
|
49
37
|
}
|
|
50
38
|
|
|
51
39
|
/**
|
|
@@ -89,7 +77,7 @@ declare class BrandsResource {
|
|
|
89
77
|
* `createProducts` and don't want to page through the full `list()`
|
|
90
78
|
* (1000 brands per page).
|
|
91
79
|
*
|
|
92
|
-
* **
|
|
80
|
+
* **Wire fact (verified STAGE 2026-05-25):** Trendyol's
|
|
93
81
|
* doc claims this is a case-sensitive *exact* match, but live behaviour
|
|
94
82
|
* is **substring + case-insensitive** — `search('Trendyol')` returns
|
|
95
83
|
* 17 hits including `TRENDYOLMILLA`, `trendyol vavist`, `Trendyol Üyelik`.
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var core = require('@lonca/core');
|
|
4
|
-
var crypto = require('crypto');
|
|
5
4
|
|
|
6
5
|
// src/resources/brands.ts
|
|
7
6
|
var DEFAULT_PAGE_SIZE = 1e3;
|
|
@@ -41,7 +40,7 @@ var BrandsResource = class {
|
|
|
41
40
|
* `createProducts` and don't want to page through the full `list()`
|
|
42
41
|
* (1000 brands per page).
|
|
43
42
|
*
|
|
44
|
-
* **
|
|
43
|
+
* **Wire fact (verified STAGE 2026-05-25):** Trendyol's
|
|
45
44
|
* doc claims this is a case-sensitive *exact* match, but live behaviour
|
|
46
45
|
* is **substring + case-insensitive** — `search('Trendyol')` returns
|
|
47
46
|
* 17 hits including `TRENDYOLMILLA`, `trendyol vavist`, `Trendyol Üyelik`.
|
|
@@ -1262,7 +1261,8 @@ var OrdersResource = class {
|
|
|
1262
1261
|
const items = (data.content ?? []).map(normalizePackage2);
|
|
1263
1262
|
const totalPages = typeof data.totalPages === "number" ? data.totalPages : 0;
|
|
1264
1263
|
const result = { items };
|
|
1265
|
-
|
|
1264
|
+
const nextPageWithinCap = (page + 2) * size <= MAX_OFFSET_RECORDS;
|
|
1265
|
+
if (page + 1 < totalPages && nextPageWithinCap) {
|
|
1266
1266
|
result.nextCursor = String(page + 1);
|
|
1267
1267
|
}
|
|
1268
1268
|
return result;
|
|
@@ -2784,14 +2784,6 @@ function extractErrorsArray(body) {
|
|
|
2784
2784
|
}
|
|
2785
2785
|
return void 0;
|
|
2786
2786
|
}
|
|
2787
|
-
function parseRetryAfter(header) {
|
|
2788
|
-
if (!header) return void 0;
|
|
2789
|
-
const seconds = Number(header);
|
|
2790
|
-
if (!Number.isNaN(seconds)) return Math.max(0, seconds * 1e3);
|
|
2791
|
-
const epoch = Date.parse(header);
|
|
2792
|
-
if (!Number.isNaN(epoch)) return Math.max(0, epoch - Date.now());
|
|
2793
|
-
return void 0;
|
|
2794
|
-
}
|
|
2795
2787
|
|
|
2796
2788
|
// src/transport.ts
|
|
2797
2789
|
var BASE_URLS = {
|
|
@@ -2802,95 +2794,26 @@ var TrendyolTransport = class {
|
|
|
2802
2794
|
constructor(config) {
|
|
2803
2795
|
this.config = config;
|
|
2804
2796
|
this.baseUrl = BASE_URLS[config.env];
|
|
2805
|
-
this.
|
|
2806
|
-
|
|
2807
|
-
|
|
2797
|
+
this.requester = core.createRequester({
|
|
2798
|
+
fetch: config.fetch ?? fetch,
|
|
2799
|
+
logger: config.logger,
|
|
2800
|
+
timeoutMs: config.timeoutMs ?? 3e4,
|
|
2801
|
+
label: "Trendyol",
|
|
2802
|
+
logPrefix: "trendyol",
|
|
2803
|
+
buildUrl: (opts) => this.buildUrl(opts.path, opts.query),
|
|
2804
|
+
buildHeaders: (correlationId) => this.buildHeaders(correlationId),
|
|
2805
|
+
mapHttpError
|
|
2806
|
+
});
|
|
2808
2807
|
}
|
|
2809
2808
|
config;
|
|
2810
2809
|
baseUrl;
|
|
2811
|
-
|
|
2812
|
-
timeoutMs;
|
|
2813
|
-
fetchImpl;
|
|
2810
|
+
requester;
|
|
2814
2811
|
/** Seller ID this transport is configured with. Resources read it for path-building. */
|
|
2815
2812
|
get sellerId() {
|
|
2816
2813
|
return this.config.sellerId;
|
|
2817
2814
|
}
|
|
2818
|
-
|
|
2819
|
-
return
|
|
2820
|
-
async (attempt) => {
|
|
2821
|
-
if (opts.rateLimiter) await opts.rateLimiter.acquire(opts.signal);
|
|
2822
|
-
const url = this.buildUrl(opts.path, opts.query);
|
|
2823
|
-
const correlationId = crypto.randomUUID();
|
|
2824
|
-
const headers = { ...this.buildHeaders(correlationId), ...opts.headers };
|
|
2825
|
-
const init = {
|
|
2826
|
-
method: opts.method,
|
|
2827
|
-
headers,
|
|
2828
|
-
signal: this.composeSignal(opts.signal)
|
|
2829
|
-
};
|
|
2830
|
-
if (opts.body !== void 0 && opts.method !== "GET") {
|
|
2831
|
-
if (opts.body instanceof FormData) {
|
|
2832
|
-
init.body = opts.body;
|
|
2833
|
-
delete headers["Content-Type"];
|
|
2834
|
-
} else {
|
|
2835
|
-
init.body = JSON.stringify(opts.body);
|
|
2836
|
-
}
|
|
2837
|
-
}
|
|
2838
|
-
this.logger.debug("trendyol.request", {
|
|
2839
|
-
method: opts.method,
|
|
2840
|
-
url,
|
|
2841
|
-
correlationId,
|
|
2842
|
-
attempt
|
|
2843
|
-
});
|
|
2844
|
-
let response;
|
|
2845
|
-
try {
|
|
2846
|
-
response = await this.fetchImpl(url, init);
|
|
2847
|
-
} catch (err) {
|
|
2848
|
-
if (err instanceof Error && err.name === "AbortError") {
|
|
2849
|
-
throw new core.TimeoutError({
|
|
2850
|
-
message: `Trendyol request timed out after ${this.timeoutMs}ms`,
|
|
2851
|
-
cause: err
|
|
2852
|
-
});
|
|
2853
|
-
}
|
|
2854
|
-
throw new core.NetworkError({
|
|
2855
|
-
message: "Trendyol network failure",
|
|
2856
|
-
cause: err
|
|
2857
|
-
});
|
|
2858
|
-
}
|
|
2859
|
-
if (!response.ok) {
|
|
2860
|
-
const body = await safeJson(response);
|
|
2861
|
-
const retryAfterMs = parseRetryAfter(response.headers.get("retry-after"));
|
|
2862
|
-
const error = mapHttpError(response.status, body, retryAfterMs);
|
|
2863
|
-
this.logger.warn("trendyol.error", {
|
|
2864
|
-
method: opts.method,
|
|
2865
|
-
url,
|
|
2866
|
-
correlationId,
|
|
2867
|
-
status: response.status,
|
|
2868
|
-
code: error.code,
|
|
2869
|
-
retryable: error.retryable
|
|
2870
|
-
});
|
|
2871
|
-
throw error;
|
|
2872
|
-
}
|
|
2873
|
-
this.logger.debug("trendyol.response", {
|
|
2874
|
-
correlationId,
|
|
2875
|
-
status: response.status
|
|
2876
|
-
});
|
|
2877
|
-
if (response.status === 204) return void 0;
|
|
2878
|
-
return await safeJson(response);
|
|
2879
|
-
},
|
|
2880
|
-
{
|
|
2881
|
-
signal: opts.signal,
|
|
2882
|
-
onRetry: (err, attempt, delay2) => {
|
|
2883
|
-
if (err instanceof core.LoncaError) {
|
|
2884
|
-
this.logger.warn("trendyol.retry", {
|
|
2885
|
-
attempt,
|
|
2886
|
-
delayMs: delay2,
|
|
2887
|
-
code: err.code,
|
|
2888
|
-
status: err.status
|
|
2889
|
-
});
|
|
2890
|
-
}
|
|
2891
|
-
}
|
|
2892
|
-
}
|
|
2893
|
-
);
|
|
2815
|
+
request(opts) {
|
|
2816
|
+
return this.requester(opts);
|
|
2894
2817
|
}
|
|
2895
2818
|
buildUrl(path, query) {
|
|
2896
2819
|
const url = new URL(path, this.baseUrl);
|
|
@@ -2913,21 +2836,7 @@ var TrendyolTransport = class {
|
|
|
2913
2836
|
Accept: "application/json"
|
|
2914
2837
|
};
|
|
2915
2838
|
}
|
|
2916
|
-
composeSignal(external) {
|
|
2917
|
-
const timeoutSignal = AbortSignal.timeout(this.timeoutMs);
|
|
2918
|
-
if (!external) return timeoutSignal;
|
|
2919
|
-
return AbortSignal.any([external, timeoutSignal]);
|
|
2920
|
-
}
|
|
2921
2839
|
};
|
|
2922
|
-
async function safeJson(response) {
|
|
2923
|
-
const text = await response.text();
|
|
2924
|
-
if (!text) return void 0;
|
|
2925
|
-
try {
|
|
2926
|
-
return JSON.parse(text);
|
|
2927
|
-
} catch {
|
|
2928
|
-
return text;
|
|
2929
|
-
}
|
|
2930
|
-
}
|
|
2931
2840
|
|
|
2932
2841
|
// src/client.ts
|
|
2933
2842
|
function createTrendyolClient(opts) {
|