vantuz 3.3.0 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/cli.js +185 -70
  2. package/core/agent.js +82 -0
  3. package/core/ai-provider.js +26 -6
  4. package/core/automation.js +504 -0
  5. package/core/channels.js +2 -2
  6. package/core/eia-monitor.js +14 -6
  7. package/core/engine.js +319 -90
  8. package/core/gateway.js +68 -16
  9. package/core/migrations/001-initial-schema.sql +20 -0
  10. package/core/openclaw-bridge.js +191 -0
  11. package/core/scrapers/TrendyolScraper.js +74 -19
  12. package/package.json +85 -91
  13. package/platforms/amazon.js +5 -3
  14. package/platforms/ciceksepeti.js +4 -2
  15. package/platforms/hepsiburada.js +6 -4
  16. package/platforms/n11.js +5 -3
  17. package/platforms/pazarama.js +4 -2
  18. package/platforms/trendyol.js +3 -3
  19. package/plugins/vantuz/package.json +2 -2
  20. package/plugins/vantuz/platforms/_request.js +34 -0
  21. package/plugins/vantuz/platforms/amazon.js +59 -35
  22. package/plugins/vantuz/platforms/ciceksepeti.js +14 -9
  23. package/plugins/vantuz/platforms/hepsiburada.js +14 -9
  24. package/plugins/vantuz/platforms/index.js +101 -54
  25. package/plugins/vantuz/platforms/n11.js +91 -34
  26. package/plugins/vantuz/platforms/pazarama.js +30 -17
  27. package/plugins/vantuz/platforms/pttavm.js +14 -9
  28. package/plugins/vantuz/platforms/trendyol.js +16 -11
  29. package/server/app.js +29 -12
  30. package/server/public/index.html +2 -2
  31. package/.openclaw/completions/openclaw.bash +0 -227
  32. package/.openclaw/completions/openclaw.fish +0 -1552
  33. package/.openclaw/completions/openclaw.ps1 +0 -1966
  34. package/.openclaw/completions/openclaw.zsh +0 -3571
  35. package/.openclaw/gateway.cmd +0 -10
  36. package/.openclaw/identity/device.json +0 -7
  37. package/.openclaw/openclaw.json +0 -32
  38. package/DOCS_TR.md +0 -298
  39. package/onboard.js +0 -322
@@ -3,8 +3,9 @@
3
3
  * developer-docs.amazon.com/sp-api
4
4
  */
5
5
 
6
- import axios from 'axios';
7
- import crypto from 'crypto';
6
+ import axios from 'axios';
7
+ import crypto from 'crypto';
8
+ import { requestWithRetry } from './_request.js';
8
9
 
9
10
  const REGIONS = {
10
11
  eu: {
@@ -29,48 +30,70 @@ export class AmazonAPI {
29
30
  this.clientSecret = config.clientSecret;
30
31
  this.refreshToken = config.refreshToken;
31
32
 
32
- this.regionConfig = REGIONS[this.region];
33
- this.accessToken = null;
34
- this.tokenExpiry = null;
35
- }
36
-
37
- async _getAccessToken() {
33
+ this.regionConfig = REGIONS[this.region];
34
+ this.accessToken = null;
35
+ this.tokenExpiry = null;
36
+ this._tokenPromise = null;
37
+ }
38
+
39
+ async _getAccessToken() {
38
40
  if (this.accessToken && this.tokenExpiry > Date.now()) {
39
41
  return this.accessToken;
40
42
  }
41
-
42
- try {
43
- const response = await axios.post('https://api.amazon.com/auth/o2/token', {
44
- grant_type: 'refresh_token',
45
- refresh_token: this.refreshToken,
46
- client_id: this.clientId,
47
- client_secret: this.clientSecret
48
- });
49
-
50
- this.accessToken = response.data.access_token;
51
- this.tokenExpiry = Date.now() + (response.data.expires_in * 1000) - 60000;
52
- return this.accessToken;
53
- } catch (error) {
54
- throw new Error('Token alınamadı: ' + error.message);
43
+ if (this._tokenPromise) {
44
+ return await this._tokenPromise;
55
45
  }
46
+
47
+ this._tokenPromise = (async () => {
48
+ try {
49
+ const response = await requestWithRetry(axios, {
50
+ method: 'POST',
51
+ url: 'https://api.amazon.com/auth/o2/token',
52
+ data: {
53
+ grant_type: 'refresh_token',
54
+ refresh_token: this.refreshToken,
55
+ client_id: this.clientId,
56
+ client_secret: this.clientSecret
57
+ }
58
+ }, {
59
+ retries: 3,
60
+ baseDelayMs: 500,
61
+ maxDelayMs: 4000
62
+ });
63
+
64
+ this.accessToken = response.data.access_token;
65
+ this.tokenExpiry = Date.now() + (response.data.expires_in * 1000) - 60000;
66
+ return this.accessToken;
67
+ } catch (error) {
68
+ throw new Error('Token alınamadı: ' + error.message);
69
+ } finally {
70
+ this._tokenPromise = null;
71
+ }
72
+ })();
73
+
74
+ return await this._tokenPromise;
56
75
  }
57
76
 
58
77
  async _request(method, path, data = null, params = null) {
59
78
  try {
60
79
  const token = await this._getAccessToken();
61
- const response = await axios({
62
- method,
63
- url: `${this.regionConfig.endpoint}${path}`,
64
- headers: {
65
- 'x-amz-access-token': token,
66
- 'Content-Type': 'application/json'
67
- },
68
- data,
69
- params: {
70
- ...params,
71
- MarketplaceIds: this.regionConfig.marketplace
72
- }
73
- });
80
+ const response = await requestWithRetry(axios, {
81
+ method,
82
+ url: `${this.regionConfig.endpoint}${path}`,
83
+ headers: {
84
+ 'x-amz-access-token': token,
85
+ 'Content-Type': 'application/json'
86
+ },
87
+ data,
88
+ params: {
89
+ ...params,
90
+ MarketplaceIds: this.regionConfig.marketplace
91
+ }
92
+ }, {
93
+ retries: 3,
94
+ baseDelayMs: 500,
95
+ maxDelayMs: 4000
96
+ });
74
97
  return { success: true, data: response.data };
75
98
  } catch (error) {
76
99
  return {
@@ -237,3 +260,4 @@ export const amazonApi = {
237
260
  async updatePrice(sku, price, region) { return instances[region]?.updatePrice(sku, price); },
238
261
  async getOrders(params, region) { return instances[region]?.getOrders(params); }
239
262
  };
263
+
@@ -3,7 +3,8 @@
3
3
  * bayi.ciceksepeti.com
4
4
  */
5
5
 
6
- import axios from 'axios';
6
+ import axios from 'axios';
7
+ import { requestWithRetry } from './_request.js';
7
8
 
8
9
  const BASE_URL = 'https://apis.ciceksepeti.com/api/v1';
9
10
 
@@ -22,14 +23,18 @@ export class CiceksepetiAPI {
22
23
 
23
24
  async _request(method, endpoint, data = null, params = null) {
24
25
  try {
25
- const response = await axios({
26
- method,
27
- url: `${BASE_URL}${endpoint}`,
28
- headers: this._headers(),
29
- data,
30
- params
31
- });
32
- return { success: true, data: response.data };
26
+ const response = await requestWithRetry(axios, {
27
+ method,
28
+ url: `${BASE_URL}${endpoint}`,
29
+ headers: this._headers(),
30
+ data,
31
+ params
32
+ }, {
33
+ retries: 3,
34
+ baseDelayMs: 500,
35
+ maxDelayMs: 4000
36
+ });
37
+ return { success: true, data: response.data };
33
38
  } catch (error) {
34
39
  return {
35
40
  success: false,
@@ -3,7 +3,8 @@
3
3
  * developer.hepsiburada.com
4
4
  */
5
5
 
6
- import axios from 'axios';
6
+ import axios from 'axios';
7
+ import { requestWithRetry } from './_request.js';
7
8
 
8
9
  const BASE_URL = 'https://mpop-sit.hepsiburada.com'; // Production: mpop.hepsiburada.com
9
10
  const LISTING_URL = 'https://listing-external.hepsiburada.com';
@@ -27,14 +28,18 @@ export class HepsiburadaAPI {
27
28
 
28
29
  async _request(method, url, data = null, params = null) {
29
30
  try {
30
- const response = await axios({
31
- method,
32
- url,
33
- headers: this._headers(),
34
- data,
35
- params
36
- });
37
- return { success: true, data: response.data };
31
+ const response = await requestWithRetry(axios, {
32
+ method,
33
+ url,
34
+ headers: this._headers(),
35
+ data,
36
+ params
37
+ }, {
38
+ retries: 3,
39
+ baseDelayMs: 500,
40
+ maxDelayMs: 4000
41
+ });
42
+ return { success: true, data: response.data };
38
43
  } catch (error) {
39
44
  return {
40
45
  success: false,
@@ -133,68 +133,115 @@ export const platformHub = {
133
133
  /**
134
134
  * Çoklu platform fiyat güncelle
135
135
  */
136
- async updatePriceMulti(barcode, price, targetPlatforms = 'all') {
137
- const targets = targetPlatforms === 'all'
138
- ? this.getConnected()
139
- : targetPlatforms.split(',').map(p => PLATFORM_ALIASES[p.trim()]).filter(Boolean);
140
-
141
- const results = {};
142
- for (const platform of targets) {
143
- const api = platforms[platform];
144
- if (api?.isConnected()) {
145
- results[platform] = await api.updatePrice(barcode, price);
146
- }
147
- }
148
- return results;
149
- },
136
+ async updatePriceMulti(barcode, price, targetPlatforms = 'all') {
137
+ const targets = targetPlatforms === 'all'
138
+ ? this.getConnected()
139
+ : targetPlatforms.split(',').map(p => PLATFORM_ALIASES[p.trim()]).filter(Boolean);
140
+
141
+ const results = {};
142
+ const tasks = targets.map(async (platform) => {
143
+ const api = platforms[platform];
144
+ if (!api?.isConnected()) {
145
+ results[platform] = { success: false, error: 'Not connected' };
146
+ return;
147
+ }
148
+ try {
149
+ results[platform] = await api.updatePrice(barcode, price);
150
+ } catch (error) {
151
+ results[platform] = { success: false, error: error.message };
152
+ }
153
+ });
154
+ await Promise.allSettled(tasks);
155
+ return results;
156
+ },
150
157
 
151
158
  /**
152
159
  * Çoklu platform stok güncelle
153
160
  */
154
- async updateStockMulti(barcode, quantity, targetPlatforms = 'all') {
155
- const targets = targetPlatforms === 'all'
156
- ? this.getConnected()
157
- : targetPlatforms.split(',').map(p => PLATFORM_ALIASES[p.trim()]).filter(Boolean);
158
-
159
- const results = {};
160
- for (const platform of targets) {
161
- const api = platforms[platform];
162
- if (api?.isConnected()) {
163
- results[platform] = await api.updateStock(barcode, quantity);
164
- }
165
- }
166
- return results;
167
- },
161
+ async updateStockMulti(barcode, quantity, targetPlatforms = 'all') {
162
+ const targets = targetPlatforms === 'all'
163
+ ? this.getConnected()
164
+ : targetPlatforms.split(',').map(p => PLATFORM_ALIASES[p.trim()]).filter(Boolean);
165
+
166
+ const results = {};
167
+ const tasks = targets.map(async (platform) => {
168
+ const api = platforms[platform];
169
+ if (!api?.isConnected()) {
170
+ results[platform] = { success: false, error: 'Not connected' };
171
+ return;
172
+ }
173
+ try {
174
+ results[platform] = await api.updateStock(barcode, quantity);
175
+ } catch (error) {
176
+ results[platform] = { success: false, error: error.message };
177
+ }
178
+ });
179
+ await Promise.allSettled(tasks);
180
+ return results;
181
+ },
168
182
 
169
183
  /**
170
184
  * Tüm platformlardan sipariş çek
171
185
  */
172
- async getAllOrders(params = {}) {
173
- const connected = this.getConnected();
174
- const allOrders = [];
175
-
176
- const orderPromises = connected.map(async (platform) => {
177
- const api = platforms[platform];
178
- const result = await api.getOrders(params);
179
- if (result.success) {
180
- const orders = result.data.content || result.data.orders || result.data || [];
181
- return orders.map(order => ({
182
- ...order,
183
- _platform: platform,
184
- _icon: this.getIcon(platform)
185
- }));
186
- }
187
- return [];
188
- });
189
-
190
- const results = await Promise.all(orderPromises);
191
- results.forEach(platformOrders => {
192
- allOrders.push(...platformOrders);
193
- });
194
-
195
- // Tarihe göre sırala
196
- allOrders.sort((a, b) => new Date(b.createdDate || b.orderDate) - new Date(a.createdDate || a.orderDate));
197
- return allOrders;
186
+ async getAllOrders(params = {}) {
187
+ const connected = this.getConnected();
188
+ const allOrders = [];
189
+
190
+ const orderPromises = connected.map(async (platform) => {
191
+ const api = platforms[platform];
192
+ try {
193
+ const result = await api.getOrders(params);
194
+ if (!result?.success) return [];
195
+
196
+ const data = result.data;
197
+ let orders = [];
198
+ if (Array.isArray(data?.content)) {
199
+ orders = data.content;
200
+ } else if (Array.isArray(data?.orders)) {
201
+ orders = data.orders;
202
+ } else if (Array.isArray(data)) {
203
+ orders = data;
204
+ } else {
205
+ return [];
206
+ }
207
+
208
+ return orders.map(order => {
209
+ const normalized = { ...order };
210
+ if (platform === 'n11') {
211
+ if (!normalized.orderNumber && normalized.orderNumber !== 0) {
212
+ normalized.orderNumber = normalized.id;
213
+ }
214
+ if (!normalized.customerName) {
215
+ normalized.customerName = normalized.customerfullName || normalized.customerFullName;
216
+ }
217
+ if (!normalized.totalPrice) {
218
+ normalized.totalPrice = normalized.totalAmount || normalized.totalPrice;
219
+ }
220
+ if (!normalized.status) {
221
+ normalized.status = normalized.shipmentPackageStatus || normalized.status;
222
+ }
223
+ }
224
+ return {
225
+ ...normalized,
226
+ _platform: platform,
227
+ _icon: this.getIcon(platform)
228
+ };
229
+ });
230
+ } catch {
231
+ return [];
232
+ }
233
+ });
234
+
235
+ const results = await Promise.allSettled(orderPromises);
236
+ results.forEach(platformOrders => {
237
+ if (platformOrders.status === 'fulfilled') {
238
+ allOrders.push(...platformOrders.value);
239
+ }
240
+ });
241
+
242
+ // Tarihe göre sırala
243
+ allOrders.sort((a, b) => new Date(b.createdDate || b.orderDate) - new Date(a.createdDate || a.orderDate));
244
+ return allOrders;
198
245
  }
199
246
  };
200
247
 
@@ -3,8 +3,9 @@
3
3
  * api.n11.com/ws/*.wsdl
4
4
  */
5
5
 
6
- import axios from 'axios';
7
- import { parseStringPromise, Builder } from 'xml2js';
6
+ import axios from 'axios';
7
+ import { parseStringPromise, Builder } from 'xml2js';
8
+ import { requestWithRetry } from './_request.js';
8
9
 
9
10
  const WSDL_URLS = {
10
11
  product: 'https://api.n11.com/ws/ProductService.wsdl',
@@ -14,14 +15,16 @@ const WSDL_URLS = {
14
15
  city: 'https://api.n11.com/ws/CityService.wsdl'
15
16
  };
16
17
 
17
- const SOAP_ENDPOINTS = {
18
- product: 'https://api.n11.com/ws/ProductService',
19
- order: 'https://api.n11.com/ws/OrderService',
20
- shipment: 'https://api.n11.com/ws/ShipmentService',
21
- category: 'https://api.n11.com/ws/CategoryService'
22
- };
23
-
24
- export class N11API {
18
+ const SOAP_ENDPOINTS = {
19
+ product: 'https://api.n11.com/ws/ProductService',
20
+ order: 'https://api.n11.com/ws/OrderService',
21
+ shipment: 'https://api.n11.com/ws/ShipmentService',
22
+ category: 'https://api.n11.com/ws/CategoryService'
23
+ };
24
+
25
+ const REST_BASE = 'https://api.n11.com/rest';
26
+
27
+ export class N11API {
25
28
  constructor(config) {
26
29
  this.apiKey = config.apiKey;
27
30
  this.apiSecret = config.apiSecret;
@@ -47,15 +50,22 @@ export class N11API {
47
50
  </SOAP-ENV:Envelope>`;
48
51
  }
49
52
 
50
- async _soapRequest(service, method, body = '') {
53
+ async _soapRequest(service, method, body = '') {
51
54
  try {
52
55
  const envelope = this._buildSoapEnvelope(service, method, body);
53
- const response = await axios.post(SOAP_ENDPOINTS[service], envelope, {
54
- headers: {
55
- 'Content-Type': 'text/xml; charset=utf-8',
56
- 'SOAPAction': `${method}`
57
- }
58
- });
56
+ const response = await requestWithRetry(axios, {
57
+ method: 'POST',
58
+ url: SOAP_ENDPOINTS[service],
59
+ data: envelope,
60
+ headers: {
61
+ 'Content-Type': 'text/xml; charset=utf-8',
62
+ 'SOAPAction': `${method}`
63
+ }
64
+ }, {
65
+ retries: 3,
66
+ baseDelayMs: 500,
67
+ maxDelayMs: 4000
68
+ });
59
69
 
60
70
  const result = await parseStringPromise(response.data, { explicitArray: false });
61
71
  const bodyKey = Object.keys(result['SOAP-ENV:Envelope']['SOAP-ENV:Body'])[0];
@@ -69,7 +79,31 @@ export class N11API {
69
79
  error: error.response?.data || error.message
70
80
  };
71
81
  }
72
- }
82
+ }
83
+
84
+ async _restRequest(method, path, params = {}) {
85
+ try {
86
+ const response = await requestWithRetry(axios, {
87
+ method,
88
+ url: `${REST_BASE}${path}`,
89
+ headers: {
90
+ appkey: this.apiKey,
91
+ appsecret: this.apiSecret
92
+ },
93
+ params
94
+ }, {
95
+ retries: 3,
96
+ baseDelayMs: 500,
97
+ maxDelayMs: 4000
98
+ });
99
+ return { success: true, data: response.data };
100
+ } catch (error) {
101
+ return {
102
+ success: false,
103
+ error: error.response?.data || error.message
104
+ };
105
+ }
106
+ }
73
107
 
74
108
  // ═══════════════════════════════════════════════════════════════════════════
75
109
  // ÜRÜN İŞLEMLERİ
@@ -161,22 +195,45 @@ export class N11API {
161
195
  // SİPARİŞ İŞLEMLERİ
162
196
  // ═══════════════════════════════════════════════════════════════════════════
163
197
 
164
- async getOrders(params = {}) {
165
- const { status, startDate, endDate, page = 0, size = 100 } = params;
166
-
167
- let searchData = '';
168
- if (status) searchData += `<status>${status}</status>`;
169
- if (startDate) searchData += `<period><startDate>${startDate}</startDate>`;
170
- if (endDate) searchData += `<endDate>${endDate}</endDate></period>`;
171
-
172
- return await this._soapRequest('order', 'DetailedOrderList', `
173
- <searchData>${searchData}</searchData>
174
- <pagingData>
175
- <currentPage>${page}</currentPage>
176
- <pageSize>${size}</pageSize>
177
- </pagingData>
178
- `);
179
- }
198
+ async getOrders(params = {}) {
199
+ const {
200
+ status,
201
+ allStatuses = false,
202
+ startDate,
203
+ endDate,
204
+ page = 0,
205
+ size = 100,
206
+ orderNumber,
207
+ packageIds,
208
+ orderByField,
209
+ orderByDirection
210
+ } = params;
211
+
212
+ const now = Date.now();
213
+ const fifteenDaysMs = 15 * 24 * 60 * 60 * 1000;
214
+ const effectiveStart = startDate ?? (endDate ? endDate - fifteenDaysMs : now - fifteenDaysMs);
215
+ const effectiveEnd = endDate ?? (startDate ? startDate + fifteenDaysMs : now);
216
+ const effectiveStatus = allStatuses ? undefined : (status ?? (orderNumber || packageIds ? undefined : 'Created'));
217
+ const requestParams = {
218
+ status: effectiveStatus,
219
+ startDate: effectiveStart,
220
+ endDate: effectiveEnd,
221
+ page,
222
+ size: Math.min(Number(size) || 100, 100),
223
+ orderNumber,
224
+ packageIds,
225
+ orderByField,
226
+ orderByDirection
227
+ };
228
+
229
+ Object.keys(requestParams).forEach(key => {
230
+ if (requestParams[key] === undefined || requestParams[key] === null || requestParams[key] === '') {
231
+ delete requestParams[key];
232
+ }
233
+ });
234
+
235
+ return await this._restRequest('GET', '/delivery/v1/shipmentPackages', requestParams);
236
+ }
180
237
 
181
238
  async getOrderDetail(orderId) {
182
239
  return await this._soapRequest('order', 'OrderDetail', `
@@ -3,7 +3,8 @@
3
3
  * sellers.pazarama.com
4
4
  */
5
5
 
6
- import axios from 'axios';
6
+ import axios from 'axios';
7
+ import { requestWithRetry } from './_request.js';
7
8
 
8
9
  const BASE_URL = 'https://isortagimapi.pazarama.com/api';
9
10
  const AUTH_URL = 'https://isortagimapi.pazarama.com/oauth/token';
@@ -22,11 +23,19 @@ export class PazaramaAPI {
22
23
  }
23
24
 
24
25
  try {
25
- const response = await axios.post(AUTH_URL, {
26
- grant_type: 'client_credentials',
27
- client_id: this.clientId,
28
- client_secret: this.clientSecret
29
- });
26
+ const response = await requestWithRetry(axios, {
27
+ method: 'POST',
28
+ url: AUTH_URL,
29
+ data: {
30
+ grant_type: 'client_credentials',
31
+ client_id: this.clientId,
32
+ client_secret: this.clientSecret
33
+ }
34
+ }, {
35
+ retries: 3,
36
+ baseDelayMs: 500,
37
+ maxDelayMs: 4000
38
+ });
30
39
 
31
40
  this.accessToken = response.data.access_token;
32
41
  this.tokenExpiry = Date.now() + (response.data.expires_in * 1000) - 60000;
@@ -39,17 +48,21 @@ export class PazaramaAPI {
39
48
  async _request(method, endpoint, data = null, params = null) {
40
49
  try {
41
50
  const token = await this._getAccessToken();
42
- const response = await axios({
43
- method,
44
- url: `${BASE_URL}${endpoint}`,
45
- headers: {
46
- 'Authorization': `Bearer ${token}`,
47
- 'Content-Type': 'application/json'
48
- },
49
- data,
50
- params
51
- });
52
- return { success: true, data: response.data };
51
+ const response = await requestWithRetry(axios, {
52
+ method,
53
+ url: `${BASE_URL}${endpoint}`,
54
+ headers: {
55
+ 'Authorization': `Bearer ${token}`,
56
+ 'Content-Type': 'application/json'
57
+ },
58
+ data,
59
+ params
60
+ }, {
61
+ retries: 3,
62
+ baseDelayMs: 500,
63
+ maxDelayMs: 4000
64
+ });
65
+ return { success: true, data: response.data };
53
66
  } catch (error) {
54
67
  return {
55
68
  success: false,
@@ -3,7 +3,8 @@
3
3
  * pttavm.com/entegrasyon
4
4
  */
5
5
 
6
- import axios from 'axios';
6
+ import axios from 'axios';
7
+ import { requestWithRetry } from './_request.js';
7
8
 
8
9
  const BASE_URL = 'https://api.pttavm.com/v1';
9
10
 
@@ -24,14 +25,18 @@ export class PttavmAPI {
24
25
 
25
26
  async _request(method, endpoint, data = null, params = null) {
26
27
  try {
27
- const response = await axios({
28
- method,
29
- url: `${BASE_URL}${endpoint}`,
30
- headers: this._headers(),
31
- data,
32
- params
33
- });
34
- return { success: true, data: response.data };
28
+ const response = await requestWithRetry(axios, {
29
+ method,
30
+ url: `${BASE_URL}${endpoint}`,
31
+ headers: this._headers(),
32
+ data,
33
+ params
34
+ }, {
35
+ retries: 3,
36
+ baseDelayMs: 500,
37
+ maxDelayMs: 4000
38
+ });
39
+ return { success: true, data: response.data };
35
40
  } catch (error) {
36
41
  return {
37
42
  success: false,
@@ -8,8 +8,9 @@
8
8
  * Rate Limit: 50 req / 10 sec per endpoint
9
9
  */
10
10
 
11
- import axios from 'axios';
12
- import { log } from '../../../core/ai-provider.js';
11
+ import axios from 'axios';
12
+ import { log } from '../../../core/ai-provider.js';
13
+ import { requestWithRetry } from './_request.js';
13
14
 
14
15
  const BASE_URL = 'https://apigw.trendyol.com/integration';
15
16
  const STAGE_URL = 'https://stageapigw.trendyol.com/integration';
@@ -56,15 +57,19 @@ export class TrendyolAPI {
56
57
  headers['Content-Type'] = 'application/json';
57
58
  }
58
59
 
59
- const response = await this.client({
60
- method,
61
- url,
62
- headers,
63
- data,
64
- params,
65
- timeout: 30000
66
- });
67
- return { success: true, data: response.data };
60
+ const response = await requestWithRetry(this.client, {
61
+ method,
62
+ url,
63
+ headers,
64
+ data,
65
+ params,
66
+ timeout: 30000
67
+ }, {
68
+ retries: 3,
69
+ baseDelayMs: 500,
70
+ maxDelayMs: 4000
71
+ });
72
+ return { success: true, data: response.data };
68
73
  } catch (error) {
69
74
  const errorMsg = error.response?.data?.errors?.[0]?.message || error.message;
70
75
  const statusCode = error.response?.status;