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 +22 -4
- package/changelog.md +6 -0
- package/dist/app.d.ts +140 -1
- package/dist/enums.d.ts +55 -12
- package/dist/enums.js +55 -12
- package/dist/gateways.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/responses.d.ts +0 -1
- package/dist/webhooks.js +124 -0
- package/dist/webhooks.normalizer.js +140 -0
- package/package.json +1 -1
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
|
[](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 **
|
|
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
|
|
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
|
-
|
|
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
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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;
|
package/dist/gateways.d.ts
CHANGED
|
@@ -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 };
|
package/dist/responses.d.ts
CHANGED
|
@@ -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. */
|
package/dist/webhooks.js
ADDED
|
@@ -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
|
+
}
|