@lonca/trendyol 0.4.0 → 0.6.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.
package/dist/index.cjs CHANGED
@@ -234,6 +234,254 @@ function extractAttributeList(data) {
234
234
  }
235
235
  return null;
236
236
  }
237
+ function toIso(epochMs) {
238
+ if (typeof epochMs !== "number" || !Number.isFinite(epochMs) || epochMs === 0) {
239
+ return void 0;
240
+ }
241
+ return new Date(epochMs).toISOString();
242
+ }
243
+ function normalizeClaim(node) {
244
+ const out = {
245
+ id: node.id ?? node.claimId ?? "",
246
+ orderNumber: node.orderNumber ?? "",
247
+ raw: node
248
+ };
249
+ const orderDate = toIso(node.orderDate);
250
+ if (orderDate) out.orderDate = orderDate;
251
+ const claimDate = toIso(node.claimDate);
252
+ if (claimDate) out.claimDate = claimDate;
253
+ if (node.customerFirstName !== void 0) out.customerFirstName = node.customerFirstName;
254
+ if (node.customerLastName !== void 0) out.customerLastName = node.customerLastName;
255
+ return out;
256
+ }
257
+ var ClaimsResource = class {
258
+ constructor(transport, sellerId, limiter) {
259
+ this.transport = transport;
260
+ this.sellerId = sellerId;
261
+ this.limiter = limiter ?? new core.TokenBucketRateLimiter({ capacity: 1e3, intervalMs: 6e4 });
262
+ }
263
+ transport;
264
+ sellerId;
265
+ limiter;
266
+ /**
267
+ * Create a return claim against an order. Use this to file a return on
268
+ * behalf of a customer (e.g. when they called your CS line). For
269
+ * customer-initiated returns coming from trendyol.com, you receive them
270
+ * via `claims.list()` — no need to call `create`.
271
+ *
272
+ * Returns whatever Trendyol returns (typically the new claim's identifier).
273
+ *
274
+ * @throws {ValidationError} when `claimItems` is empty.
275
+ */
276
+ async create(input) {
277
+ if (!Array.isArray(input?.claimItems) || input.claimItems.length === 0) {
278
+ throw new core.ValidationError({ message: "claims.create: claimItems must not be empty" });
279
+ }
280
+ return this.transport.request({
281
+ method: "POST",
282
+ path: `/integration/order/sellers/${this.sellerId}/claims/create`,
283
+ body: input,
284
+ rateLimiter: this.limiter
285
+ });
286
+ }
287
+ /**
288
+ * File a seller-side rejection ("ret talebi") against a customer claim.
289
+ *
290
+ * **Wire format: `multipart/form-data`** — the SDK builds the FormData
291
+ * internally from the typed input. `claimItemIdList` is joined with
292
+ * commas (Trendyol expects a single comma-separated string field).
293
+ * Attach supporting docs (PDF / JPEG) via `files: [Blob, ...]`.
294
+ */
295
+ async createIssue(claimId, input) {
296
+ if (!Array.isArray(input?.claimItemIdList) || input.claimItemIdList.length === 0) {
297
+ throw new core.ValidationError({
298
+ message: "claims.createIssue: claimItemIdList must not be empty"
299
+ });
300
+ }
301
+ if (typeof input.description !== "string" || input.description.length === 0) {
302
+ throw new core.ValidationError({ message: "claims.createIssue: description is required" });
303
+ }
304
+ if (input.description.length > 500) {
305
+ throw new core.ValidationError({
306
+ message: `claims.createIssue: description must be \u2264500 chars (got ${input.description.length})`
307
+ });
308
+ }
309
+ const form = new FormData();
310
+ form.append("claimIssueReasonId", String(input.claimIssueReasonId));
311
+ form.append("claimItemIdList", input.claimItemIdList.join(","));
312
+ form.append("description", input.description);
313
+ if (input.files) {
314
+ for (const file of input.files) {
315
+ form.append("files", file);
316
+ }
317
+ }
318
+ return this.transport.request({
319
+ method: "POST",
320
+ path: `/integration/order/sellers/${this.sellerId}/claims/${encodeURIComponent(claimId)}/issue`,
321
+ body: form,
322
+ rateLimiter: this.limiter
323
+ });
324
+ }
325
+ /**
326
+ * Approve specific claim line items. After approval, Trendyol moves
327
+ * those line items into the post-approval refund / return-shipping flow.
328
+ *
329
+ * @throws {ValidationError} when `claimLineItemIdList` is empty.
330
+ */
331
+ async approveLineItems(claimId, input) {
332
+ if (!Array.isArray(input?.claimLineItemIdList) || input.claimLineItemIdList.length === 0) {
333
+ throw new core.ValidationError({
334
+ message: "claims.approveLineItems: claimLineItemIdList must not be empty"
335
+ });
336
+ }
337
+ return this.transport.request({
338
+ method: "PUT",
339
+ path: `/integration/order/sellers/${this.sellerId}/claims/${encodeURIComponent(claimId)}/items/approve`,
340
+ body: input,
341
+ rateLimiter: this.limiter
342
+ });
343
+ }
344
+ /**
345
+ * List claims (page-based; SDK exposes opaque cursor convention).
346
+ *
347
+ * @example
348
+ * ```ts
349
+ * import { paginate } from '@lonca/core';
350
+ * for await (const c of paginate((p) =>
351
+ * client.claims.list({ ...p, claimItemStatus: 'WaitingInAction' }),
352
+ * )) {
353
+ * console.log(c.id, c.orderNumber, c.claimDate);
354
+ * }
355
+ * ```
356
+ */
357
+ async list(params = {}) {
358
+ const size = Math.min(params.limit ?? 50, 200);
359
+ const page = params.cursor ? Number.parseInt(params.cursor, 10) : 0;
360
+ const query = { page, size };
361
+ if (params.startDate) query.startDate = params.startDate.getTime();
362
+ if (params.endDate) query.endDate = params.endDate.getTime();
363
+ if (params.claimItemStatus) query.claimItemStatus = params.claimItemStatus;
364
+ const data = await this.transport.request({
365
+ method: "GET",
366
+ path: `/integration/order/sellers/${this.sellerId}/claims`,
367
+ query,
368
+ rateLimiter: this.limiter
369
+ });
370
+ const items = (data.content ?? []).map(normalizeClaim);
371
+ const result = { items };
372
+ const totalPages = typeof data.totalPages === "number" ? data.totalPages : 0;
373
+ if (page + 1 < totalPages) {
374
+ result.nextCursor = String(page + 1);
375
+ }
376
+ return result;
377
+ }
378
+ /**
379
+ * Fetch the catalog of rejection-reason IDs the seller can use on
380
+ * `claims.createIssue()`. Cache the result — it changes rarely.
381
+ *
382
+ * Note: this endpoint is **not seller-scoped** (no `sellerId` in path).
383
+ */
384
+ async getIssueReasons() {
385
+ const data = await this.transport.request({
386
+ method: "GET",
387
+ path: `/integration/order/claim-issue-reasons`,
388
+ rateLimiter: this.limiter
389
+ });
390
+ return (data ?? []).map((r) => ({
391
+ id: typeof r.id === "number" ? r.id : 0,
392
+ name: r.name ?? ""
393
+ }));
394
+ }
395
+ /**
396
+ * Fetch the audit log for a single claim item (state transitions,
397
+ * actor, timestamp). Trendyol's response shape varies — the SDK
398
+ * surfaces each row as `{ raw }` and leaves field extraction to the
399
+ * caller until we observe a stable shape on the wire.
400
+ */
401
+ async getItemAudits(claimItemId) {
402
+ const data = await this.transport.request({
403
+ method: "GET",
404
+ path: `/integration/order/sellers/${this.sellerId}/claims/items/${encodeURIComponent(claimItemId)}/audit`,
405
+ rateLimiter: this.limiter
406
+ });
407
+ const rows = Array.isArray(data) ? data : Array.isArray(data?.content) ? data.content : [];
408
+ return rows.map((row) => ({ raw: row }));
409
+ }
410
+ };
411
+ function toIso2(epochMs) {
412
+ if (typeof epochMs !== "number" || !Number.isFinite(epochMs) || epochMs === 0) {
413
+ return void 0;
414
+ }
415
+ return new Date(epochMs).toISOString();
416
+ }
417
+ function normalizeRow(row) {
418
+ const out = {
419
+ id: row.id !== void 0 ? String(row.id) : "",
420
+ raw: row
421
+ };
422
+ const tx = toIso2(row.transactionDate);
423
+ if (tx) out.transactionDate = tx;
424
+ if (row.barcode !== void 0) out.barcode = row.barcode;
425
+ if (row.transactionType !== void 0) out.transactionType = row.transactionType;
426
+ if (row.receiptId !== void 0) out.receiptId = row.receiptId;
427
+ if (row.description !== void 0) out.description = row.description;
428
+ if (typeof row.debt === "number") out.debt = row.debt;
429
+ if (typeof row.credit === "number") out.credit = row.credit;
430
+ if (row.paymentPeriod !== void 0) out.paymentPeriod = row.paymentPeriod;
431
+ if (row.commissionRate !== void 0) out.commissionRate = row.commissionRate;
432
+ if (row.commissionAmount !== void 0) out.commissionAmount = row.commissionAmount;
433
+ if (row.commissionInvoiceSerialNumber !== void 0) {
434
+ out.commissionInvoiceSerialNumber = row.commissionInvoiceSerialNumber;
435
+ }
436
+ if (row.sellerRevenue !== void 0) out.sellerRevenue = row.sellerRevenue;
437
+ if (row.orderNumber !== void 0) out.orderNumber = row.orderNumber;
438
+ if (row.paymentOrderId !== void 0) out.paymentOrderId = row.paymentOrderId;
439
+ const pay = toIso2(row.paymentDate);
440
+ if (pay) out.paymentDate = pay;
441
+ if (typeof row.sellerId === "number") out.sellerId = row.sellerId;
442
+ if (row.storeId !== void 0) out.storeId = row.storeId;
443
+ if (row.storeName !== void 0) out.storeName = row.storeName;
444
+ if (row.storeAddress !== void 0) out.storeAddress = row.storeAddress;
445
+ if (row.country !== void 0) out.country = row.country;
446
+ return out;
447
+ }
448
+ var FinanceResource = class {
449
+ constructor(transport, sellerId, limiter) {
450
+ this.transport = transport;
451
+ this.sellerId = sellerId;
452
+ this.limiter = limiter ?? new core.TokenBucketRateLimiter({ capacity: 100, intervalMs: 6e4 });
453
+ }
454
+ transport;
455
+ sellerId;
456
+ limiter;
457
+ async getSettlements(params = {}) {
458
+ return this.queryPage(`/integration/sellers/${this.sellerId}/settlements`, params);
459
+ }
460
+ async getOtherFinancials(params = {}) {
461
+ return this.queryPage(`/integration/sellers/${this.sellerId}/otherfinancials`, params);
462
+ }
463
+ async queryPage(path, params) {
464
+ const size = Math.min(params.limit ?? 50, 200);
465
+ const page = params.cursor ? Number.parseInt(params.cursor, 10) : 0;
466
+ const query = { page, size };
467
+ if (params.startDate) query.startDate = params.startDate.getTime();
468
+ if (params.endDate) query.endDate = params.endDate.getTime();
469
+ if (params.transactionType) query.transactionType = params.transactionType;
470
+ const data = await this.transport.request({
471
+ method: "GET",
472
+ path,
473
+ query,
474
+ rateLimiter: this.limiter
475
+ });
476
+ const items = (data.content ?? []).map(normalizeRow);
477
+ const result = { items };
478
+ const totalPages = typeof data.totalPages === "number" ? data.totalPages : 0;
479
+ if (page + 1 < totalPages) {
480
+ result.nextCursor = String(page + 1);
481
+ }
482
+ return result;
483
+ }
484
+ };
237
485
  var MAX_ITEMS_PER_REQUEST = 1e3;
238
486
  var InventoryResource = class {
239
487
  constructor(transport, sellerId) {
@@ -273,9 +521,212 @@ var InventoryResource = class {
273
521
  return { batchRequestId: data.batchRequestId ?? "" };
274
522
  }
275
523
  };
524
+ var InvoicesResource = class {
525
+ constructor(transport, sellerId, limiter) {
526
+ this.transport = transport;
527
+ this.sellerId = sellerId;
528
+ this.limiter = limiter ?? new core.TokenBucketRateLimiter({ capacity: 500, intervalMs: 6e4 });
529
+ }
530
+ transport;
531
+ sellerId;
532
+ limiter;
533
+ /**
534
+ * Upload an invoice file for a shipment package. **Multipart**: the
535
+ * SDK builds the FormData internally from the typed input.
536
+ *
537
+ * Max 10 MB. Accepted formats: PDF, JPEG, PNG.
538
+ */
539
+ async uploadFile(input) {
540
+ if (!input?.file) {
541
+ throw new core.ValidationError({ message: "invoices.uploadFile: file is required" });
542
+ }
543
+ if (!input.shipmentPackageId) {
544
+ throw new core.ValidationError({ message: "invoices.uploadFile: shipmentPackageId is required" });
545
+ }
546
+ const form = new FormData();
547
+ form.append("shipmentPackageId", String(input.shipmentPackageId));
548
+ form.append("file", input.file);
549
+ if (input.invoiceDateTime !== void 0) {
550
+ form.append("invoiceDateTime", String(input.invoiceDateTime));
551
+ }
552
+ if (input.invoiceNumber !== void 0) {
553
+ form.append("invoiceNumber", input.invoiceNumber);
554
+ }
555
+ return this.transport.request({
556
+ method: "POST",
557
+ path: `/integration/sellers/${this.sellerId}/seller-invoice-file`,
558
+ body: form,
559
+ rateLimiter: this.limiter
560
+ });
561
+ }
562
+ /** Register an invoice URL with Trendyol (alternative to uploading the file). */
563
+ async sendLink(input) {
564
+ if (!input?.invoiceLink) {
565
+ throw new core.ValidationError({ message: "invoices.sendLink: invoiceLink is required" });
566
+ }
567
+ return this.transport.request({
568
+ method: "POST",
569
+ path: `/integration/sellers/${this.sellerId}/seller-invoice-links`,
570
+ body: input,
571
+ rateLimiter: this.limiter
572
+ });
573
+ }
574
+ /** Remove a previously-registered invoice link. */
575
+ async deleteLink(input) {
576
+ return this.transport.request({
577
+ method: "POST",
578
+ path: `/integration/sellers/${this.sellerId}/seller-invoice-links/delete`,
579
+ body: input,
580
+ rateLimiter: this.limiter
581
+ });
582
+ }
583
+ };
584
+ var LabelsResource = class {
585
+ constructor(transport, sellerId, limiter) {
586
+ this.transport = transport;
587
+ this.sellerId = sellerId;
588
+ this.limiter = limiter ?? new core.TokenBucketRateLimiter({ capacity: 100, intervalMs: 6e4 });
589
+ }
590
+ transport;
591
+ sellerId;
592
+ limiter;
593
+ /**
594
+ * Request a common ZPL label for a cargo tracking number. After this
595
+ * returns, call `getCommon()` with the same `cargoTrackingNumber` to
596
+ * retrieve the generated label.
597
+ *
598
+ * @throws {ValidationError} when `format` is missing.
599
+ */
600
+ async createCommon(cargoTrackingNumber, input) {
601
+ if (!input?.format) {
602
+ throw new core.ValidationError({ message: "labels.createCommon: format is required" });
603
+ }
604
+ return this.transport.request({
605
+ method: "POST",
606
+ path: `/integration/sellers/${this.sellerId}/common-label/${encodeURIComponent(String(cargoTrackingNumber))}`,
607
+ body: input,
608
+ rateLimiter: this.limiter
609
+ });
610
+ }
611
+ /**
612
+ * Retrieve the previously-created common label. Trendyol returns
613
+ * `{ data: [{ label, format }] }`; the SDK surfaces the array as
614
+ * `labels[]` for ergonomic access.
615
+ *
616
+ * Typically `labels.length === 1` per tracking number, but kept as an
617
+ * array to match the wire shape.
618
+ */
619
+ async getCommon(cargoTrackingNumber) {
620
+ const raw = await this.transport.request({
621
+ method: "GET",
622
+ path: `/integration/sellers/${this.sellerId}/common-label/${encodeURIComponent(String(cargoTrackingNumber))}`,
623
+ rateLimiter: this.limiter
624
+ });
625
+ const labels = (raw?.data ?? []).map((row) => ({
626
+ label: row.label ?? "",
627
+ format: row.format ?? "ZPL"
628
+ }));
629
+ return { labels, raw: raw ?? {} };
630
+ }
631
+ };
632
+ function n(rows, extract) {
633
+ const list = Array.isArray(rows) ? rows : [];
634
+ return list.map((r) => {
635
+ const node = r;
636
+ return { ...extract(node), raw: node };
637
+ });
638
+ }
639
+ var LocationsResource = class {
640
+ constructor(transport, limiter) {
641
+ this.transport = transport;
642
+ this.limiter = limiter ?? new core.TokenBucketRateLimiter({ capacity: 60, intervalMs: 6e4 });
643
+ }
644
+ transport;
645
+ limiter;
646
+ /** List all supported countries (Türkiye + AZ + GULF + CEE). */
647
+ async getCountries() {
648
+ const data = await this.transport.request({
649
+ method: "GET",
650
+ path: `/integration/member/countries`,
651
+ rateLimiter: this.limiter
652
+ });
653
+ return n(data, (node) => ({
654
+ code: String(node.code ?? node.id ?? ""),
655
+ name: node.name
656
+ }));
657
+ }
658
+ // ─── Domestic (TR / AZ) ───────────────────────────────────────────────
659
+ async getTurkeyCities() {
660
+ return this.cities(`/integration/member/countries/domestic/TR/cities`);
661
+ }
662
+ async getTurkeyDistricts(cityCode) {
663
+ return this.districts(
664
+ `/integration/member/countries/domestic/TR/cities/${encodeURIComponent(String(cityCode))}/districts`
665
+ );
666
+ }
667
+ async getTurkeyNeighborhoods(cityCode, districtCode) {
668
+ return this.neighborhoods(
669
+ `/integration/member/countries/domestic/TR/cities/${encodeURIComponent(String(cityCode))}/districts/${encodeURIComponent(String(districtCode))}/neighborhoods`
670
+ );
671
+ }
672
+ async getAzerbaijanCities() {
673
+ return this.cities(`/integration/member/countries/domestic/AZ/cities`);
674
+ }
675
+ async getAzerbaijanDistricts(cityCode) {
676
+ return this.districts(
677
+ `/integration/member/countries/domestic/AZ/cities/${encodeURIComponent(String(cityCode))}/districts`
678
+ );
679
+ }
680
+ // ─── International (GULF / CEE) ───────────────────────────────────────
681
+ async getCitiesByCountry(countryCode) {
682
+ return this.cities(`/integration/member/countries/${encodeURIComponent(countryCode)}/cities`);
683
+ }
684
+ async getDistrictsByCity(countryCode, cityId) {
685
+ return this.districts(
686
+ `/integration/member/countries/${encodeURIComponent(countryCode)}/cities/${encodeURIComponent(String(cityId))}/districts`
687
+ );
688
+ }
689
+ // ─── Shared paginators ────────────────────────────────────────────────
690
+ async cities(path) {
691
+ const data = await this.transport.request({
692
+ method: "GET",
693
+ path,
694
+ rateLimiter: this.limiter
695
+ });
696
+ return n(data, (node) => ({
697
+ code: String(node.code ?? node.id ?? ""),
698
+ name: node.name,
699
+ countryCode: node.countryCode
700
+ }));
701
+ }
702
+ async districts(path) {
703
+ const data = await this.transport.request({
704
+ method: "GET",
705
+ path,
706
+ rateLimiter: this.limiter
707
+ });
708
+ return n(data, (node) => ({
709
+ code: String(node.code ?? node.id ?? ""),
710
+ name: node.name,
711
+ cityCode: node.cityCode !== void 0 ? String(node.cityCode) : void 0
712
+ }));
713
+ }
714
+ async neighborhoods(path) {
715
+ const data = await this.transport.request({
716
+ method: "GET",
717
+ path,
718
+ rateLimiter: this.limiter
719
+ });
720
+ return n(data, (node) => ({
721
+ code: String(node.code ?? node.id ?? ""),
722
+ name: node.name,
723
+ districtCode: node.districtCode !== void 0 ? String(node.districtCode) : void 0
724
+ }));
725
+ }
726
+ };
276
727
  var MAX_PAGE_SIZE = 200;
277
728
  var DEFAULT_PAGE_SIZE2 = 50;
278
- function toIso(epochMs) {
729
+ function toIso3(epochMs) {
279
730
  if (typeof epochMs !== "number" || !Number.isFinite(epochMs) || epochMs === 0) {
280
731
  return void 0;
281
732
  }
@@ -343,7 +794,7 @@ function normalizeLine(node) {
343
794
  function normalizeHistory(node) {
344
795
  const out = { raw: node };
345
796
  if (node.status !== void 0) out.status = node.status;
346
- const createdAt = toIso(node.createdDate);
797
+ const createdAt = toIso3(node.createdDate);
347
798
  if (createdAt) out.createdAt = createdAt;
348
799
  return out;
349
800
  }
@@ -358,6 +809,9 @@ function normalizeCustomer(node) {
358
809
  if (node.identityNumber !== void 0) out.identityNumber = node.identityNumber;
359
810
  return out;
360
811
  }
812
+ function normalizeShipmentPackage(rawNode) {
813
+ return normalizePackage(rawNode ?? {});
814
+ }
361
815
  function normalizePackage(node) {
362
816
  const pkgId = node.shipmentPackageId ?? node.id;
363
817
  const out = {
@@ -365,8 +819,8 @@ function normalizePackage(node) {
365
819
  orderNumber: node.orderNumber ?? "",
366
820
  status: node.status ?? "",
367
821
  customer: normalizeCustomer(node),
368
- orderDate: toIso(node.orderDate) ?? "",
369
- lastModifiedDate: toIso(node.lastModifiedDate) ?? "",
822
+ orderDate: toIso3(node.orderDate) ?? "",
823
+ lastModifiedDate: toIso3(node.lastModifiedDate) ?? "",
370
824
  currencyCode: node.currencyCode ?? "",
371
825
  packageTotalPrice: typeof node.packageTotalPrice === "number" ? node.packageTotalPrice : 0,
372
826
  packageGrossAmount: typeof node.packageGrossAmount === "number" ? node.packageGrossAmount : 0,
@@ -386,13 +840,13 @@ function normalizePackage(node) {
386
840
  if (node.shipmentPackageStatus !== void 0) {
387
841
  out.shipmentPackageStatus = node.shipmentPackageStatus;
388
842
  }
389
- const agreed = toIso(node.agreedDeliveryDate);
843
+ const agreed = toIso3(node.agreedDeliveryDate);
390
844
  if (agreed) out.agreedDeliveryDate = agreed;
391
- const estStart = toIso(node.estimatedDeliveryStartDate);
845
+ const estStart = toIso3(node.estimatedDeliveryStartDate);
392
846
  if (estStart) out.estimatedDeliveryStartDate = estStart;
393
- const estEnd = toIso(node.estimatedDeliveryEndDate);
847
+ const estEnd = toIso3(node.estimatedDeliveryEndDate);
394
848
  if (estEnd) out.estimatedDeliveryEndDate = estEnd;
395
- const origin = toIso(node.originShipmentDate);
849
+ const origin = toIso3(node.originShipmentDate);
396
850
  if (origin) out.originShipmentDate = origin;
397
851
  const invoice = normalizeAddress(node.invoiceAddress);
398
852
  if (invoice) out.invoiceAddress = invoice;
@@ -802,6 +1256,101 @@ var OrdersResource = class {
802
1256
  }
803
1257
  return result;
804
1258
  }
1259
+ /**
1260
+ * Notify Trendyol that a shipped package was returned to you (manual
1261
+ * return flow, e.g. customer dropped it at your address or you got the
1262
+ * package back without going through Trendyol's return cargo).
1263
+ *
1264
+ * No body; Trendyol responds with 200 + empty body on success.
1265
+ */
1266
+ async manualReturnByPackageId(packageId) {
1267
+ await this.transport.request({
1268
+ method: "PUT",
1269
+ path: `${this.packagePath(packageId)}/manual-return`,
1270
+ rateLimiter: this.limiter
1271
+ });
1272
+ }
1273
+ /**
1274
+ * Manual-return variant that takes the cargo tracking number instead of
1275
+ * the package ID. Useful when the cargo provider's webhook only carries
1276
+ * the tracking number.
1277
+ *
1278
+ * Sibling path (not under `/{packageId}/...`).
1279
+ */
1280
+ async manualReturnByTrackingNumber(cargoTrackingNumber) {
1281
+ await this.transport.request({
1282
+ method: "PUT",
1283
+ path: `/integration/order/sellers/${this.sellerId}/shipment-packages/manual-return-by-tracking-number/${encodeURIComponent(String(cargoTrackingNumber))}`,
1284
+ rateLimiter: this.limiter
1285
+ });
1286
+ }
1287
+ /**
1288
+ * Fetch Trendyol Express compensation tickets (claims filed when a
1289
+ * shipment is lost or damaged in transit). Page-based pagination
1290
+ * internally; the SDK exposes the cursor convention.
1291
+ *
1292
+ * Note the different base path — `/integration/tex/compensation/...`,
1293
+ * not the regular `/integration/order/...`.
1294
+ *
1295
+ * @example
1296
+ * ```ts
1297
+ * import { paginate } from '@lonca/core';
1298
+ * const tickets = await client.orders.getCompensationTickets({
1299
+ * startDate: new Date('2026-01-01'),
1300
+ * endDate: new Date('2026-02-01'),
1301
+ * });
1302
+ * for (const t of tickets.items) {
1303
+ * console.log(t.orderNumber, t.currentState, t.stateMessage);
1304
+ * }
1305
+ * ```
1306
+ */
1307
+ async getCompensationTickets(params = {}) {
1308
+ const size = Math.min(params.limit ?? 200, 200);
1309
+ const page = params.cursor ? Number.parseInt(params.cursor, 10) : 0;
1310
+ const query = { page, size };
1311
+ if (params.startDate) query.startDate = params.startDate.getTime();
1312
+ if (params.endDate) query.endDate = params.endDate.getTime();
1313
+ const res = await this.transport.request({
1314
+ method: "GET",
1315
+ path: `/integration/tex/compensation/sellers/${this.sellerId}/tickets`,
1316
+ query,
1317
+ rateLimiter: this.limiter
1318
+ });
1319
+ const tickets = Array.isArray(res.data) ? res.data : res.data?.items ?? res.data?.content ?? res.content ?? [];
1320
+ const items = tickets.map((t) => {
1321
+ const itemDetails = (t.itemDetails ?? []).map((d) => {
1322
+ const out2 = {};
1323
+ if (typeof d.itemAmount === "number") out2.itemAmount = d.itemAmount;
1324
+ if (d.itemCode !== void 0) out2.itemCode = d.itemCode;
1325
+ if (typeof d.itemCount === "number") out2.itemCount = d.itemCount;
1326
+ if (d.itemName !== void 0) out2.itemName = d.itemName;
1327
+ return out2;
1328
+ });
1329
+ const out = {
1330
+ itemDetails,
1331
+ raw: t
1332
+ };
1333
+ if (t.cargoProvider !== void 0) out.cargoProvider = t.cargoProvider;
1334
+ if (t.compensateReason !== void 0) out.compensateReason = t.compensateReason;
1335
+ const createdAt = toIso3(t.createDate);
1336
+ if (createdAt) out.createdAt = createdAt;
1337
+ if (t.currentState !== void 0) {
1338
+ out.currentState = t.currentState;
1339
+ }
1340
+ if (t.deliveryNumber !== void 0) out.deliveryNumber = t.deliveryNumber;
1341
+ if (t.orderNumber !== void 0) out.orderNumber = t.orderNumber;
1342
+ if (t.requestedBy !== void 0) out.requestedBy = t.requestedBy;
1343
+ if (t.stateMessage !== void 0) out.stateMessage = t.stateMessage;
1344
+ if (t.totalItemsAmount !== void 0) out.totalItemsAmount = t.totalItemsAmount;
1345
+ return out;
1346
+ });
1347
+ const result = { items };
1348
+ const total = typeof res.totalCount === "number" ? res.totalCount : 0;
1349
+ if ((page + 1) * size < total) {
1350
+ result.nextCursor = String(page + 1);
1351
+ }
1352
+ return result;
1353
+ }
805
1354
  packagePath(packageId) {
806
1355
  return `/integration/order/sellers/${this.sellerId}/shipment-packages/${encodeURIComponent(String(packageId))}`;
807
1356
  }
@@ -851,7 +1400,7 @@ function normalizeVariant(variant) {
851
1400
  if (stock !== void 0) out.stock = stock;
852
1401
  return out;
853
1402
  }
854
- function toIso2(epochMs) {
1403
+ function toIso4(epochMs) {
855
1404
  if (typeof epochMs !== "number" || !Number.isFinite(epochMs)) return void 0;
856
1405
  return new Date(epochMs).toISOString();
857
1406
  }
@@ -865,8 +1414,8 @@ function normalizeProduct(node) {
865
1414
  images: normalizeImages(node.images),
866
1415
  attributes: (node.attributes ?? []).map(normalizeAttribute2),
867
1416
  variants: (node.variants ?? []).map(normalizeVariant),
868
- createdAt: toIso2(node.creationDate) ?? "",
869
- updatedAt: toIso2(node.lastModifiedDate) ?? "",
1417
+ createdAt: toIso4(node.creationDate) ?? "",
1418
+ updatedAt: toIso4(node.lastModifiedDate) ?? "",
870
1419
  raw: node
871
1420
  };
872
1421
  if (node.description !== void 0) out.description = node.description;
@@ -912,13 +1461,13 @@ function normalizeUnapproved(node) {
912
1461
  out.specialConsumptionTax = node.specialConsumptionTax;
913
1462
  }
914
1463
  if (node.sgrPrice !== void 0) out.sgrPrice = node.sgrPrice;
915
- const createdAt = toIso2(node.createDateTime);
1464
+ const createdAt = toIso4(node.createDateTime);
916
1465
  if (createdAt) out.createdAt = createdAt;
917
- const updatedAt = toIso2(node.lastUpdateDate);
1466
+ const updatedAt = toIso4(node.lastUpdateDate);
918
1467
  if (updatedAt) out.updatedAt = updatedAt;
919
- const priceChanged = toIso2(node.lastPriceChangeDate);
1468
+ const priceChanged = toIso4(node.lastPriceChangeDate);
920
1469
  if (priceChanged) out.lastPriceChangedAt = priceChanged;
921
- const stockChanged = toIso2(node.lastStockChangeDate);
1470
+ const stockChanged = toIso4(node.lastStockChangeDate);
922
1471
  if (stockChanged) out.lastStockChangedAt = stockChanged;
923
1472
  return out;
924
1473
  }
@@ -943,7 +1492,7 @@ function normalizeProductBase(data) {
943
1492
  archived: !!data.archived,
944
1493
  raw: data
945
1494
  };
946
- const approvedAt = toIso2(data.approvedDate);
1495
+ const approvedAt = toIso4(data.approvedDate);
947
1496
  if (approvedAt) out.approvedAt = approvedAt;
948
1497
  if (data.listingId !== void 0) out.listingId = data.listingId;
949
1498
  if (data.contentId !== void 0) out.contentId = String(data.contentId);
@@ -965,9 +1514,9 @@ function normalizeBatchResult(data) {
965
1514
  };
966
1515
  if (typeof data.itemCount === "number") out.itemCount = data.itemCount;
967
1516
  if (typeof data.failedItemCount === "number") out.failedItemCount = data.failedItemCount;
968
- const createdAt = toIso2(data.creationDate);
1517
+ const createdAt = toIso4(data.creationDate);
969
1518
  if (createdAt) out.createdAt = createdAt;
970
- const lastModifiedAt = toIso2(data.lastModification);
1519
+ const lastModifiedAt = toIso4(data.lastModification);
971
1520
  if (lastModifiedAt) out.lastModifiedAt = lastModifiedAt;
972
1521
  if (data.sourceType !== void 0) out.sourceType = data.sourceType;
973
1522
  if (data.batchRequestType !== void 0) out.batchRequestType = data.batchRequestType;
@@ -1313,6 +1862,120 @@ var ProductsResource = class {
1313
1862
  return { batchRequestId: data?.batchRequestId ?? "" };
1314
1863
  }
1315
1864
  };
1865
+ function toIso5(epochMs) {
1866
+ if (typeof epochMs !== "number" || !Number.isFinite(epochMs) || epochMs === 0) {
1867
+ return void 0;
1868
+ }
1869
+ return new Date(epochMs).toISOString();
1870
+ }
1871
+ function normalizeAnswer(a) {
1872
+ if (!a) return void 0;
1873
+ const out = {};
1874
+ if (a.text !== void 0) out.text = a.text;
1875
+ const createdAt = toIso5(a.creationDate);
1876
+ if (createdAt) out.createdAt = createdAt;
1877
+ if (a.status !== void 0) out.status = a.status;
1878
+ return out;
1879
+ }
1880
+ function normalizeQuestion(node) {
1881
+ const out = {
1882
+ id: node.id !== void 0 ? String(node.id) : "",
1883
+ raw: node
1884
+ };
1885
+ if (node.text !== void 0) out.text = node.text;
1886
+ if (node.customerId !== void 0) out.customerId = String(node.customerId);
1887
+ if (node.userName !== void 0) out.userName = node.userName;
1888
+ if (typeof node.showUserName === "boolean") out.showUserName = node.showUserName;
1889
+ if (node.status !== void 0) out.status = node.status;
1890
+ if (typeof node.public === "boolean") out.public = node.public;
1891
+ if (node.productMainId !== void 0) out.productMainId = node.productMainId;
1892
+ if (node.productName !== void 0) out.productName = node.productName;
1893
+ if (node.imageUrl !== void 0) out.imageUrl = node.imageUrl;
1894
+ if (node.webUrl !== void 0) out.webUrl = node.webUrl;
1895
+ const createdAt = toIso5(node.creationDate);
1896
+ if (createdAt) out.createdAt = createdAt;
1897
+ if (node.answeredDateMessage !== void 0) out.answeredDateMessage = node.answeredDateMessage;
1898
+ const answer = normalizeAnswer(node.answer);
1899
+ if (answer) out.answer = answer;
1900
+ const rejectedAnswer = normalizeAnswer(node.rejectedAnswer);
1901
+ if (rejectedAnswer) out.rejectedAnswer = rejectedAnswer;
1902
+ const rejectedAt = toIso5(node.rejectedDate);
1903
+ if (rejectedAt) out.rejectedAt = rejectedAt;
1904
+ if (node.reason !== void 0) out.reason = node.reason;
1905
+ if (node.reportReason !== void 0) out.reportReason = node.reportReason;
1906
+ const reportedAt = toIso5(node.reportedDate);
1907
+ if (reportedAt) out.reportedAt = reportedAt;
1908
+ return out;
1909
+ }
1910
+ var QuestionsResource = class {
1911
+ constructor(transport, sellerId, limiter) {
1912
+ this.transport = transport;
1913
+ this.sellerId = sellerId;
1914
+ this.limiter = limiter ?? new core.TokenBucketRateLimiter({ capacity: 500, intervalMs: 6e4 });
1915
+ }
1916
+ transport;
1917
+ sellerId;
1918
+ limiter;
1919
+ /** Fetch a single question by its numeric ID. */
1920
+ async get(questionId) {
1921
+ const data = await this.transport.request({
1922
+ method: "GET",
1923
+ path: `/integration/qna/sellers/${this.sellerId}/questions/${encodeURIComponent(String(questionId))}`,
1924
+ rateLimiter: this.limiter
1925
+ });
1926
+ return normalizeQuestion(data);
1927
+ }
1928
+ /**
1929
+ * Filter questions by barcode / date range / status. Page-based
1930
+ * pagination internally; SDK exposes the opaque-cursor convention.
1931
+ */
1932
+ async list(params = {}) {
1933
+ const size = Math.min(params.limit ?? 50, 200);
1934
+ const page = params.cursor ? Number.parseInt(params.cursor, 10) : 0;
1935
+ const query = { page, size };
1936
+ if (params.barcode) query.barcode = params.barcode;
1937
+ if (params.startDate) query.startDate = params.startDate.getTime();
1938
+ if (params.endDate) query.endDate = params.endDate.getTime();
1939
+ if (params.status) query.status = params.status;
1940
+ const data = await this.transport.request({
1941
+ method: "GET",
1942
+ path: `/integration/qna/sellers/${this.sellerId}/questions/filter`,
1943
+ query,
1944
+ rateLimiter: this.limiter
1945
+ });
1946
+ const items = (data.content ?? []).map(normalizeQuestion);
1947
+ const result = { items };
1948
+ const totalPages = typeof data.totalPages === "number" ? data.totalPages : 0;
1949
+ if (page + 1 < totalPages) {
1950
+ result.nextCursor = String(page + 1);
1951
+ }
1952
+ return result;
1953
+ }
1954
+ /**
1955
+ * Reply to a question. Trendyol enforces 10–2000 characters on the
1956
+ * answer text; the SDK pre-validates client-side.
1957
+ *
1958
+ * @throws {ValidationError} when `text` is outside the 10–2000 char range.
1959
+ */
1960
+ async answer(questionId, text) {
1961
+ if (typeof text !== "string" || text.length < 10) {
1962
+ throw new core.ValidationError({
1963
+ message: `questions.answer: text must be at least 10 chars (got ${text?.length ?? 0})`
1964
+ });
1965
+ }
1966
+ if (text.length > 2e3) {
1967
+ throw new core.ValidationError({
1968
+ message: `questions.answer: text must be at most 2000 chars (got ${text.length})`
1969
+ });
1970
+ }
1971
+ return this.transport.request({
1972
+ method: "POST",
1973
+ path: `/integration/qna/sellers/${this.sellerId}/questions/${encodeURIComponent(String(questionId))}/answers`,
1974
+ body: { text },
1975
+ rateLimiter: this.limiter
1976
+ });
1977
+ }
1978
+ };
1316
1979
  var VALID_TYPES = /* @__PURE__ */ new Set([
1317
1980
  "SHIPMENT",
1318
1981
  "RETURNING",
@@ -1393,6 +2056,170 @@ var SuppliersResource = class {
1393
2056
  return items;
1394
2057
  }
1395
2058
  };
2059
+ var TestOrdersResource = class {
2060
+ constructor(transport, sellerId, limiter) {
2061
+ this.transport = transport;
2062
+ this.sellerId = sellerId;
2063
+ this.limiter = limiter ?? new core.TokenBucketRateLimiter({ capacity: 60, intervalMs: 6e4 });
2064
+ }
2065
+ transport;
2066
+ sellerId;
2067
+ limiter;
2068
+ /**
2069
+ * Create a test order with the given customer / addresses / lines. The
2070
+ * SDK forwards the typed payload verbatim — drill into Trendyol's
2071
+ * `createTestOrder` doc for inner field rules.
2072
+ *
2073
+ * @throws {ValidationError} when required top-level fields are missing.
2074
+ */
2075
+ async create(input) {
2076
+ for (const k of ["customer", "invoiceAddress", "shippingAddress", "seller", "lines"]) {
2077
+ if (!input?.[k]) {
2078
+ throw new core.ValidationError({ message: `testOrders.create: ${k} is required` });
2079
+ }
2080
+ }
2081
+ return this.transport.request({
2082
+ method: "POST",
2083
+ path: `/integration/test/order/orders/core`,
2084
+ body: input,
2085
+ rateLimiter: this.limiter
2086
+ });
2087
+ }
2088
+ /** Push a test shipment package to the given status. */
2089
+ async updateStatus(packageId, status) {
2090
+ return this.transport.request({
2091
+ method: "PUT",
2092
+ path: `/integration/test/order/sellers/${this.sellerId}/shipment-packages/${encodeURIComponent(String(packageId))}/status`,
2093
+ body: { status },
2094
+ rateLimiter: this.limiter
2095
+ });
2096
+ }
2097
+ /** Move test claims to the `WaitingInAction` state. */
2098
+ async setClaimsWaitingInAction() {
2099
+ return this.transport.request({
2100
+ method: "PUT",
2101
+ path: `/integration/test/order/sellers/${this.sellerId}/claims/waiting-in-action`,
2102
+ rateLimiter: this.limiter
2103
+ });
2104
+ }
2105
+ };
2106
+ function normalizeWebhook(node) {
2107
+ const out = {
2108
+ id: node.id !== void 0 ? String(node.id) : "",
2109
+ raw: node
2110
+ };
2111
+ if (node.url !== void 0) out.url = node.url;
2112
+ if (node.authenticationType !== void 0) out.authenticationType = node.authenticationType;
2113
+ if (node.username !== void 0) out.username = node.username;
2114
+ if (node.apiKey !== void 0) out.apiKey = node.apiKey;
2115
+ if (node.subscribedStatuses !== void 0) out.subscribedStatuses = node.subscribedStatuses;
2116
+ if (typeof node.active === "boolean") out.active = node.active;
2117
+ else if (typeof node.isActive === "boolean") out.active = node.isActive;
2118
+ else if (typeof node.status === "string") out.active = node.status.toUpperCase() === "ACTIVE";
2119
+ return out;
2120
+ }
2121
+ var WebhooksResource = class {
2122
+ constructor(transport, sellerId, limiter) {
2123
+ this.transport = transport;
2124
+ this.sellerId = sellerId;
2125
+ this.limiter = limiter ?? new core.TokenBucketRateLimiter({ capacity: 50, intervalMs: 6e4 });
2126
+ }
2127
+ transport;
2128
+ sellerId;
2129
+ limiter;
2130
+ /**
2131
+ * Create a new webhook subscription. Trendyol caps subscriptions at 15
2132
+ * per seller — the SDK does NOT pre-check (you'd need to call `list()`
2133
+ * first), but Trendyol returns 400 when the cap is exceeded.
2134
+ *
2135
+ * @throws {ValidationError} when `url` or `authenticationType` is missing.
2136
+ */
2137
+ async create(input) {
2138
+ this.validateInput(input, "create");
2139
+ return this.transport.request({
2140
+ method: "POST",
2141
+ path: `/integration/sellers/${this.sellerId}/webhooks`,
2142
+ body: input,
2143
+ rateLimiter: this.limiter
2144
+ });
2145
+ }
2146
+ /** List all registered webhook subscriptions. */
2147
+ async list() {
2148
+ const data = await this.transport.request({
2149
+ method: "GET",
2150
+ path: `/integration/sellers/${this.sellerId}/webhooks`,
2151
+ rateLimiter: this.limiter
2152
+ });
2153
+ const rows = Array.isArray(data) ? data : Array.isArray(data?.webhooks) ? data.webhooks : Array.isArray(data?.content) ? data.content : [];
2154
+ return rows.map((r) => normalizeWebhook(r));
2155
+ }
2156
+ /**
2157
+ * Update a webhook subscription. Same input shape as `create`; replaces
2158
+ * the whole subscription (Trendyol does NOT partially update).
2159
+ */
2160
+ async update(webhookId, input) {
2161
+ this.validateInput(input, "update");
2162
+ return this.transport.request({
2163
+ method: "PUT",
2164
+ path: this.webhookPath(webhookId),
2165
+ body: input,
2166
+ rateLimiter: this.limiter
2167
+ });
2168
+ }
2169
+ /** Permanently delete a webhook subscription. */
2170
+ async delete(webhookId) {
2171
+ return this.transport.request({
2172
+ method: "DELETE",
2173
+ path: this.webhookPath(webhookId),
2174
+ rateLimiter: this.limiter
2175
+ });
2176
+ }
2177
+ /** Re-activate a previously-deactivated webhook subscription. */
2178
+ async activate(webhookId) {
2179
+ return this.transport.request({
2180
+ method: "PUT",
2181
+ path: `${this.webhookPath(webhookId)}/activate`,
2182
+ rateLimiter: this.limiter
2183
+ });
2184
+ }
2185
+ /**
2186
+ * Deactivate a webhook subscription. Trendyol automatically deactivates
2187
+ * a subscription after persistent delivery failures (and sends 2 emails);
2188
+ * use `activate()` to bring it back online once your endpoint is healthy.
2189
+ */
2190
+ async deactivate(webhookId) {
2191
+ return this.transport.request({
2192
+ method: "PUT",
2193
+ path: `${this.webhookPath(webhookId)}/deactivate`,
2194
+ rateLimiter: this.limiter
2195
+ });
2196
+ }
2197
+ validateInput(input, method) {
2198
+ if (!input?.url || typeof input.url !== "string") {
2199
+ throw new core.ValidationError({ message: `webhooks.${method}: url is required` });
2200
+ }
2201
+ if (input.authenticationType !== "BASIC_AUTHENTICATION" && input.authenticationType !== "API_KEY") {
2202
+ throw new core.ValidationError({
2203
+ message: `webhooks.${method}: authenticationType must be 'BASIC_AUTHENTICATION' or 'API_KEY'`
2204
+ });
2205
+ }
2206
+ if (input.authenticationType === "BASIC_AUTHENTICATION") {
2207
+ if (!input.username || !input.password) {
2208
+ throw new core.ValidationError({
2209
+ message: `webhooks.${method}: BASIC_AUTHENTICATION requires username + password`
2210
+ });
2211
+ }
2212
+ } else if (!input.apiKey) {
2213
+ throw new core.ValidationError({
2214
+ message: `webhooks.${method}: API_KEY requires apiKey`
2215
+ });
2216
+ }
2217
+ if (input.subscribedStatuses && input.subscribedStatuses.length === 0) ;
2218
+ }
2219
+ webhookPath(webhookId) {
2220
+ return `/integration/sellers/${this.sellerId}/webhooks/${encodeURIComponent(String(webhookId))}`;
2221
+ }
2222
+ };
1396
2223
 
1397
2224
  // src/auth.ts
1398
2225
  function buildAuthHeader(apiKey, apiSecret) {
@@ -1485,7 +2312,12 @@ var TrendyolTransport = class {
1485
2312
  signal: this.composeSignal(opts.signal)
1486
2313
  };
1487
2314
  if (opts.body !== void 0 && opts.method !== "GET") {
1488
- init.body = JSON.stringify(opts.body);
2315
+ if (opts.body instanceof FormData) {
2316
+ init.body = opts.body;
2317
+ delete headers["Content-Type"];
2318
+ } else {
2319
+ init.body = JSON.stringify(opts.body);
2320
+ }
1489
2321
  }
1490
2322
  this.logger.debug("trendyol.request", {
1491
2323
  method: opts.method,
@@ -1600,16 +2432,68 @@ function createTrendyolClient(opts) {
1600
2432
  suppliers: new SuppliersResource(transport, opts.sellerId),
1601
2433
  products: new ProductsResource(transport, opts.sellerId),
1602
2434
  inventory: new InventoryResource(transport, opts.sellerId),
1603
- orders: new OrdersResource(transport, opts.sellerId)
2435
+ orders: new OrdersResource(transport, opts.sellerId),
2436
+ claims: new ClaimsResource(transport, opts.sellerId),
2437
+ webhooks: new WebhooksResource(transport, opts.sellerId),
2438
+ questions: new QuestionsResource(transport, opts.sellerId),
2439
+ invoices: new InvoicesResource(transport, opts.sellerId),
2440
+ finance: new FinanceResource(transport, opts.sellerId),
2441
+ labels: new LabelsResource(transport, opts.sellerId),
2442
+ testOrders: new TestOrdersResource(transport, opts.sellerId),
2443
+ locations: new LocationsResource(transport)
2444
+ };
2445
+ }
2446
+ function parseWebhookEvent(rawBody) {
2447
+ let body;
2448
+ if (typeof rawBody === "string") {
2449
+ try {
2450
+ body = JSON.parse(rawBody);
2451
+ } catch {
2452
+ throw new core.ValidationError({
2453
+ message: "parseWebhookEvent: rawBody is not valid JSON"
2454
+ });
2455
+ }
2456
+ } else if (rawBody && typeof rawBody === "object") {
2457
+ body = rawBody;
2458
+ } else {
2459
+ throw new core.ValidationError({
2460
+ message: "parseWebhookEvent: rawBody must be an object or JSON string"
2461
+ });
2462
+ }
2463
+ const content = body.content;
2464
+ if (!Array.isArray(content)) {
2465
+ throw new core.ValidationError({
2466
+ message: "parseWebhookEvent: body.content must be an array"
2467
+ });
2468
+ }
2469
+ return {
2470
+ packages: content.map(normalizeShipmentPackage),
2471
+ pageInfo: {
2472
+ totalElements: typeof body.totalElements === "number" ? body.totalElements : void 0,
2473
+ totalPages: typeof body.totalPages === "number" ? body.totalPages : void 0,
2474
+ page: typeof body.page === "number" ? body.page : void 0,
2475
+ size: typeof body.size === "number" ? body.size : void 0
2476
+ },
2477
+ raw: body
1604
2478
  };
1605
2479
  }
1606
2480
 
1607
2481
  exports.BrandsResource = BrandsResource;
1608
2482
  exports.CategoriesResource = CategoriesResource;
2483
+ exports.ClaimsResource = ClaimsResource;
2484
+ exports.FinanceResource = FinanceResource;
1609
2485
  exports.InventoryResource = InventoryResource;
2486
+ exports.InvoicesResource = InvoicesResource;
2487
+ exports.LabelsResource = LabelsResource;
2488
+ exports.LocationsResource = LocationsResource;
1610
2489
  exports.OrdersResource = OrdersResource;
1611
2490
  exports.ProductsResource = ProductsResource;
2491
+ exports.QuestionsResource = QuestionsResource;
1612
2492
  exports.SuppliersResource = SuppliersResource;
2493
+ exports.TestOrdersResource = TestOrdersResource;
2494
+ exports.WebhooksResource = WebhooksResource;
1613
2495
  exports.createTrendyolClient = createTrendyolClient;
2496
+ exports.normalizeShipmentPackage = normalizeShipmentPackage;
2497
+ exports.parseWebhookEvent = parseWebhookEvent;
1614
2498
  //# sourceMappingURL=index.cjs.map
1615
2499
  //# sourceMappingURL=index.cjs.map