idosell 0.4.38 → 0.4.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  This package wraps around the Idosell REST Api to make it easier to use by implementing chainable options, more intuitive methods and helpers to format requests more easily. [Official Idosell documentation](https://idosell.readme.io/docs) is still applicable for the most part.
4
4
 
5
- Visit [This page](https://idosell-converter.vercel.app/) for more detailed usage and examples.
6
-
7
5
  [![npm version](https://img.shields.io/npm/v/idosell.svg)](https://www.npmjs.com/package/idosell)
8
6
 
9
7
  ## Basic use
@@ -17,7 +15,7 @@ const idosellRequest = idosell('SHOP_URL', 'API_KEY', API_VERSION)
17
15
 
18
16
  **API_KEY** can be obtained in your Idosell panel.
19
17
  **SHOP_URL** is the base URI of your shop.
20
- **API_VERSION** version of the API to call, current default version is **v7**
18
+ **API_VERSION** version of the API to call, current default version is **v8**
21
19
  Here are some examples:
22
20
  ```
23
21
  https://yourdomain.com
@@ -353,6 +351,26 @@ const orderRequest = idosellRequest.searchOrders.ordersSerialNumbers([123, 456,
353
351
  // Will return Object: { ordersSerialNumbers: [ 123, 456, 789 ] }
354
352
  ```
355
353
 
354
+ ## Webhooks
355
+
356
+ The package provides a convenient `webhooks` helper to handle Idosell webhook events with full TypeScript typings.
357
+
358
+ ```javascript
359
+ import { webhooks, type IaiWebhookHeaders } from "idosell";
360
+
361
+ // Validate incoming webhook request headers and handle events
362
+ webhooks
363
+ .validateHeaders((headers) => headers.token === TOKEN) // header validation
364
+ .on("productUpdated", ({ headers, body }) => {
365
+ console.log({ panelId: headers.panelId, code: body.results[0].productDisplayedCode });
366
+ })
367
+ .on("orderCreated", ({ headers, body }) => {
368
+ console.log({ panelId: headers.panelId, order: body.Results[0].orderSerialNumber });
369
+ })
370
+ .handle(request) // process the request
371
+ .catch(console.error); // standard error handling
372
+ ```
373
+
356
374
  ## Examples
357
375
 
358
- Read documentation from this package and more examples on [This page](https://idosell-converter.vercel.app/examples)
376
+ Read documentation from this package and more examples on [This page](https://idosell-converter.vercel.app)
package/changelog.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.41] - 2025-06-07
9
+ ### Added
10
+ - Added webook support
11
+ - Added LANG_ID enumerator
12
+ - Added mapProductParameters utils helper
13
+
8
14
 
9
15
  ## [0.4.38] - 2025-06-03
10
16
  ### Changed
package/dist/app.d.ts CHANGED
@@ -1,3 +1,11 @@
1
+ import type {
2
+ GetProductsResponse,
3
+ GetRmaResponse,
4
+ GetReturnsResponse,
5
+ GetOrdersResponse,
6
+ GetClientsResponse,
7
+ } from "./responses.d.ts";
8
+
1
9
  export interface ExecutableDumpParams {
2
10
  url: string;
3
11
  method: string;
@@ -104,4 +112,135 @@ export interface IdosellErrorFaultStructure {
104
112
  faultString: string;
105
113
  }
106
114
 
107
- export {};
115
+ // ─── Final normalized shape ──────────────────────────────────────────────────
116
+
117
+ export interface NormalizedIaiRequest<T = unknown> {
118
+ headers: IaiWebhookHeaders;
119
+ body: T;
120
+ }
121
+
122
+ export declare const WEBHOOK_OBJECT_TYPE: {
123
+ readonly CLIENT: "client";
124
+ readonly PRODUCT: "product";
125
+ readonly ORDER: "order";
126
+ readonly RETURN: "return";
127
+ readonly RMA: "rma";
128
+ };
129
+
130
+ export declare const WEBHOOK_EVENT_TYPE: {
131
+ readonly CLIENT_CREATED: "clientCreated";
132
+ readonly CLIENT_UPDATED: "clientUpdated";
133
+ readonly PRODUCT_CREATED: "productCreated";
134
+ readonly PRODUCT_UPDATED: "productUpdated";
135
+ readonly PRODUCT_PRICE_UPDATED: "productPriceUpdated";
136
+ readonly PRODUCT_STOCK_UPDATED: "productStockUpdated";
137
+ readonly PRODUCT_DISPOSITION_UPDATED: "productDispositionUpdated";
138
+ readonly ORDER_CREATED: "orderCreated";
139
+ readonly ORDER_UPDATED: "orderUpdated";
140
+ readonly ORDER_PAID: "orderPaid";
141
+ readonly ORDER_STATUS_UPDATED: "orderStatusUpdated";
142
+ readonly ORDER_PACKAGE_CREATED: "orderPackageCreated";
143
+ readonly ORDER_FILES_CREATED: "orderFilesCreated";
144
+ readonly ORDER_SALE_DOCUMENT_CREATED: "orderSaleDocumentCreated";
145
+ readonly ORDER_SALE_DOCUMENT_UPDATED: "orderSaleDocumentUpdated";
146
+ readonly ORDER_SENT: "orderSent";
147
+ readonly ORDER_DELIVERED: "orderDelivered";
148
+ readonly ORDER_CANCELED: "orderCanceled";
149
+ readonly RETURN_CREATED: "returnCreated";
150
+ readonly RETURN_UPDATED: "returnUpdated";
151
+ readonly RETURN_FUNDS_CONFIRMED: "returnFundsConfirmed";
152
+ readonly RETURN_PACKAGE_CREATED: "returnPackageCreated";
153
+ readonly RETURN_CONFIRMED: "returnConfirmed";
154
+ readonly RETURN_CANCELED: "returnCanceled";
155
+ readonly RMA_CREATED: "rmaCreated";
156
+ readonly RMA_UPDATED: "rmaUpdated";
157
+ readonly RMA_PACKAGE_CREATED: "rmaPackageCreated";
158
+ readonly RMA_APPROVED: "rmaApproved";
159
+ readonly RMA_REJECTED: "rmaRejected";
160
+ };
161
+
162
+ export type WebhookObjectType = typeof WEBHOOK_OBJECT_TYPE[keyof typeof WEBHOOK_OBJECT_TYPE];
163
+ export type WebhookEventType = typeof WEBHOOK_EVENT_TYPE[keyof typeof WEBHOOK_EVENT_TYPE];
164
+
165
+ interface ObjectBodyMap {
166
+ "client": GetClientsResponse;
167
+ "product": GetProductsResponse;
168
+ "order": GetOrdersResponse;
169
+ "return": GetReturnsResponse;
170
+ "rma": GetRmaResponse;
171
+ }
172
+
173
+ interface EventObjectMap {
174
+ "clientCreated": "client";
175
+ "clientUpdated": "client";
176
+ "productCreated": "product";
177
+ "productUpdated": "product";
178
+ "productPriceUpdated": "product";
179
+ "productStockUpdated": "product";
180
+ "productDispositionUpdated": "product";
181
+ "orderCreated": "order";
182
+ "orderUpdated": "order";
183
+ "orderPaid": "order";
184
+ "orderStatusUpdated": "order";
185
+ "orderPackageCreated": "order";
186
+ "orderFilesCreated": "order";
187
+ "orderSaleDocumentCreated": "order";
188
+ "orderSaleDocumentUpdated": "order";
189
+ "orderSent": "order";
190
+ "orderDelivered": "order";
191
+ "orderCanceled": "order";
192
+ "returnCreated": "return";
193
+ "returnUpdated": "return";
194
+ "returnFundsConfirmed": "return";
195
+ "returnPackageCreated": "return";
196
+ "returnConfirmed": "return";
197
+ "returnCanceled": "return";
198
+ "rmaCreated": "rma";
199
+ "rmaUpdated": "rma";
200
+ "rmaPackageCreated": "rma";
201
+ "rmaApproved": "rma";
202
+ "rmaRejected": "rma";
203
+ }
204
+
205
+ // ─── Parsed & renamed headers ────────────────────────────────────────────────
206
+
207
+ export interface IaiWebhookHeaders {
208
+ token: string;
209
+ apiVersion: number;
210
+ eventTime: Date;
211
+ objectType: WebhookObjectType;
212
+ eventType: WebhookEventType;
213
+ eventUid: string;
214
+ panelId: number;
215
+ signature: string;
216
+ webhookTime: Date;
217
+ }
218
+
219
+ export interface WebhookContext<E extends WebhookEventType> {
220
+ headers: IaiWebhookHeaders;
221
+ body: ObjectBodyMap[EventObjectMap[E]];
222
+ }
223
+
224
+ export type WebhookHandler<E extends WebhookEventType> =
225
+ (ctx: WebhookContext<E>) => Promise<void> | void;
226
+
227
+ export type HeaderValidator =
228
+ (headers: IaiWebhookHeaders) => Promise<boolean> | boolean;
229
+
230
+ export type DispatchResult =
231
+ | { matched: true; eventType: WebhookEventType }
232
+ | { matched: false; eventType: string }
233
+ | { matched: false; eventType: null; reason: "validation_failed" };
234
+
235
+ export declare class WebhookChain {
236
+ validateHeaders(validator: HeaderValidator): this;
237
+ on<E extends WebhookEventType>(eventType: E, handler: WebhookHandler<E>): this;
238
+ handle(req: import("node:http").IncomingMessage | Request): Promise<DispatchResult>;
239
+ }
240
+
241
+ export type Webhooks = {
242
+ validateHeaders(validator: HeaderValidator): WebhookChain;
243
+ on<E extends WebhookEventType>(eventType: E, handler: WebhookHandler<E>): WebhookChain;
244
+ };
245
+
246
+ export {};
package/dist/enums.d.ts CHANGED
@@ -398,18 +398,44 @@ declare enum PRODUCE_SIZE_INDEX {
398
398
  ID = "sizeId",
399
399
  IAI_CODE = "iaiCode"
400
400
  }
401
- declare const ENUMS: {
402
- PRODUCTS_RETURN_ELEMENTS: typeof PRODUCTS_RETURN_ELEMENTS;
403
- ORDER_STATUS: typeof ORDER_STATUS;
404
- STOCK_DOCUMENT_TYPE: typeof STOCK_DOCUMENT_TYPE;
405
- RETURN_STATUS: typeof RETURN_STATUS;
406
- RMA_STATUS: typeof RMA_STATUS;
407
- PAYMENT_FORMS: typeof PAYMENT_FORMS;
408
- PRODUCT_SIZE_COUNTABLE: typeof PRODUCT_SIZE_COUNTABLE;
409
- PRODUCT_SIZE_CODES: typeof PRODUCT_SIZE_CODES;
410
- PRODUCT_SIZE_LOCATIONS: typeof PRODUCT_SIZE_LOCATIONS;
411
- PRODUCE_SIZE_INDEX: typeof PRODUCE_SIZE_INDEX;
412
- };
401
+ declare enum WEBHOOK_OBJECT_TYPE {
402
+ CLIENT = "client",
403
+ PRODUCT = "product",
404
+ ORDER = "order",
405
+ RETURN = "return",
406
+ RMA = "rma"
407
+ }
408
+ declare enum WEBHOOK_EVENT_TYPE {
409
+ CLIENT_CREATED = "clientCreated",
410
+ CLIENT_UPDATED = "clientUpdated",
411
+ PRODUCT_CREATED = "productCreated",
412
+ PRODUCT_UPDATED = "productUpdated",
413
+ PRODUCT_PRICE_UPDATED = "productPriceUpdated",
414
+ PRODUCT_STOCK_UPDATED = "productStockUpdated",
415
+ PRODUCT_DISPOSITION_UPDATED = "productDispositionUpdated",
416
+ ORDER_CREATED = "orderCreated",
417
+ ORDER_UPDATED = "orderUpdated",
418
+ ORDER_PAID = "orderPaid",
419
+ ORDER_STATUS_UPDATED = "orderStatusUpdated",
420
+ ORDER_PACKAGE_CREATED = "orderPackageCreated",
421
+ ORDER_FILES_CREATED = "orderFilesCreated",
422
+ ORDER_SALE_DOCUMENT_CREATED = "orderSaleDocumentCreated",
423
+ ORDER_SALE_DOCUMENT_UPDATED = "orderSaleDocumentUpdated",
424
+ ORDER_SENT = "orderSent",
425
+ ORDER_DELIVERED = "orderDelivered",
426
+ ORDER_CANCELED = "orderCanceled",
427
+ RETURN_CREATED = "returnCreated",
428
+ RETURN_UPDATED = "returnUpdated",
429
+ RETURN_FUNDS_CONFIRMED = "returnFundsConfirmed",
430
+ RETURN_PACKAGE_CREATED = "returnPackageCreated",
431
+ RETURN_CONFIRMED = "returnConfirmed",
432
+ RETURN_CANCELED = "returnCanceled",
433
+ RMA_CREATED = "rmaCreated",
434
+ RMA_UPDATED = "rmaUpdated",
435
+ RMA_PACKAGE_CREATED = "rmaPackageCreated",
436
+ RMA_APPROVED = "rmaApproved",
437
+ RMA_REJECTED = "rmaRejected"
438
+ }
413
439
  declare enum LANG_IDS {
414
440
  ABCHASKI = "abk",
415
441
  ACHINSKI = "ace",
@@ -584,6 +610,21 @@ declare enum LANG_IDS {
584
610
  ZULUS = "zul",
585
611
  ZUNI = "zun"
586
612
  }
613
+ declare const ENUMS: {
614
+ PRODUCTS_RETURN_ELEMENTS: typeof PRODUCTS_RETURN_ELEMENTS;
615
+ ORDER_STATUS: typeof ORDER_STATUS;
616
+ STOCK_DOCUMENT_TYPE: typeof STOCK_DOCUMENT_TYPE;
617
+ RETURN_STATUS: typeof RETURN_STATUS;
618
+ RMA_STATUS: typeof RMA_STATUS;
619
+ PAYMENT_FORMS: typeof PAYMENT_FORMS;
620
+ PRODUCT_SIZE_COUNTABLE: typeof PRODUCT_SIZE_COUNTABLE;
621
+ PRODUCT_SIZE_CODES: typeof PRODUCT_SIZE_CODES;
622
+ PRODUCT_SIZE_LOCATIONS: typeof PRODUCT_SIZE_LOCATIONS;
623
+ PRODUCE_SIZE_INDEX: typeof PRODUCE_SIZE_INDEX;
624
+ LANG_IDS: typeof LANG_IDS;
625
+ WEBHOOK_OBJECT_TYPE: typeof WEBHOOK_OBJECT_TYPE;
626
+ WEBHOOK_EVENT_TYPE: typeof WEBHOOK_EVENT_TYPE;
627
+ };
587
628
  export declare namespace ENUMS {
588
629
  type PRODUCTS_RETURN_ELEMENTS = typeof PRODUCTS_RETURN_ELEMENTS[keyof typeof PRODUCTS_RETURN_ELEMENTS];
589
630
  type ORDER_STATUS = typeof ORDER_STATUS[keyof typeof ORDER_STATUS];
@@ -596,6 +637,8 @@ export declare namespace ENUMS {
596
637
  type PRODUCT_SIZE_LOCATIONS = typeof PRODUCT_SIZE_LOCATIONS[keyof typeof PRODUCT_SIZE_LOCATIONS];
597
638
  type PRODUCE_SIZE_INDEX = typeof PRODUCE_SIZE_INDEX[keyof typeof PRODUCE_SIZE_INDEX];
598
639
  type LANG_IDS = typeof LANG_IDS[keyof typeof LANG_IDS];
640
+ type WEBHOOK_OBJECT_TYPE = typeof WEBHOOK_OBJECT_TYPE[keyof typeof WEBHOOK_OBJECT_TYPE];
641
+ type WEBHOOK_EVENT_TYPE = typeof WEBHOOK_EVENT_TYPE[keyof typeof WEBHOOK_EVENT_TYPE];
599
642
  }
600
643
  export { ENUMS };
601
644
  export default ENUMS;
package/dist/enums.js CHANGED
@@ -409,18 +409,46 @@ var PRODUCE_SIZE_INDEX;
409
409
  PRODUCE_SIZE_INDEX["ID"] = "sizeId";
410
410
  PRODUCE_SIZE_INDEX["IAI_CODE"] = "iaiCode";
411
411
  })(PRODUCE_SIZE_INDEX || (PRODUCE_SIZE_INDEX = {}));
412
- const ENUMS = {
413
- PRODUCTS_RETURN_ELEMENTS,
414
- ORDER_STATUS,
415
- STOCK_DOCUMENT_TYPE,
416
- RETURN_STATUS,
417
- RMA_STATUS,
418
- PAYMENT_FORMS,
419
- PRODUCT_SIZE_COUNTABLE,
420
- PRODUCT_SIZE_CODES,
421
- PRODUCT_SIZE_LOCATIONS,
422
- PRODUCE_SIZE_INDEX
423
- };
412
+ var WEBHOOK_OBJECT_TYPE;
413
+ (function (WEBHOOK_OBJECT_TYPE) {
414
+ WEBHOOK_OBJECT_TYPE["CLIENT"] = "client";
415
+ WEBHOOK_OBJECT_TYPE["PRODUCT"] = "product";
416
+ WEBHOOK_OBJECT_TYPE["ORDER"] = "order";
417
+ WEBHOOK_OBJECT_TYPE["RETURN"] = "return";
418
+ WEBHOOK_OBJECT_TYPE["RMA"] = "rma";
419
+ })(WEBHOOK_OBJECT_TYPE || (WEBHOOK_OBJECT_TYPE = {}));
420
+ var WEBHOOK_EVENT_TYPE;
421
+ (function (WEBHOOK_EVENT_TYPE) {
422
+ WEBHOOK_EVENT_TYPE["CLIENT_CREATED"] = "clientCreated";
423
+ WEBHOOK_EVENT_TYPE["CLIENT_UPDATED"] = "clientUpdated";
424
+ WEBHOOK_EVENT_TYPE["PRODUCT_CREATED"] = "productCreated";
425
+ WEBHOOK_EVENT_TYPE["PRODUCT_UPDATED"] = "productUpdated";
426
+ WEBHOOK_EVENT_TYPE["PRODUCT_PRICE_UPDATED"] = "productPriceUpdated";
427
+ WEBHOOK_EVENT_TYPE["PRODUCT_STOCK_UPDATED"] = "productStockUpdated";
428
+ WEBHOOK_EVENT_TYPE["PRODUCT_DISPOSITION_UPDATED"] = "productDispositionUpdated";
429
+ WEBHOOK_EVENT_TYPE["ORDER_CREATED"] = "orderCreated";
430
+ WEBHOOK_EVENT_TYPE["ORDER_UPDATED"] = "orderUpdated";
431
+ WEBHOOK_EVENT_TYPE["ORDER_PAID"] = "orderPaid";
432
+ WEBHOOK_EVENT_TYPE["ORDER_STATUS_UPDATED"] = "orderStatusUpdated";
433
+ WEBHOOK_EVENT_TYPE["ORDER_PACKAGE_CREATED"] = "orderPackageCreated";
434
+ WEBHOOK_EVENT_TYPE["ORDER_FILES_CREATED"] = "orderFilesCreated";
435
+ WEBHOOK_EVENT_TYPE["ORDER_SALE_DOCUMENT_CREATED"] = "orderSaleDocumentCreated";
436
+ WEBHOOK_EVENT_TYPE["ORDER_SALE_DOCUMENT_UPDATED"] = "orderSaleDocumentUpdated";
437
+ WEBHOOK_EVENT_TYPE["ORDER_SENT"] = "orderSent";
438
+ WEBHOOK_EVENT_TYPE["ORDER_DELIVERED"] = "orderDelivered";
439
+ WEBHOOK_EVENT_TYPE["ORDER_CANCELED"] = "orderCanceled";
440
+ WEBHOOK_EVENT_TYPE["RETURN_CREATED"] = "returnCreated";
441
+ WEBHOOK_EVENT_TYPE["RETURN_UPDATED"] = "returnUpdated";
442
+ WEBHOOK_EVENT_TYPE["RETURN_FUNDS_CONFIRMED"] = "returnFundsConfirmed";
443
+ WEBHOOK_EVENT_TYPE["RETURN_PACKAGE_CREATED"] = "returnPackageCreated";
444
+ WEBHOOK_EVENT_TYPE["RETURN_CONFIRMED"] = "returnConfirmed";
445
+ WEBHOOK_EVENT_TYPE["RETURN_CANCELED"] = "returnCanceled";
446
+ WEBHOOK_EVENT_TYPE["RMA_CREATED"] = "rmaCreated";
447
+ WEBHOOK_EVENT_TYPE["RMA_UPDATED"] = "rmaUpdated";
448
+ WEBHOOK_EVENT_TYPE["RMA_PACKAGE_CREATED"] = "rmaPackageCreated";
449
+ WEBHOOK_EVENT_TYPE["RMA_APPROVED"] = "rmaApproved";
450
+ WEBHOOK_EVENT_TYPE["RMA_REJECTED"] = "rmaRejected";
451
+ })(WEBHOOK_EVENT_TYPE || (WEBHOOK_EVENT_TYPE = {}));
424
452
  var LANG_IDS;
425
453
  (function (LANG_IDS) {
426
454
  LANG_IDS["ABCHASKI"] = "abk";
@@ -596,5 +624,20 @@ var LANG_IDS;
596
624
  LANG_IDS["ZULUS"] = "zul";
597
625
  LANG_IDS["ZUNI"] = "zun";
598
626
  })(LANG_IDS || (LANG_IDS = {}));
627
+ const ENUMS = {
628
+ PRODUCTS_RETURN_ELEMENTS,
629
+ ORDER_STATUS,
630
+ STOCK_DOCUMENT_TYPE,
631
+ RETURN_STATUS,
632
+ RMA_STATUS,
633
+ PAYMENT_FORMS,
634
+ PRODUCT_SIZE_COUNTABLE,
635
+ PRODUCT_SIZE_CODES,
636
+ PRODUCT_SIZE_LOCATIONS,
637
+ PRODUCE_SIZE_INDEX,
638
+ LANG_IDS,
639
+ WEBHOOK_OBJECT_TYPE,
640
+ WEBHOOK_EVENT_TYPE
641
+ };
599
642
  export { ENUMS };
600
643
  export default ENUMS;
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-empty-object-type */
2
- import type { PagableGateway, AppendableGateway, Gateway, DateLike, JSObject, IdosellErrorFaultStructure } from "./app.d.ts"
2
+ import type { PagableGateway, AppendableGateway, Gateway, DateLike, JSObject, IdosellErrorFaultStructure, Webhooks, IaiWebhookHeaders } from "./app.d.ts"
3
3
  import type { GetClientsBalanceResponse, BooleanStatusResponse, GetClientsResponse, PostClientsResponse, PutClientsResponse, SearchClientsCrmResponse, GetClientsDeliveryAddressResponse, PostClientsDeliveryAddressResponse, PutClientsDeliveryAddressResponse, VouchersResponse, PutVouchersResponse, SearchClientsGiftcardsResponse, GetClientsGiftcardsTypesResponse, GetClientsMembershipCardsResponse, PutClientsMembershipCardsResponse, SearchClientsNewsletterEmailResponse, SearchClientsNewsletterSmsResponse, GetClientsPayerAddressResponse, PostClientsPayerAddressResponse, PutClientsPayerAddressResponse, GetClientsPricelistsClientsResponse, PutClientsPricelistsClientsResponse, GetClientsPricelistsResponse, PostClientsPricelistsResponse, GetClientsPricelistsProductsResponse, PutClientsPricelistsProductsResponse, GetClientsPricesActiveCardResponse, GetClientsPricesDiscountGroupsResponse, GetClientsPricesDiscountsResponse, PutClientsPricesDiscountsResponse, GetClientsProfitPointsResponse, GetClientsProvinceListResponse, GetClientsTagsResponse, PostClientsTagsResponse, PutClientsTagsResponse, GetConfigVariablesResponse, PutConfigVariablesResponse, GetCouriersAssignedToShippingProfilesResponse, GetCouriersResponse, GetCouriersPickupPointsResponse, PutCouriersPickupPointsResponse, GetCpaCampaignResponse, CmsCampaignResponse, CmsResponse, GetCpaResponse, GetDeliveriesProfilesResponse, GetDeliveriesRegionsResponse, PostDeliveriesRegionsResponse, GetDiscountsGroupsClientsResponse, GetDiscountsGroupsResponse, PostDiscountsGroupsResponse, GetEntriesResponse, PostEntriesResponse, GetEntriesPagesToDisplayResponse, GetEntriesSourcesResponse, GetMenuResponse, PostMenuResponse, PutMenuResponse, PutMenuSortResponse, GetOrdersAnalyticsResponse, GetOrdersAuctionDetailsResponse, PutOrdersCourierResponse, PostOrdersDocumentsCreateResponse, GetOrdersDocumentsResponse, PostOrdersDocumentsResponse, GetOrdersHandlerResponse, GetOrdersHistoryResponse, GetOrdersImagesResponse, PostOrdersImagesResponse, GetOrdersLabelsResponse, SearchOrdersOpinionsResponse, GetOrdersOpinionsRateResponse, SearchOrdersResponse, PostOrdersResponse, PutOrdersResponse, GetOrdersPackagesResponse, PutOrdersPackagesResponse, PutOrdersProductsSerialNumbersResponse, PutOrdersProfitMarginResponse, GetOrdersProfitabilityResponse, GetOrdersStatusesResponse, GetOrdersWarehouseResponse, PostPackagesLabelsResponse, PutPackagesResponse, SearchPackagesResponse, GetPaymentsFormsResponse, GetPaymentsResponse, PostPaymentsResponse, GetPaymentsProfilesResponse, PostPaymentsRepaymentResponse, GetProductsSKUbyBarcodeResponse, GetProductsAttachmentsGetContentResponse, PutProductsAttachmentsResponse, GetProductsAuctionsResponse, GetProductsBrandsResponse, PutProductsBrandsResponse, GetProductsCategoriesResponse, PutProductsCategoriesResponse, SearchProductsCategoriesIdosellResponse, GetProductsCodeExistenceResponse, SearchProductsDeliveryTimeResponse, GetProductsDescriptionsResponse, ProductIdentResponse, PutProductsGroupsSettingsResponse, GetProductsIdBySizecodeResponse, PutProductsImagesResponse, GetProductsMarketingZonesResponse, PutProductsMarketingZonesResponse, GetProductsOmnibusPricesResponse, GetProductsOpinionsResponse, PostProductsOpinionsResponse, GetProductsOpinionsRateResponse, PutProductsParametersResponse, SearchProductsParametersResponse, SearchProductsResponse, PostProductsResponse, PutProductsResponse, PutProductsMarketingPromotionResponse, GetProductsQuestionsResponse, GetProductsReservationsResponse, GetProductsSeriesResponse, PutProductsSeriesResponse, GetProductsSizesResponse, PutProductsSizesResponse, PutProductsStockQuantityResponse, GetProductsStocksResponse, PutProductsStocksResponse, GetProductsStrikethroughPricesResponse, PutProductsSupplierCodeResponse, PutProductsSupplierProductDataResponse, PromotionBoolResponse, SearchPromotionsElementsResponse, SearchPromotionsHistoryResponse, PromotionIdResponse, GetPromotionsResponse, SearchPromotionsListViewResponse, GetPromotionsArchiveResponse, SearchPromotionsArchiveResponse, GetPromotionsSettingsResponse, GetRegulationsHistoryResponse, GetResponsibilityEntitiesResponse, PutResponsibilityEntitiesResponse, GetReturnsResponse, PostReturnsResponse, PutReturnsResponse, PutReturnsSerialNumberResponse, GetRmaResponse, PutRmaResponse, GetRmaStatusesResponse, GetShopsCurrenciesResponse, GetShopsLanguagesResponse, GetSizechartsResponse, PutSizechartsResponse, GetSizesResponse, PutSizesResponse, GetSnippetsCampaignResponse, GetSnippetsCookiesResponse, GetSnippetsResponse, GetSystemConfigResponse, GetSystemCurrenciesResponse, PutSystemCurrenciesResponse, GetSystemProcessesAutomationResponse, GetSystemServerLoadResponse, GetSystemServerTimeResponse, GetSystemShopsDataResponse, GetSystemUnitsResponse, PutSystemUnitsResponse, GetSystemUsersResponse, GetVouchersTypesResponse, GetVouchersResponse, GetWarrantiesCountTotalResponse, PutWarrantiesLanguageDataResponse, GetWarrantiesResponse, PutWarrantiesResponse, GetWmsLocationsResponse, GetWmsStocksdocumentsDocumentsResponse, PostWmsStocksdocumentsDocumentsResponse, PutWmsStocksdocumentsDocumentsResponse, GetWmsStocksdocumentsOpenedDocumentsResponse, GetWmsStocksdocumentsProductsResponse, PutWmsStocksdocumentsProductsResponse, GetWmsSuppliersResponse, PutWmsSuppliersResponse, GetProductsMarketingPromotionResponse, PostProductsMarketingPromotionResponse } from "./responses.d.ts"
4
4
  import type * as RequestParams from "./reqparams.d.ts";
5
5
  import { ENUMS } from "./enums";
@@ -5419,6 +5419,7 @@ export interface Gateways {
5419
5419
  deleteProductsProductsToPromotion: DeleteProductsToPromotionRequest,
5420
5420
  }
5421
5421
 
5422
+ declare const webhooks: Webhooks;
5422
5423
  declare const defaultExport: (url: string, apiKey: string, version?: number | string) => Gateways;
5423
5424
  export default defaultExport;
5424
- export { ENUMS, RequestParams, utils }
5425
+ export { ENUMS, RequestParams, utils, webhooks, IaiWebhookHeaders }
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import ENUMS from "./enums.js";
2
2
  import utils from "./utils.js";
3
+ import webhooks from "./webhooks.js";
3
4
  import { gateProxy } from "./gates.js";
4
5
  import { IdosellFaultStringError, catchEmptyList } from "./errors.js";
5
6
  export const DEFAULT_VERSION = 8;
@@ -27,4 +28,4 @@ const idosell = (url, apiKey, version = DEFAULT_VERSION) => {
27
28
  return new Proxy(element, gateProxy);
28
29
  };
29
30
  export default idosell;
30
- export { ENUMS, utils, IdosellFaultStringError, catchEmptyList };
31
+ export { ENUMS, utils, webhooks, IdosellFaultStringError, catchEmptyList };
@@ -9055,7 +9055,6 @@ export type GetOrdersResponse = {
9055
9055
  clientPickupPointAddress?: {
9056
9056
  /** @description Collection point ID. */
9057
9057
  pickupPointId: number;
9058
- externalPickupPointId?: string;
9059
9058
  /** @description External service collection point ID. */
9060
9059
  externalPickupPointId: string;
9061
9060
  /** @description Town / City. */
@@ -0,0 +1,124 @@
1
+ /* eslint-disable no-unused-vars */
2
+ import { normalizeIaiRequest, WebhookValidationError } from "./webhooks.normalizer.js";
3
+ // ─── Runtime constants ────────────────────────────────────────────────────────
4
+ export const WEBHOOK_OBJECT_TYPE = {
5
+ CLIENT: "client",
6
+ PRODUCT: "product",
7
+ ORDER: "order",
8
+ RETURN: "return",
9
+ RMA: "rma",
10
+ };
11
+ export const WEBHOOK_EVENT_TYPE = {
12
+ CLIENT_CREATED: "clientCreated",
13
+ CLIENT_UPDATED: "clientUpdated",
14
+ PRODUCT_CREATED: "productCreated",
15
+ PRODUCT_UPDATED: "productUpdated",
16
+ PRODUCT_PRICE_UPDATED: "productPriceUpdated",
17
+ PRODUCT_STOCK_UPDATED: "productStockUpdated",
18
+ PRODUCT_DISPOSITION_UPDATED: "productDispositionUpdated",
19
+ ORDER_CREATED: "orderCreated",
20
+ ORDER_UPDATED: "orderUpdated",
21
+ ORDER_PAID: "orderPaid",
22
+ ORDER_STATUS_UPDATED: "orderStatusUpdated",
23
+ ORDER_PACKAGE_CREATED: "orderPackageCreated",
24
+ ORDER_FILES_CREATED: "orderFilesCreated",
25
+ ORDER_SALE_DOCUMENT_CREATED: "orderSaleDocumentCreated",
26
+ ORDER_SALE_DOCUMENT_UPDATED: "orderSaleDocumentUpdated",
27
+ ORDER_SENT: "orderSent",
28
+ ORDER_DELIVERED: "orderDelivered",
29
+ ORDER_CANCELED: "orderCanceled",
30
+ RETURN_CREATED: "returnCreated",
31
+ RETURN_UPDATED: "returnUpdated",
32
+ RETURN_FUNDS_CONFIRMED: "returnFundsConfirmed",
33
+ RETURN_PACKAGE_CREATED: "returnPackageCreated",
34
+ RETURN_CONFIRMED: "returnConfirmed",
35
+ RETURN_CANCELED: "returnCanceled",
36
+ RMA_CREATED: "rmaCreated",
37
+ RMA_UPDATED: "rmaUpdated",
38
+ RMA_PACKAGE_CREATED: "rmaPackageCreated",
39
+ RMA_APPROVED: "rmaApproved",
40
+ RMA_REJECTED: "rmaRejected",
41
+ };
42
+ // ─── Runtime event → object map ───────────────────────────────────────────────
43
+ const EVENT_OBJECT_MAP = {
44
+ clientCreated: "client",
45
+ clientUpdated: "client",
46
+ productCreated: "product",
47
+ productUpdated: "product",
48
+ productPriceUpdated: "product",
49
+ productStockUpdated: "product",
50
+ productDispositionUpdated: "product",
51
+ orderCreated: "order",
52
+ orderUpdated: "order",
53
+ orderPaid: "order",
54
+ orderStatusUpdated: "order",
55
+ orderPackageCreated: "order",
56
+ orderFilesCreated: "order",
57
+ orderSaleDocumentCreated: "order",
58
+ orderSaleDocumentUpdated: "order",
59
+ orderSent: "order",
60
+ orderDelivered: "order",
61
+ orderCanceled: "order",
62
+ returnCreated: "return",
63
+ returnUpdated: "return",
64
+ returnFundsConfirmed: "return",
65
+ returnPackageCreated: "return",
66
+ returnConfirmed: "return",
67
+ returnCanceled: "return",
68
+ rmaCreated: "rma",
69
+ rmaUpdated: "rma",
70
+ rmaPackageCreated: "rma",
71
+ rmaApproved: "rma",
72
+ rmaRejected: "rma",
73
+ };
74
+ export class WebhookChain {
75
+ slots = [];
76
+ validator = null;
77
+ validateHeaders(validator) {
78
+ this.validator = validator;
79
+ return this;
80
+ }
81
+ on(eventType, handler) {
82
+ this.slots.push({
83
+ eventType,
84
+ fn: handler,
85
+ });
86
+ return this;
87
+ }
88
+ async handle(req) {
89
+ const { headers, body } = await normalizeIaiRequest(req);
90
+ if (this.validator !== null) {
91
+ let valid = false;
92
+ try {
93
+ valid = await this.validator(headers);
94
+ }
95
+ catch {
96
+ valid = false;
97
+ }
98
+ if (!valid) {
99
+ return { matched: false, eventType: null, reason: "validation_failed" };
100
+ }
101
+ }
102
+ const incomingEvent = headers.eventType;
103
+ const expectedObject = EVENT_OBJECT_MAP[incomingEvent];
104
+ if (expectedObject !== undefined && headers.objectType !== expectedObject) {
105
+ throw new WebhookValidationError(`eventType "${incomingEvent}" expects objectType "${expectedObject}", got "${headers.objectType}"`, "x-iai-object-type");
106
+ }
107
+ const slot = this.slots.find(s => s.eventType === incomingEvent);
108
+ if (!slot) {
109
+ return { matched: false, eventType: incomingEvent };
110
+ }
111
+ await slot.fn({ headers, body });
112
+ return { matched: true, eventType: slot.eventType };
113
+ }
114
+ }
115
+ // ─── Entry point ──────────────────────────────────────────────────────────────
116
+ export const webhooks = {
117
+ validateHeaders(validator) {
118
+ return new WebhookChain().validateHeaders(validator);
119
+ },
120
+ on(eventType, handler) {
121
+ return new WebhookChain().on(eventType, handler);
122
+ },
123
+ };
124
+ export default webhooks;
@@ -0,0 +1,140 @@
1
+ // ─── Errors ──────────────────────────────────────────────────────────────────
2
+ export class WebhookValidationError extends Error {
3
+ field;
4
+ constructor(message, field) {
5
+ super(message);
6
+ this.field = field;
7
+ this.name = `WebhookValidationError ${field}`;
8
+ }
9
+ }
10
+ // ─── Internal helpers ────────────────────────────────────────────────────────
11
+ function requireHeader(headers, key) {
12
+ const value = headers[key];
13
+ if (!value || value.trim() === "") {
14
+ throw new WebhookValidationError(`Missing or empty required header: ${key}`, key);
15
+ }
16
+ return value.trim();
17
+ }
18
+ function parseIntHeader(headers, key) {
19
+ const raw = requireHeader(headers, key);
20
+ const n = Number(raw);
21
+ if (!Number.isInteger(n) || n < 0) {
22
+ throw new WebhookValidationError(`Header ${key} must be a positive integer, got: "${raw}"`, key);
23
+ }
24
+ return n;
25
+ }
26
+ function parseDateHeader(headers, key) {
27
+ const raw = requireHeader(headers, key);
28
+ const date = new Date(raw);
29
+ if (isNaN(date.getTime())) {
30
+ throw new WebhookValidationError(`Header ${key} is not a valid date string, got: "${raw}"`, key);
31
+ }
32
+ return date;
33
+ }
34
+ function parseAuthHeader(headers) {
35
+ const raw = requireHeader(headers, "authorization");
36
+ const [scheme, token] = raw.split(" ");
37
+ if (scheme?.toLowerCase() !== "bearer" || !token) {
38
+ throw new WebhookValidationError(`Authorization header must use Bearer scheme, got: "${raw}"`, "authorization");
39
+ }
40
+ return token;
41
+ }
42
+ function extractHeaders(raw) {
43
+ return {
44
+ token: parseAuthHeader(raw),
45
+ apiVersion: parseIntHeader(raw, "x-iai-api-version"),
46
+ eventTime: parseDateHeader(raw, "x-iai-event-time"),
47
+ eventType: requireHeader(raw, "x-iai-event-type"),
48
+ eventUid: requireHeader(raw, "x-iai-event-uid"),
49
+ objectType: requireHeader(raw, "x-iai-object-type"),
50
+ panelId: parseIntHeader(raw, "x-iai-panel-id"),
51
+ signature: requireHeader(raw, "x-iai-signature"),
52
+ webhookTime: parseDateHeader(raw, "x-iai-webhook-time"),
53
+ };
54
+ }
55
+ // ─── Type guard ──────────────────────────────────────────────────────────────
56
+ function isWebRequest(req) {
57
+ return typeof req.json === "function";
58
+ }
59
+ // ─── Raw headers flattening ──────────────────────────────────────────────────
60
+ function flattenNodeHeaders(headers) {
61
+ const out = {};
62
+ for (const [key, value] of Object.entries(headers)) {
63
+ if (value !== undefined) {
64
+ out[key.toLowerCase()] = Array.isArray(value) ? value.join(", ") : value;
65
+ }
66
+ }
67
+ return out;
68
+ }
69
+ function flattenWebHeaders(headers) {
70
+ const out = {};
71
+ headers.forEach((value, key) => { out[key.toLowerCase()] = value; });
72
+ return out;
73
+ }
74
+ function readNodeStream(req) {
75
+ return new Promise((resolve, reject) => {
76
+ const chunks = [];
77
+ req.on("data", (chunk) => chunks.push(chunk));
78
+ req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
79
+ req.on("error", reject);
80
+ });
81
+ }
82
+ // ─── Main normalizer ─────────────────────────────────────────────────────────
83
+ /**
84
+ * Parses and validates an incoming IAI webhook request from any of:
85
+ * - Express (pass req directly — do NOT attach express.json())
86
+ * - Next.js Pages (disable bodyParser in route config)
87
+ * - Next.js App (Web Fetch API Request)
88
+ * - SvelteKit (Web Fetch API Request — pass event.request)
89
+ *
90
+ * Throws WebhookValidationError for any missing/malformed header or empty body.
91
+ *
92
+ * @example Express
93
+ * app.post('/webhook', async (req, res) => {
94
+ * const { headers, body } = await normalizeIaiRequest(req);
95
+ * });
96
+ *
97
+ * @example SvelteKit
98
+ * export async function POST({ request }) {
99
+ * const { headers, body } = await normalizeIaiRequest(request);
100
+ * }
101
+ *
102
+ * @example Next.js App Router
103
+ * export async function POST(request: Request) {
104
+ * const { headers, body } = await normalizeIaiRequest(request);
105
+ * }
106
+ *
107
+ * @example Next.js Pages Router (add export const config = { api: { bodyParser: false } })
108
+ * export default async function handler(req, res) {
109
+ * const { headers, body } = await normalizeIaiRequest(req);
110
+ * }
111
+ */
112
+ export async function normalizeIaiRequest(req) {
113
+ let flatHeaders;
114
+ let rawBody;
115
+ if (isWebRequest(req)) {
116
+ flatHeaders = flattenWebHeaders(req.headers);
117
+ rawBody = await req.text();
118
+ }
119
+ else {
120
+ flatHeaders = flattenNodeHeaders(req.headers);
121
+ rawBody = req.body !== undefined
122
+ ? JSON.stringify(req.body)
123
+ : await readNodeStream(req);
124
+ }
125
+ if (!rawBody || rawBody.trim() === "") {
126
+ throw new WebhookValidationError("Request body is empty", "body");
127
+ }
128
+ let body;
129
+ try {
130
+ body = JSON.parse(rawBody);
131
+ }
132
+ catch {
133
+ throw new WebhookValidationError("Request body is not valid JSON", "body");
134
+ }
135
+ if (typeof body !== "object" || body === null || Array.isArray(body)) {
136
+ throw new WebhookValidationError("Request body must be a JSON object", "body");
137
+ }
138
+ const headers = extractHeaders(flatHeaders);
139
+ return { headers, body };
140
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "idosell",
3
- "version": "0.4.38",
3
+ "version": "0.4.41",
4
4
  "description": "Idosell 3 REST connector",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/gateways.d.ts",