@hubcommerce/trendyol 1.0.0

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.
Files changed (235) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/LICENSE +21 -0
  3. package/README.md +257 -0
  4. package/dist/batch/poller.d.ts +23 -0
  5. package/dist/batch/poller.d.ts.map +1 -0
  6. package/dist/batch/poller.js +85 -0
  7. package/dist/batch/report.d.ts +15 -0
  8. package/dist/batch/report.d.ts.map +1 -0
  9. package/dist/batch/report.js +41 -0
  10. package/dist/batch/types.d.ts +4 -0
  11. package/dist/batch/types.d.ts.map +1 -0
  12. package/dist/batch/types.js +2 -0
  13. package/dist/claims/api.d.ts +48 -0
  14. package/dist/claims/api.d.ts.map +1 -0
  15. package/dist/claims/api.js +116 -0
  16. package/dist/claims/form.d.ts +9 -0
  17. package/dist/claims/form.d.ts.map +1 -0
  18. package/dist/claims/form.js +20 -0
  19. package/dist/claims/paths.d.ts +3 -0
  20. package/dist/claims/paths.d.ts.map +1 -0
  21. package/dist/claims/paths.js +8 -0
  22. package/dist/client.d.ts +39 -0
  23. package/dist/client.d.ts.map +1 -0
  24. package/dist/client.js +66 -0
  25. package/dist/compensation/api.d.ts +17 -0
  26. package/dist/compensation/api.d.ts.map +1 -0
  27. package/dist/compensation/api.js +37 -0
  28. package/dist/compensation/paths.d.ts +2 -0
  29. package/dist/compensation/paths.d.ts.map +1 -0
  30. package/dist/compensation/paths.js +4 -0
  31. package/dist/config.d.ts +10 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +78 -0
  34. package/dist/connection.d.ts +4 -0
  35. package/dist/connection.d.ts.map +1 -0
  36. package/dist/connection.js +8 -0
  37. package/dist/constants/claim-reasons.d.ts +10 -0
  38. package/dist/constants/claim-reasons.d.ts.map +1 -0
  39. package/dist/constants/claim-reasons.js +43 -0
  40. package/dist/constants/error-codes.d.ts +3 -0
  41. package/dist/constants/error-codes.d.ts.map +1 -0
  42. package/dist/constants/error-codes.js +9 -0
  43. package/dist/constants/origins.d.ts +6 -0
  44. package/dist/constants/origins.d.ts.map +1 -0
  45. package/dist/constants/origins.js +6 -0
  46. package/dist/constants/package-status.d.ts +3 -0
  47. package/dist/constants/package-status.d.ts.map +1 -0
  48. package/dist/constants/package-status.js +15 -0
  49. package/dist/constants/page-limits.d.ts +3 -0
  50. package/dist/constants/page-limits.d.ts.map +1 -0
  51. package/dist/constants/page-limits.js +9 -0
  52. package/dist/constants.d.ts +18 -0
  53. package/dist/constants.d.ts.map +1 -0
  54. package/dist/constants.js +17 -0
  55. package/dist/errors.d.ts +27 -0
  56. package/dist/errors.d.ts.map +1 -0
  57. package/dist/errors.js +113 -0
  58. package/dist/finance/api.d.ts +39 -0
  59. package/dist/finance/api.d.ts.map +1 -0
  60. package/dist/finance/api.js +165 -0
  61. package/dist/finance/paths.d.ts +6 -0
  62. package/dist/finance/paths.d.ts.map +1 -0
  63. package/dist/finance/paths.js +16 -0
  64. package/dist/http/multipart.d.ts +10 -0
  65. package/dist/http/multipart.d.ts.map +1 -0
  66. package/dist/http/multipart.js +1 -0
  67. package/dist/http/query.d.ts +5 -0
  68. package/dist/http/query.d.ts.map +1 -0
  69. package/dist/http/query.js +24 -0
  70. package/dist/http/response.d.ts +9 -0
  71. package/dist/http/response.d.ts.map +1 -0
  72. package/dist/http/response.js +37 -0
  73. package/dist/http/signals.d.ts +5 -0
  74. package/dist/http/signals.d.ts.map +1 -0
  75. package/dist/http/signals.js +26 -0
  76. package/dist/http.d.ts +14 -0
  77. package/dist/http.d.ts.map +1 -0
  78. package/dist/http.js +180 -0
  79. package/dist/index.d.ts +61 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +41 -0
  82. package/dist/inventory/api.d.ts +26 -0
  83. package/dist/inventory/api.d.ts.map +1 -0
  84. package/dist/inventory/api.js +51 -0
  85. package/dist/inventory/paths.d.ts +2 -0
  86. package/dist/inventory/paths.d.ts.map +1 -0
  87. package/dist/inventory/paths.js +4 -0
  88. package/dist/invoices/api.d.ts +23 -0
  89. package/dist/invoices/api.d.ts.map +1 -0
  90. package/dist/invoices/api.js +52 -0
  91. package/dist/labels/api.d.ts +45 -0
  92. package/dist/labels/api.d.ts.map +1 -0
  93. package/dist/labels/api.js +89 -0
  94. package/dist/labels/paths.d.ts +3 -0
  95. package/dist/labels/paths.d.ts.map +1 -0
  96. package/dist/labels/paths.js +7 -0
  97. package/dist/logger.d.ts +6 -0
  98. package/dist/logger.d.ts.map +1 -0
  99. package/dist/logger.js +47 -0
  100. package/dist/orders/api.d.ts +68 -0
  101. package/dist/orders/api.d.ts.map +1 -0
  102. package/dist/orders/api.js +69 -0
  103. package/dist/orders/created-by.d.ts +4 -0
  104. package/dist/orders/created-by.d.ts.map +1 -0
  105. package/dist/orders/created-by.js +9 -0
  106. package/dist/orders/mutations.d.ts +31 -0
  107. package/dist/orders/mutations.d.ts.map +1 -0
  108. package/dist/orders/mutations.js +139 -0
  109. package/dist/orders/paths.d.ts +4 -0
  110. package/dist/orders/paths.d.ts.map +1 -0
  111. package/dist/orders/paths.js +12 -0
  112. package/dist/orders/read.d.ts +35 -0
  113. package/dist/orders/read.d.ts.map +1 -0
  114. package/dist/orders/read.js +140 -0
  115. package/dist/orders/split.d.ts +17 -0
  116. package/dist/orders/split.d.ts.map +1 -0
  117. package/dist/orders/split.js +45 -0
  118. package/dist/orders/status.d.ts +9 -0
  119. package/dist/orders/status.d.ts.map +1 -0
  120. package/dist/orders/status.js +20 -0
  121. package/dist/orders/stream.d.ts +19 -0
  122. package/dist/orders/stream.d.ts.map +1 -0
  123. package/dist/orders/stream.js +26 -0
  124. package/dist/orders/warranty.d.ts +24 -0
  125. package/dist/orders/warranty.d.ts.map +1 -0
  126. package/dist/orders/warranty.js +30 -0
  127. package/dist/pagination.d.ts +23 -0
  128. package/dist/pagination.d.ts.map +1 -0
  129. package/dist/pagination.js +34 -0
  130. package/dist/products/api.d.ts +52 -0
  131. package/dist/products/api.d.ts.map +1 -0
  132. package/dist/products/api.js +222 -0
  133. package/dist/products/builder.d.ts +22 -0
  134. package/dist/products/builder.d.ts.map +1 -0
  135. package/dist/products/builder.js +89 -0
  136. package/dist/products/paths.d.ts +7 -0
  137. package/dist/products/paths.d.ts.map +1 -0
  138. package/dist/products/paths.js +20 -0
  139. package/dist/qna/api.d.ts +32 -0
  140. package/dist/qna/api.d.ts.map +1 -0
  141. package/dist/qna/api.js +78 -0
  142. package/dist/qna/paths.d.ts +5 -0
  143. package/dist/qna/paths.d.ts.map +1 -0
  144. package/dist/qna/paths.js +13 -0
  145. package/dist/rate-limit/governor.d.ts +11 -0
  146. package/dist/rate-limit/governor.d.ts.map +1 -0
  147. package/dist/rate-limit/governor.js +25 -0
  148. package/dist/rate-limit/groups.d.ts +15 -0
  149. package/dist/rate-limit/groups.d.ts.map +1 -0
  150. package/dist/rate-limit/groups.js +14 -0
  151. package/dist/reference/addresses-cache.d.ts +13 -0
  152. package/dist/reference/addresses-cache.d.ts.map +1 -0
  153. package/dist/reference/addresses-cache.js +33 -0
  154. package/dist/reference/api.d.ts +48 -0
  155. package/dist/reference/api.d.ts.map +1 -0
  156. package/dist/reference/api.js +215 -0
  157. package/dist/reference/paths.d.ts +12 -0
  158. package/dist/reference/paths.d.ts.map +1 -0
  159. package/dist/reference/paths.js +34 -0
  160. package/dist/retry.d.ts +6 -0
  161. package/dist/retry.d.ts.map +1 -0
  162. package/dist/retry.js +37 -0
  163. package/dist/testing/fixtures/batch-partial-fail.json +12 -0
  164. package/dist/testing/fixtures/shipment-package.json +5 -0
  165. package/dist/testing/fixtures/webhook-payload.json +4 -0
  166. package/dist/testing/fixtures.d.ts +23 -0
  167. package/dist/testing/fixtures.d.ts.map +1 -0
  168. package/dist/testing/fixtures.js +9 -0
  169. package/dist/testing/guard.d.ts +13 -0
  170. package/dist/testing/guard.d.ts.map +1 -0
  171. package/dist/testing/guard.js +32 -0
  172. package/dist/testing/index.d.ts +6 -0
  173. package/dist/testing/index.d.ts.map +1 -0
  174. package/dist/testing/index.js +4 -0
  175. package/dist/testing/paths.d.ts +5 -0
  176. package/dist/testing/paths.d.ts.map +1 -0
  177. package/dist/testing/paths.js +14 -0
  178. package/dist/testing/stage-helpers.d.ts +24 -0
  179. package/dist/testing/stage-helpers.d.ts.map +1 -0
  180. package/dist/testing/stage-helpers.js +64 -0
  181. package/dist/testing/types.d.ts +66 -0
  182. package/dist/testing/types.d.ts.map +1 -0
  183. package/dist/testing/types.js +1 -0
  184. package/dist/types/claims.d.ts +132 -0
  185. package/dist/types/claims.d.ts.map +1 -0
  186. package/dist/types/claims.js +1 -0
  187. package/dist/types/compensation.d.ts +32 -0
  188. package/dist/types/compensation.d.ts.map +1 -0
  189. package/dist/types/compensation.js +20 -0
  190. package/dist/types/finance.d.ts +98 -0
  191. package/dist/types/finance.d.ts.map +1 -0
  192. package/dist/types/finance.js +1 -0
  193. package/dist/types/inventory.d.ts +12 -0
  194. package/dist/types/inventory.d.ts.map +1 -0
  195. package/dist/types/inventory.js +1 -0
  196. package/dist/types/labels.d.ts +19 -0
  197. package/dist/types/labels.d.ts.map +1 -0
  198. package/dist/types/labels.js +1 -0
  199. package/dist/types/orders.d.ts +276 -0
  200. package/dist/types/orders.d.ts.map +1 -0
  201. package/dist/types/orders.js +1 -0
  202. package/dist/types/products.d.ts +99 -0
  203. package/dist/types/products.d.ts.map +1 -0
  204. package/dist/types/products.js +1 -0
  205. package/dist/types/qna.d.ts +51 -0
  206. package/dist/types/qna.d.ts.map +1 -0
  207. package/dist/types/qna.js +6 -0
  208. package/dist/types/reference.d.ts +78 -0
  209. package/dist/types/reference.d.ts.map +1 -0
  210. package/dist/types/reference.js +1 -0
  211. package/dist/types/webhooks.d.ts +47 -0
  212. package/dist/types/webhooks.d.ts.map +1 -0
  213. package/dist/types/webhooks.js +19 -0
  214. package/dist/types.d.ts +73 -0
  215. package/dist/types.d.ts.map +1 -0
  216. package/dist/types.js +1 -0
  217. package/dist/validate.d.ts +9 -0
  218. package/dist/validate.d.ts.map +1 -0
  219. package/dist/validate.js +70 -0
  220. package/dist/video/api.d.ts +46 -0
  221. package/dist/video/api.d.ts.map +1 -0
  222. package/dist/video/api.js +95 -0
  223. package/dist/video/paths.d.ts +3 -0
  224. package/dist/video/paths.d.ts.map +1 -0
  225. package/dist/video/paths.js +7 -0
  226. package/dist/webhooks/inbound.d.ts +33 -0
  227. package/dist/webhooks/inbound.d.ts.map +1 -0
  228. package/dist/webhooks/inbound.js +113 -0
  229. package/dist/webhooks/management.d.ts +49 -0
  230. package/dist/webhooks/management.d.ts.map +1 -0
  231. package/dist/webhooks/management.js +89 -0
  232. package/dist/webhooks/paths.d.ts +5 -0
  233. package/dist/webhooks/paths.d.ts.map +1 -0
  234. package/dist/webhooks/paths.js +13 -0
  235. package/package.json +47 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ Bu proje [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) formatını izler.
4
+ Sürümleme [Semantic Versioning](https://semver.org/spec/v2.0.0.html) uyumludur.
5
+
6
+ ## [1.0.0] - 2026-08-27
7
+
8
+ ### Added
9
+
10
+ - TR Marketplace Integration API tam kapsam (~77 REST metodu)
11
+ - Sipariş: stream/cursor, v2, 14 mutasyon, 4 split varyantı, lookback buffer
12
+ - Fatura: link, dosya upload, silme; CONFORMANCE re-upload notları
13
+ - Stok/fiyat: `updatePriceAndInventory` (max 1000 SKU)
14
+ - Referans: marka, kategori, attribute, adres (TTL cache), geo, kargo sağlayıcıları
15
+ - Ürün V2: CRUD, bulk update, buybox, batch poll + partial fail raporu
16
+ - Video API + `waitForVideoReady` poll
17
+ - Garanti belgesi upload
18
+ - İade (Claims): liste, oluşturma, onay, issue multipart
19
+ - Webhook CRUD + inbound parse/verify (`parseWebhookPayload`, `verifyWebhookApiKey`)
20
+ - Finans: payment-order, settlements, otherfinancials, kargo faturası, settlement helper
21
+ - QnA: soru listesi, cevap
22
+ - Ortak etiket: ZPL + AB ihracat varyantı; `isCommonLabelNotAllowed`
23
+ - TEX tazmin ticket listesi
24
+ - `@hubcommerce/trendyol/testing` subpath: stage helpers, fixture export, production guard
25
+ - Statik sabitler: `CLAIM_REASONS`, `ORIGIN_COUNTRIES`, `TRENDYOL_ERROR_CODES`, `PACKAGE_STATUSES`
26
+ - HTTP lifecycle: `combineAbortSignals`, HTML gateway retry, transport errors
27
+ - Query serialization: Date ms, array CSV
28
+ - Client-side rate limit governor (opsiyonel, varsayılan kapalı)
29
+ - `qa:smoke` — getting-started 5 sütun checklist
30
+ - Tam dokümantasyon: `CONFORMANCE`, `QA`, `MIGRATION`, `ADAPTER-CONTRACT`, `DOC-SOURCES`
31
+
32
+ ### Notes
33
+
34
+ - npm paket adı: `@hubcommerce/trendyol` (org `@commerce` npm'de alinmis)
35
+ - V1 ürün/sipariş endpoint'leri export edilmez
36
+ - sapigw host kullanılmaz
37
+ - Bilinçli hariç: AutoFT, International, E-Faturam
38
+
39
+ ## [0.1.0] - 2026-08-27
40
+
41
+ ### Added
42
+
43
+ - Faz 0 iskelet: HTTP lifecycle, multipart, batch partial report, stream lookback, fixture export
44
+ - CONFORMANCE / ADAPTER-CONTRACT iskelet
45
+
46
+ [1.0.0]: https://github.com/commerce-packages/trendyol/compare/v0.1.0...v1.0.0
47
+ [0.1.0]: https://github.com/commerce-packages/trendyol/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,257 @@
1
+ # @hubcommerce/trendyol
2
+
3
+ Trendyol TR Marketplace Integration API SDK.
4
+
5
+ > **Yalnızca server-side kullanın.** API key/secret tarayıcıda, mobil uygulamada veya public repo'da **asla** bulunmamalı.
6
+
7
+ - Node `>=20.10.0` · ESM-only (`"type": "module"`) · sıfır runtime dependency
8
+ - `TrendyolResult<T>` — throw yerine `ok` / `error`
9
+ - ~77 documented REST metodu + batch poll, stream, webhook inbound
10
+
11
+ Detay: [`docs/CONFORMANCE.md`](./docs/CONFORMANCE.md) · [`docs/QA.md`](./docs/QA.md) · [`docs/MIGRATION.md`](./docs/MIGRATION.md)
12
+
13
+ ---
14
+
15
+ ## Kurulum
16
+
17
+ ```powershell
18
+ npm install @hubcommerce/trendyol
19
+ ```
20
+
21
+ Monorepo yerel:
22
+
23
+ ```powershell
24
+ npm install file:../commerce-packages/marketplace/trendyol
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Yapılandırma
30
+
31
+ `.env.example` dosyasını kopyalayın:
32
+
33
+ ```powershell
34
+ copy marketplace\trendyol\.env.example .env
35
+ ```
36
+
37
+ | Değişken | Açıklama |
38
+ |----------|----------|
39
+ | `TRENDYOL_ENV` | `stage` veya `production` |
40
+ | `TRENDYOL_SELLER_ID` | Satıcı ID |
41
+ | `TRENDYOL_API_KEY` | API key |
42
+ | `TRENDYOL_API_SECRET` | API secret |
43
+ | `TRENDYOL_INTEGRATOR_NAME` | Varsayılan `SelfIntegration` |
44
+ | `TRENDYOL_STORE_FRONT_CODE` | Varsayılan `TR` |
45
+
46
+ ### Gateway URL matrisi
47
+
48
+ | Ortam | Gateway |
49
+ |-------|---------|
50
+ | Production | `https://apigw.trendyol.com` |
51
+ | Stage | `https://stageapigw.trendyol.com` |
52
+
53
+ Eski `api.trendyol.com/sapigw` **kullanılmaz**.
54
+
55
+ Stage IP whitelist gerekir — değişiklik ~24 saat gecikebilir ([QA.md](./docs/QA.md)).
56
+
57
+ ---
58
+
59
+ ## Hızlı başlangıç
60
+
61
+ ```typescript
62
+ import { createTrendyolClient } from "@hubcommerce/trendyol";
63
+
64
+ const client = createTrendyolClient({
65
+ sellerId: process.env.TRENDYOL_SELLER_ID!,
66
+ apiKey: process.env.TRENDYOL_API_KEY!,
67
+ apiSecret: process.env.TRENDYOL_API_SECRET!,
68
+ env: "stage",
69
+ });
70
+
71
+ const conn = await client.testConnection();
72
+ if (!conn.ok) {
73
+ console.error(conn.error.message);
74
+ }
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Modül örnekleri
80
+
81
+ ### Sipariş stream (birincil senkron)
82
+
83
+ Trendyol önerisi: **webhook + periyodik stream/poll** birlikte kullanın.
84
+
85
+ ```typescript
86
+ import { createTrendyolClient } from "@hubcommerce/trendyol";
87
+
88
+ const client = createTrendyolClient();
89
+
90
+ for await (const page of client.orders.streamPackages({
91
+ lookbackMs: 300_000, // varsayılan 5 dk — saat kayması için
92
+ size: 50,
93
+ onCursorSave: (cursor) => {
94
+ // adapter: cursor'u DB'ye persist et
95
+ },
96
+ })) {
97
+ for (const pkg of page.content ?? []) {
98
+ console.log(pkg.id, pkg.status);
99
+ }
100
+ }
101
+ ```
102
+
103
+ ### Stok / fiyat
104
+
105
+ ```typescript
106
+ const result = await client.inventory.updatePriceAndInventory([
107
+ { barcode: "8683772071724", quantity: 10, salePrice: 99.9, listPrice: 129.9 },
108
+ ]);
109
+
110
+ // quantity: 0 → satış durabilir (JSDoc uyarısı)
111
+ ```
112
+
113
+ ### Ürün oluşturma + batch poll
114
+
115
+ ```typescript
116
+ import { validateEan13 } from "@hubcommerce/trendyol";
117
+
118
+ if (!validateEan13("8683772071724")) throw new Error("Geçersiz barkod");
119
+
120
+ const submit = await client.products.createProducts([/* ProductCreateItem[] */]);
121
+ if (!submit.ok) throw submit.error;
122
+
123
+ const batch = await client.batch.waitForResult(submit.data.batchRequestId, {
124
+ intervalMs: 2000,
125
+ timeoutMs: 120_000,
126
+ });
127
+
128
+ if (batch.ok && batch.data.failedItemCount > 0) {
129
+ // partial fail — adapter başarısız barkodları işler
130
+ console.log(batch.data.items?.filter((i) => i.status === "FAILED"));
131
+ }
132
+ ```
133
+
134
+ ### Webhook inbound
135
+
136
+ ```typescript
137
+ import {
138
+ parseWebhookPayload,
139
+ verifyWebhookApiKey,
140
+ } from "@hubcommerce/trendyol";
141
+
142
+ // HTTP handler (adapter katmanında)
143
+ if (!verifyWebhookApiKey(req.headers, process.env.WEBHOOK_API_KEY!)) {
144
+ return res.status(401).end();
145
+ }
146
+
147
+ const parsed = parseWebhookPayload(req.body);
148
+ if (!parsed.ok) {
149
+ return res.status(400).json({ error: parsed.error });
150
+ }
151
+
152
+ // adapter: dedup + iş kuyruğu
153
+ const pkg = parsed.data;
154
+ ```
155
+
156
+ ### Fatura
157
+
158
+ ```typescript
159
+ // Invoiced statü ≠ fatura gönderimi — iki ayrı adım
160
+ await client.orders.updatePackageStatus(packageId, { status: "Invoiced", lines: [...] });
161
+
162
+ await client.invoices.sendInvoiceLink({
163
+ shipmentPackageId: packageId,
164
+ invoiceLink: "https://...",
165
+ invoiceNumber: "INV-2026-001",
166
+ });
167
+ ```
168
+
169
+ ### Finans
170
+
171
+ ```typescript
172
+ const orders = await client.finance.getPaymentOrders({ size: 10 });
173
+ if (orders.ok && orders.data.content?.[0]) {
174
+ const paymentOrderId = orders.data.content[0].paymentOrderId;
175
+ const details = await client.finance.getSettlementDetails(paymentOrderId);
176
+ }
177
+ ```
178
+
179
+ ### Ortak etiket (TEX / Aras, Trendyol öder)
180
+
181
+ ```typescript
182
+ import { isCommonLabelNotAllowed } from "@hubcommerce/trendyol";
183
+
184
+ const created = await client.labels.createCommonLabel(cargoTrackingNumber);
185
+ if (!created.ok && isCommonLabelNotAllowed(created)) {
186
+ // capability yok — alternatif kargo akışı
187
+ }
188
+
189
+ const label = await client.labels.getCommonLabel(cargoTrackingNumber);
190
+
191
+ // AB ihracat varyantı
192
+ await client.labels.getCommonLabelWithAbProduct(cargoTrackingNumber, {
193
+ productLabelType: "ZPL",
194
+ });
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Stage test helpers
200
+
201
+ ```typescript
202
+ import { createTestOrder, SHIPMENT_PACKAGE_FIXTURE } from "@hubcommerce/trendyol/testing";
203
+ ```
204
+
205
+ **Yalnızca stage** — production config ile runtime guard throw eder.
206
+
207
+ ---
208
+
209
+ ## Geliştirme
210
+
211
+ ```powershell
212
+ npm run build --workspace=@hubcommerce/trendyol
213
+ npm test --workspace=@hubcommerce/trendyol
214
+ npm run test:exports --workspace=@hubcommerce/trendyol
215
+ npm run qa:smoke --workspace=@hubcommerce/trendyol
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Public API yüzeyi
221
+
222
+ Facade client domain modülleri:
223
+
224
+ | Modül | Açıklama |
225
+ |-------|----------|
226
+ | `client.orders` | Stream, mutasyon, split |
227
+ | `client.invoices` | Link, dosya, silme |
228
+ | `client.inventory` | Fiyat/stok toplu |
229
+ | `client.reference` | Marka, kategori, adres, geo |
230
+ | `client.products` | V2 CRUD, filter, buybox |
231
+ | `client.batch` | `waitForResult` poll |
232
+ | `client.video` | Video upload + poll |
233
+ | `client.warranty` | Garanti belgesi |
234
+ | `client.claims` | İade |
235
+ | `client.webhooks` | CRUD |
236
+ | `client.finance` | Hakedis, settlements |
237
+ | `client.qna` | Müşteri soruları |
238
+ | `client.labels` | Ortak etiket ZPL |
239
+ | `client.compensation` | TEX tazmin |
240
+ | `client.testConnection()` | Canonical bağlantı testi |
241
+
242
+ Root export helper'lar: `parseWebhookPayload`, `verifyWebhookApiKey`, `validateEan13`, `buildProductCreatePayload`, statik sabitler (`CLAIM_REASONS`, `ORIGIN_COUNTRIES`, …).
243
+
244
+ ---
245
+
246
+ ## Migration
247
+
248
+ - Ürün V1 kapanış: **15 Eylül 2026**
249
+ - Sipariş V1 kapanış: **15 Ekim 2026**
250
+
251
+ Detay: [`docs/MIGRATION.md`](./docs/MIGRATION.md)
252
+
253
+ ---
254
+
255
+ ## Lisans
256
+
257
+ MIT — [`LICENSE`](./LICENSE)
@@ -0,0 +1,23 @@
1
+ import { parseBatchRequestReport, type BatchRequestReport } from "./report.js";
2
+ import type { TrendyolHooks, TrendyolResult } from "../types.js";
3
+ export type WaitForBatchOptions = {
4
+ intervalMs?: number;
5
+ timeoutMs?: number;
6
+ signal?: AbortSignal;
7
+ };
8
+ export type BatchResultFetcher = (batchRequestId: string, signal?: AbortSignal) => Promise<TrendyolResult<BatchRequestReport>>;
9
+ /**
10
+ * Product batch async poll — sonuc TTL ~4 saat.
11
+ *
12
+ * Ayni batchRequestId ile eszamanli poll → client instance'ta paylasilan in-flight promise.
13
+ */
14
+ export declare class BatchPoller {
15
+ private readonly fetchResult;
16
+ private readonly getHooks;
17
+ private readonly inFlight;
18
+ constructor(fetchResult: BatchResultFetcher, getHooks: () => TrendyolHooks);
19
+ waitForResult(batchRequestId: string, options?: WaitForBatchOptions): Promise<TrendyolResult<BatchRequestReport>>;
20
+ private pollUntilTerminal;
21
+ }
22
+ export { parseBatchRequestReport };
23
+ //# sourceMappingURL=poller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poller.d.ts","sourceRoot":"","sources":["../../src/batch/poller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjE,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAYF,MAAM,MAAM,kBAAkB,GAAG,CAC/B,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,WAAW,KACjB,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAEjD;;;;GAIG;AACH,qBAAa,WAAW;IAOpB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAP3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGrB;gBAGe,WAAW,EAAE,kBAAkB,EAC/B,QAAQ,EAAE,MAAM,aAAa;IAGhD,aAAa,CACX,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;YAchC,iBAAiB;CA6ChC;AAiBD,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { parseBatchRequestReport } from "./report.js";
2
+ const DEFAULT_INTERVAL_MS = 2_000;
3
+ const DEFAULT_TIMEOUT_MS = 120_000;
4
+ const TERMINAL_BATCH_STATUSES = new Set([
5
+ "COMPLETED",
6
+ "FAILED",
7
+ "CANCELLED",
8
+ "CANCELED",
9
+ ]);
10
+ /**
11
+ * Product batch async poll — sonuc TTL ~4 saat.
12
+ *
13
+ * Ayni batchRequestId ile eszamanli poll → client instance'ta paylasilan in-flight promise.
14
+ */
15
+ export class BatchPoller {
16
+ fetchResult;
17
+ getHooks;
18
+ inFlight = new Map();
19
+ constructor(fetchResult, getHooks) {
20
+ this.fetchResult = fetchResult;
21
+ this.getHooks = getHooks;
22
+ }
23
+ waitForResult(batchRequestId, options) {
24
+ const existing = this.inFlight.get(batchRequestId);
25
+ if (existing) {
26
+ return existing;
27
+ }
28
+ const promise = this.pollUntilTerminal(batchRequestId, options);
29
+ this.inFlight.set(batchRequestId, promise);
30
+ void promise.finally(() => {
31
+ this.inFlight.delete(batchRequestId);
32
+ });
33
+ return promise;
34
+ }
35
+ async pollUntilTerminal(batchRequestId, options) {
36
+ const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;
37
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
38
+ const deadline = Date.now() + timeoutMs;
39
+ let attempt = 0;
40
+ while (Date.now() < deadline) {
41
+ if (options?.signal?.aborted) {
42
+ return { ok: false, reason: "Batch poll iptal edildi.", code: "ABORTED" };
43
+ }
44
+ this.getHooks().onBatchPoll?.({ batchRequestId, attempt });
45
+ attempt += 1;
46
+ const result = await this.fetchResult(batchRequestId, options?.signal);
47
+ if (!result.ok) {
48
+ return result;
49
+ }
50
+ const report = result.data;
51
+ const status = report.status?.toUpperCase();
52
+ if (status && TERMINAL_BATCH_STATUSES.has(status)) {
53
+ return { ok: true, data: report };
54
+ }
55
+ try {
56
+ await sleep(intervalMs, options?.signal);
57
+ }
58
+ catch (error) {
59
+ if (error instanceof DOMException && error.name === "AbortError") {
60
+ return { ok: false, reason: "Batch poll iptal edildi.", code: "ABORTED" };
61
+ }
62
+ throw error;
63
+ }
64
+ }
65
+ return {
66
+ ok: false,
67
+ reason: `Batch poll zaman asimi (${timeoutMs}ms): ${batchRequestId}`,
68
+ code: "BATCH_POLL_TIMEOUT",
69
+ };
70
+ }
71
+ }
72
+ async function sleep(ms, signal) {
73
+ if (signal?.aborted) {
74
+ throw new DOMException("Aborted", "AbortError");
75
+ }
76
+ await new Promise((resolve, reject) => {
77
+ const timer = setTimeout(resolve, ms);
78
+ const onAbort = () => {
79
+ clearTimeout(timer);
80
+ reject(new DOMException("Aborted", "AbortError"));
81
+ };
82
+ signal?.addEventListener("abort", onAbort, { once: true });
83
+ });
84
+ }
85
+ export { parseBatchRequestReport };
@@ -0,0 +1,15 @@
1
+ export type BatchItemResult = {
2
+ barcode?: string;
3
+ status?: string;
4
+ failureReasons?: string[];
5
+ };
6
+ export type BatchRequestReport = {
7
+ status?: string;
8
+ itemCount?: number;
9
+ failedItemCount?: number;
10
+ items?: BatchItemResult[];
11
+ };
12
+ export declare function parseBatchRequestReport(raw: unknown): BatchRequestReport;
13
+ export declare function hasPartialBatchFailures(report: BatchRequestReport): boolean;
14
+ export declare function collectBatchFailureReasons(report: BatchRequestReport): string[];
15
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/batch/report.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAgBxE;AAkBD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAE3E;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAQ/E"}
@@ -0,0 +1,41 @@
1
+ export function parseBatchRequestReport(raw) {
2
+ if (!raw || typeof raw !== "object") {
3
+ return {};
4
+ }
5
+ const record = raw;
6
+ const items = Array.isArray(record.items)
7
+ ? record.items.map(parseBatchItem)
8
+ : undefined;
9
+ return {
10
+ status: typeof record.status === "string" ? record.status : undefined,
11
+ itemCount: typeof record.itemCount === "number" ? record.itemCount : undefined,
12
+ failedItemCount: typeof record.failedItemCount === "number" ? record.failedItemCount : undefined,
13
+ items,
14
+ };
15
+ }
16
+ function parseBatchItem(raw) {
17
+ if (!raw || typeof raw !== "object") {
18
+ return {};
19
+ }
20
+ const record = raw;
21
+ const failureReasons = Array.isArray(record.failureReasons)
22
+ ? record.failureReasons.filter((r) => typeof r === "string")
23
+ : undefined;
24
+ return {
25
+ barcode: typeof record.barcode === "string" ? record.barcode : undefined,
26
+ status: typeof record.status === "string" ? record.status : undefined,
27
+ failureReasons,
28
+ };
29
+ }
30
+ export function hasPartialBatchFailures(report) {
31
+ return (report.failedItemCount ?? 0) > 0;
32
+ }
33
+ export function collectBatchFailureReasons(report) {
34
+ const reasons = [];
35
+ for (const item of report.items ?? []) {
36
+ for (const reason of item.failureReasons ?? []) {
37
+ reasons.push(reason);
38
+ }
39
+ }
40
+ return reasons;
41
+ }
@@ -0,0 +1,4 @@
1
+ export type { BatchItemResult, BatchRequestReport } from "./report.js";
2
+ export { collectBatchFailureReasons, hasPartialBatchFailures, parseBatchRequestReport, } from "./report.js";
3
+ export { BatchPoller, type WaitForBatchOptions } from "./poller.js";
4
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/batch/types.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { collectBatchFailureReasons, hasPartialBatchFailures, parseBatchRequestReport, } from "./report.js";
2
+ export { BatchPoller } from "./poller.js";
@@ -0,0 +1,48 @@
1
+ import type { TrendyolHttpClient } from "../http.js";
2
+ import type { TrendyolConfig, TrendyolResult } from "../types.js";
3
+ import type { ApproveClaimLineItemsBody, ClaimIssueReason, ClaimItemAudit, ClaimsListResponse, CreateClaimBody, CreateClaimIssueFields, CreateClaimResponse, GetClaimsParams } from "../types/claims.js";
4
+ type ClaimOptions = {
5
+ signal?: AbortSignal;
6
+ };
7
+ /**
8
+ * Iade (claims) domain API.
9
+ */
10
+ export declare class ClaimsApi {
11
+ private readonly http;
12
+ private readonly config;
13
+ constructor(http: TrendyolHttpClient, config: TrendyolConfig);
14
+ /**
15
+ * Iade edilen siparisleri sayfali listeler.
16
+ * GET /integration/order/sellers/{sellerId}/claims
17
+ */
18
+ getClaims(params?: GetClaimsParams): Promise<TrendyolResult<ClaimsListResponse>>;
19
+ /**
20
+ * Iade kodu olmadan gelen paketler icin iade talebi olusturur.
21
+ * POST .../claims/create
22
+ */
23
+ createClaim(body: CreateClaimBody, options?: ClaimOptions): Promise<TrendyolResult<CreateClaimResponse>>;
24
+ /**
25
+ * Depoya iade edilen siparisleri onaylar.
26
+ * PUT .../claims/{claimId}/items/approve
27
+ *
28
+ * Rate limit: 5 istek/dk (Trendyol dokumani).
29
+ */
30
+ approveClaimLineItems(claimId: string, body: ApproveClaimLineItemsBody, options?: ClaimOptions): Promise<TrendyolResult<unknown>>;
31
+ /**
32
+ * Iade ret talebi olusturur — multipart/form-data.
33
+ * POST .../claims/{claimId}/issue
34
+ */
35
+ createClaimIssue(claimId: string, fields: CreateClaimIssueFields, options?: ClaimOptions): Promise<TrendyolResult<unknown>>;
36
+ /**
37
+ * Iade red sebeplerini listeler (global endpoint).
38
+ * GET /integration/order/claim-issue-reasons
39
+ */
40
+ getClaimIssueReasons(options?: ClaimOptions): Promise<TrendyolResult<ClaimIssueReason[]>>;
41
+ /**
42
+ * Iade kalemi audit gecmisini getirir.
43
+ * GET .../claims/items/{claimItemsId}/audit
44
+ */
45
+ getClaimItemAudits(claimItemsId: string, options?: ClaimOptions): Promise<TrendyolResult<ClaimItemAudit[]>>;
46
+ }
47
+ export {};
48
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/claims/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EACV,yBAAyB,EACzB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAK5B,KAAK,YAAY,GAAG;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAgB7C;;GAEG;AACH,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,cAAc;IAGzC;;;OAGG;IACH,SAAS,CACP,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;IAgB9C;;;OAGG;IACH,WAAW,CACT,IAAI,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;IAU/C;;;;;OAKG;IACH,qBAAqB,CACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,yBAAyB,EAC/B,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAUnC;;;OAGG;IACH,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,sBAAsB,EAC9B,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAUnC;;;OAGG;IACH,oBAAoB,CAClB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAS9C;;;OAGG;IACH,kBAAkB,CAChB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,CAAC;CAQ7C"}
@@ -0,0 +1,116 @@
1
+ import { validatePageSize } from "../validate.js";
2
+ import { buildClaimIssueFormData } from "./form.js";
3
+ import { claimIssueReasonsPath, claimsBase } from "./paths.js";
4
+ function buildClaimsQuery(params) {
5
+ const query = {};
6
+ if (params.startDate !== undefined)
7
+ query.startDate = params.startDate;
8
+ if (params.endDate !== undefined)
9
+ query.endDate = params.endDate;
10
+ if (params.page !== undefined)
11
+ query.page = params.page;
12
+ if (params.size !== undefined)
13
+ query.size = params.size;
14
+ if (params.claimItemStatus !== undefined) {
15
+ query.claimItemStatus = params.claimItemStatus;
16
+ }
17
+ if (params.orderNumber !== undefined)
18
+ query.orderNumber = params.orderNumber;
19
+ if (params.claimIds !== undefined)
20
+ query.claimIds = params.claimIds;
21
+ return query;
22
+ }
23
+ /**
24
+ * Iade (claims) domain API.
25
+ */
26
+ export class ClaimsApi {
27
+ http;
28
+ config;
29
+ constructor(http, config) {
30
+ this.http = http;
31
+ this.config = config;
32
+ }
33
+ /**
34
+ * Iade edilen siparisleri sayfali listeler.
35
+ * GET /integration/order/sellers/{sellerId}/claims
36
+ */
37
+ getClaims(params) {
38
+ const size = params?.size ?? 50;
39
+ const pageValidation = validatePageSize("claims", size);
40
+ if (!pageValidation.ok) {
41
+ return Promise.resolve(pageValidation);
42
+ }
43
+ return this.http.requestJson({
44
+ method: "GET",
45
+ path: claimsBase(this.config.sellerId),
46
+ query: buildClaimsQuery({ ...params, size }),
47
+ retryPolicy: "safe",
48
+ signal: params?.signal,
49
+ });
50
+ }
51
+ /**
52
+ * Iade kodu olmadan gelen paketler icin iade talebi olusturur.
53
+ * POST .../claims/create
54
+ */
55
+ createClaim(body, options) {
56
+ return this.http.requestJson({
57
+ method: "POST",
58
+ path: `${claimsBase(this.config.sellerId)}/create`,
59
+ body,
60
+ retryPolicy: "none",
61
+ signal: options?.signal,
62
+ });
63
+ }
64
+ /**
65
+ * Depoya iade edilen siparisleri onaylar.
66
+ * PUT .../claims/{claimId}/items/approve
67
+ *
68
+ * Rate limit: 5 istek/dk (Trendyol dokumani).
69
+ */
70
+ approveClaimLineItems(claimId, body, options) {
71
+ return this.http.requestJson({
72
+ method: "PUT",
73
+ path: `${claimsBase(this.config.sellerId)}/${claimId}/items/approve`,
74
+ body,
75
+ retryPolicy: "none",
76
+ signal: options?.signal,
77
+ });
78
+ }
79
+ /**
80
+ * Iade ret talebi olusturur — multipart/form-data.
81
+ * POST .../claims/{claimId}/issue
82
+ */
83
+ createClaimIssue(claimId, fields, options) {
84
+ return this.http.requestMultipart({
85
+ method: "POST",
86
+ path: `${claimsBase(this.config.sellerId)}/${claimId}/issue`,
87
+ formData: buildClaimIssueFormData(fields),
88
+ retryPolicy: "none",
89
+ signal: options?.signal,
90
+ });
91
+ }
92
+ /**
93
+ * Iade red sebeplerini listeler (global endpoint).
94
+ * GET /integration/order/claim-issue-reasons
95
+ */
96
+ getClaimIssueReasons(options) {
97
+ return this.http.requestJson({
98
+ method: "GET",
99
+ path: claimIssueReasonsPath(),
100
+ retryPolicy: "safe",
101
+ signal: options?.signal,
102
+ });
103
+ }
104
+ /**
105
+ * Iade kalemi audit gecmisini getirir.
106
+ * GET .../claims/items/{claimItemsId}/audit
107
+ */
108
+ getClaimItemAudits(claimItemsId, options) {
109
+ return this.http.requestJson({
110
+ method: "GET",
111
+ path: `${claimsBase(this.config.sellerId)}/items/${claimItemsId}/audit`,
112
+ retryPolicy: "safe",
113
+ signal: options?.signal,
114
+ });
115
+ }
116
+ }