@letsbot/sdk 0.2.0 → 0.5.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/README.md +54 -2
- package/dist/index.cjs +327 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6492 -2381
- package/dist/index.d.ts +6492 -2381
- package/dist/index.js +319 -7
- package/dist/index.js.map +1 -1
- package/openapi/erp-v1.yaml +3090 -0
- package/openapi/openapi.yaml +1099 -105
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -74,6 +74,7 @@ var operations = {
|
|
|
74
74
|
addGroupParticipant: { method: "POST", path: "/group/add/participant", params: "body", send: false },
|
|
75
75
|
archiveChat: { method: "POST", path: "/chat/archive", params: "body", send: false },
|
|
76
76
|
blockUser: { method: "POST", path: "/user/block", params: "body", send: false },
|
|
77
|
+
cancelOrder: { method: "POST", path: "/orders/{orderId}/cancel", params: "body", send: false },
|
|
77
78
|
checkPhone: { method: "POST", path: "/check/phone", params: "body", send: false },
|
|
78
79
|
createGroup: { method: "POST", path: "/group/create", params: "body", send: false },
|
|
79
80
|
createProduct: { method: "POST", path: "/product/create", params: "body", send: false },
|
|
@@ -108,6 +109,7 @@ var operations = {
|
|
|
108
109
|
qr: { method: "POST", path: "/qr", params: "none", send: false },
|
|
109
110
|
queryBroadcast: { method: "POST", path: "/instance/query/broadcast", params: "body", send: false },
|
|
110
111
|
readChat: { method: "POST", path: "/chat/read", params: "body", send: false },
|
|
112
|
+
recordOrder: { method: "POST", path: "/orders", params: "body", send: false },
|
|
111
113
|
removeGroupParticipant: { method: "POST", path: "/group/remove/participant", params: "body", send: false },
|
|
112
114
|
renameGroup: { method: "POST", path: "/group/rename", params: "body", send: false },
|
|
113
115
|
revokeInviteCode: { method: "POST", path: "/invite/revoke/code", params: "body", send: false },
|
|
@@ -238,7 +240,7 @@ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
238
240
|
|
|
239
241
|
// src/client.ts
|
|
240
242
|
var DEFAULT_BASE_URL = "https://letsbot.net/api/v1";
|
|
241
|
-
var SDK_VERSION = "0.
|
|
243
|
+
var SDK_VERSION = "0.5.0";
|
|
242
244
|
var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
|
|
243
245
|
var RETRYABLE_5XX = /* @__PURE__ */ new Set([500, 502, 503, 504]);
|
|
244
246
|
var LetsBotClient = class {
|
|
@@ -520,6 +522,10 @@ var resourceMap = {
|
|
|
520
522
|
collections: "getCollections",
|
|
521
523
|
getOrder: "getOrder"
|
|
522
524
|
},
|
|
525
|
+
orders: {
|
|
526
|
+
record: "recordOrder",
|
|
527
|
+
cancel: "cancelOrder"
|
|
528
|
+
},
|
|
523
529
|
session: {
|
|
524
530
|
qr: "qr",
|
|
525
531
|
find: "findSession",
|
|
@@ -561,13 +567,16 @@ var crmOperations = {
|
|
|
561
567
|
crmCompleteTask: { method: "POST", path: "/tasks/{id}/complete", body: false },
|
|
562
568
|
crmContactsSchema: { method: "GET", path: "/contacts/schema", body: false },
|
|
563
569
|
crmCreateActivity: { method: "POST", path: "/activities", body: true },
|
|
564
|
-
crmCreateCompany: { method: "POST", path: "/companies", body: true },
|
|
565
|
-
crmCreateContact: { method: "POST", path: "/contacts", body: true },
|
|
570
|
+
crmCreateCompany: { method: "POST", path: "/companies", body: true, query: ["allow_duplicate"] },
|
|
571
|
+
crmCreateContact: { method: "POST", path: "/contacts", body: true, query: ["allow_duplicate"] },
|
|
572
|
+
crmCreateCustomRecord: { method: "POST", path: "/objects/{key}/records", body: true },
|
|
566
573
|
crmCreateDeal: { method: "POST", path: "/deals", body: true },
|
|
567
574
|
crmCreateProduct: { method: "POST", path: "/products", body: true },
|
|
568
575
|
crmCreateQuote: { method: "POST", path: "/quotes", body: true },
|
|
569
576
|
crmCreateTask: { method: "POST", path: "/tasks", body: true },
|
|
577
|
+
crmCustomObjectSchema: { method: "GET", path: "/objects/{key}/schema", body: false },
|
|
570
578
|
crmDeleteCompany: { method: "DELETE", path: "/companies/{id}", body: false },
|
|
579
|
+
crmDeleteCustomRecord: { method: "DELETE", path: "/objects/{key}/records/{id}", body: false },
|
|
571
580
|
crmDeleteDeal: { method: "DELETE", path: "/deals/{id}", body: false },
|
|
572
581
|
crmDeleteProduct: { method: "DELETE", path: "/products/{id}", body: false },
|
|
573
582
|
crmDeleteQuote: { method: "DELETE", path: "/quotes/{id}", body: false },
|
|
@@ -575,6 +584,7 @@ var crmOperations = {
|
|
|
575
584
|
crmGetActivity: { method: "GET", path: "/activities/{id}", body: false },
|
|
576
585
|
crmGetCompany: { method: "GET", path: "/companies/{id}", body: false },
|
|
577
586
|
crmGetContact: { method: "GET", path: "/contacts/{id}", body: false },
|
|
587
|
+
crmGetCustomRecord: { method: "GET", path: "/objects/{key}/records/{id}", body: false },
|
|
578
588
|
crmGetDeal: { method: "GET", path: "/deals/{id}", body: false },
|
|
579
589
|
crmGetProduct: { method: "GET", path: "/products/{id}", body: false },
|
|
580
590
|
crmGetQuote: { method: "GET", path: "/quotes/{id}", body: false },
|
|
@@ -584,6 +594,8 @@ var crmOperations = {
|
|
|
584
594
|
crmListActivities: { method: "GET", path: "/activities", body: false },
|
|
585
595
|
crmListCompanies: { method: "GET", path: "/companies", body: false },
|
|
586
596
|
crmListContacts: { method: "GET", path: "/contacts", body: false },
|
|
597
|
+
crmListCustomObjects: { method: "GET", path: "/objects", body: false },
|
|
598
|
+
crmListCustomRecords: { method: "GET", path: "/objects/{key}/records", body: false },
|
|
587
599
|
crmListDeals: { method: "GET", path: "/deals", body: false },
|
|
588
600
|
crmListHookEvents: { method: "GET", path: "/hooks/events", body: false },
|
|
589
601
|
crmListHooks: { method: "GET", path: "/hooks", body: false },
|
|
@@ -599,12 +611,14 @@ var crmOperations = {
|
|
|
599
611
|
crmQuotesSchema: { method: "GET", path: "/quotes/schema", body: false },
|
|
600
612
|
crmSearchCompanies: { method: "GET", path: "/companies/search", body: false },
|
|
601
613
|
crmSearchContacts: { method: "GET", path: "/contacts/search", body: false },
|
|
614
|
+
crmSearchCustomRecords: { method: "GET", path: "/objects/{key}/records/search", body: false },
|
|
602
615
|
crmSearchDeals: { method: "GET", path: "/deals/search", body: false },
|
|
603
616
|
crmSubscribeHook: { method: "POST", path: "/hooks", body: true },
|
|
604
617
|
crmUnlinkCompanyContact: { method: "DELETE", path: "/companies/{id}/contacts/{contactId}", body: false },
|
|
605
618
|
crmUnsubscribeHook: { method: "DELETE", path: "/hooks/{id}", body: false },
|
|
606
619
|
crmUpdateCompany: { method: "PATCH", path: "/companies/{id}", body: true },
|
|
607
620
|
crmUpdateContact: { method: "PATCH", path: "/contacts/{id}", body: true },
|
|
621
|
+
crmUpdateCustomRecord: { method: "PATCH", path: "/objects/{key}/records/{id}", body: true },
|
|
608
622
|
crmUpdateDeal: { method: "PATCH", path: "/deals/{id}", body: true },
|
|
609
623
|
crmUpdateProduct: { method: "PATCH", path: "/products/{id}", body: true },
|
|
610
624
|
crmUpdateQuote: { method: "PATCH", path: "/quotes/{id}", body: true },
|
|
@@ -612,6 +626,40 @@ var crmOperations = {
|
|
|
612
626
|
};
|
|
613
627
|
|
|
614
628
|
// src/crm.ts
|
|
629
|
+
var CRM_WEBHOOK_EVENTS = [
|
|
630
|
+
"contact.created",
|
|
631
|
+
"contact.updated",
|
|
632
|
+
"contact.deleted",
|
|
633
|
+
"company.created",
|
|
634
|
+
"company.updated",
|
|
635
|
+
"company.deleted",
|
|
636
|
+
"deal.created",
|
|
637
|
+
"deal.updated",
|
|
638
|
+
"deal.deleted",
|
|
639
|
+
"deal.stage_changed",
|
|
640
|
+
"deal.won",
|
|
641
|
+
"deal.lost",
|
|
642
|
+
"deal.assigned",
|
|
643
|
+
"task.created",
|
|
644
|
+
"task.completed",
|
|
645
|
+
"ticket.created",
|
|
646
|
+
"quote.sent",
|
|
647
|
+
"quote.viewed",
|
|
648
|
+
"quote.accepted",
|
|
649
|
+
"quote.signed",
|
|
650
|
+
"quote.paid",
|
|
651
|
+
"invoice.created",
|
|
652
|
+
"form.submitted",
|
|
653
|
+
"health.at_risk"
|
|
654
|
+
];
|
|
655
|
+
function crmPossibleDuplicate(error) {
|
|
656
|
+
const e = error;
|
|
657
|
+
if (!e || e.status !== 409 || e.code !== "possible_duplicate") return null;
|
|
658
|
+
const body = e.body ?? {};
|
|
659
|
+
const duplicates = Array.isArray(body.duplicates) ? body.duplicates : [];
|
|
660
|
+
const existingId = Number(body.existing_id ?? duplicates[0]?.id);
|
|
661
|
+
return Number.isFinite(existingId) ? { existingId, duplicates } : null;
|
|
662
|
+
}
|
|
615
663
|
var CRM_DEFAULT_RATE_LIMIT = 120;
|
|
616
664
|
var CRM_SIGNATURE_HEADER = "X-LetsBot-Signature";
|
|
617
665
|
var crmResourceMap = {
|
|
@@ -679,6 +727,18 @@ var crmResourceMap = {
|
|
|
679
727
|
update: "crmUpdateProduct",
|
|
680
728
|
delete: "crmDeleteProduct"
|
|
681
729
|
},
|
|
730
|
+
customObjects: {
|
|
731
|
+
list: "crmListCustomObjects",
|
|
732
|
+
schema: "crmCustomObjectSchema"
|
|
733
|
+
},
|
|
734
|
+
customRecords: {
|
|
735
|
+
list: "crmListCustomRecords",
|
|
736
|
+
search: "crmSearchCustomRecords",
|
|
737
|
+
get: "crmGetCustomRecord",
|
|
738
|
+
create: "crmCreateCustomRecord",
|
|
739
|
+
update: "crmUpdateCustomRecord",
|
|
740
|
+
delete: "crmDeleteCustomRecord"
|
|
741
|
+
},
|
|
682
742
|
hooks: {
|
|
683
743
|
list: "crmListHooks",
|
|
684
744
|
events: "crmListHookEvents",
|
|
@@ -719,6 +779,10 @@ var LetsBotCrm = class {
|
|
|
719
779
|
activities;
|
|
720
780
|
quotes;
|
|
721
781
|
products;
|
|
782
|
+
/** Custom objects (`/objects`): 404 until the workspace has custom objects switched on. */
|
|
783
|
+
customObjects;
|
|
784
|
+
/** Records of a custom object (`/objects/{key}/records`); pass the object `key`, e.g. `co_projects`. */
|
|
785
|
+
customRecords;
|
|
722
786
|
hooks;
|
|
723
787
|
transport;
|
|
724
788
|
constructor(options) {
|
|
@@ -747,6 +811,8 @@ var LetsBotCrm = class {
|
|
|
747
811
|
this.activities = bind(crmResourceMap.activities);
|
|
748
812
|
this.quotes = bind(crmResourceMap.quotes);
|
|
749
813
|
this.products = bind(crmResourceMap.products);
|
|
814
|
+
this.customObjects = bind(crmResourceMap.customObjects);
|
|
815
|
+
this.customRecords = bind(crmResourceMap.customRecords);
|
|
750
816
|
this.hooks = bind(crmResourceMap.hooks);
|
|
751
817
|
}
|
|
752
818
|
/** The resolved base URL, e.g. `https://mystore.letsbot.net/api/v1/crm`. */
|
|
@@ -772,10 +838,19 @@ var LetsBotCrm = class {
|
|
|
772
838
|
return encodeURIComponent(String(value));
|
|
773
839
|
});
|
|
774
840
|
const url = new URL(this.transport.root + path);
|
|
841
|
+
const append = (key, value) => {
|
|
842
|
+
if (value === void 0 || value === null) return;
|
|
843
|
+
url.searchParams.append(key, typeof value === "object" ? JSON.stringify(value) : String(value));
|
|
844
|
+
};
|
|
775
845
|
if (!meta.body) {
|
|
776
|
-
for (const [key, value] of Object.entries(rest))
|
|
777
|
-
|
|
778
|
-
|
|
846
|
+
for (const [key, value] of Object.entries(rest)) append(key, value);
|
|
847
|
+
} else if ("query" in meta) {
|
|
848
|
+
for (const key of meta.query) {
|
|
849
|
+
if (key in rest) {
|
|
850
|
+
const value = rest[key];
|
|
851
|
+
append(key, typeof value === "boolean" ? value ? 1 : 0 : value);
|
|
852
|
+
delete rest[key];
|
|
853
|
+
}
|
|
779
854
|
}
|
|
780
855
|
}
|
|
781
856
|
return this.transport.request(operationId, meta.method, url, meta.body ? rest : void 0, options);
|
|
@@ -811,6 +886,240 @@ function verifyCrmWebhookSignature(rawBody, header, secret, options = {}) {
|
|
|
811
886
|
const given = Buffer.from(v1, "hex");
|
|
812
887
|
return given.length === expected.length && timingSafeEqual(given, expected);
|
|
813
888
|
}
|
|
889
|
+
|
|
890
|
+
// src/generated/erp-operations.ts
|
|
891
|
+
var erpOperations = {
|
|
892
|
+
erpConfirmSalesOrder: { method: "POST", path: "/sales/orders/{id}/confirm", body: false, idempotent: false },
|
|
893
|
+
erpCreateCreditNote: { method: "POST", path: "/sales/invoices/{id}/credit-notes", body: true, idempotent: true },
|
|
894
|
+
erpCreateExpense: { method: "POST", path: "/expenses", body: true, idempotent: true },
|
|
895
|
+
erpCreateInvoice: { method: "POST", path: "/sales/invoices", body: true, idempotent: true },
|
|
896
|
+
erpCreatePurchaseOrder: { method: "POST", path: "/purchasing/purchase-orders", body: true, idempotent: true },
|
|
897
|
+
erpCreateSalesOrder: { method: "POST", path: "/sales/orders", body: true, idempotent: true },
|
|
898
|
+
erpCustomerStatement: { method: "GET", path: "/sales/customers/{id}/statement", body: false, idempotent: false },
|
|
899
|
+
erpGetBill: { method: "GET", path: "/purchasing/bills/{id}", body: false, idempotent: false },
|
|
900
|
+
erpGetCreditNote: { method: "GET", path: "/sales/credit-notes/{id}", body: false, idempotent: false },
|
|
901
|
+
erpGetCustomer: { method: "GET", path: "/sales/customers/{id}", body: false, idempotent: false },
|
|
902
|
+
erpGetExpense: { method: "GET", path: "/expenses/{id}", body: false, idempotent: false },
|
|
903
|
+
erpGetInvoice: { method: "GET", path: "/sales/invoices/{id}", body: false, idempotent: false },
|
|
904
|
+
erpGetItem: { method: "GET", path: "/inventory/items/{id}", body: false, idempotent: false },
|
|
905
|
+
erpGetJournalEntry: { method: "GET", path: "/accounting/journal-entries/{id}", body: false, idempotent: false },
|
|
906
|
+
erpGetPayment: { method: "GET", path: "/sales/payments/{id}", body: false, idempotent: false },
|
|
907
|
+
erpGetPurchaseOrder: { method: "GET", path: "/purchasing/purchase-orders/{id}", body: false, idempotent: false },
|
|
908
|
+
erpGetSalesOrder: { method: "GET", path: "/sales/orders/{id}", body: false, idempotent: false },
|
|
909
|
+
erpGetSupplier: { method: "GET", path: "/purchasing/suppliers/{id}", body: false, idempotent: false },
|
|
910
|
+
erpHookEvents: { method: "GET", path: "/hooks/events", body: false, idempotent: false },
|
|
911
|
+
erpHookSample: { method: "GET", path: "/hooks/sample", body: false, idempotent: false },
|
|
912
|
+
erpInvoicePdfLink: { method: "GET", path: "/sales/invoices/{id}/pdf", body: false, idempotent: false },
|
|
913
|
+
erpIssueCreditNote: { method: "POST", path: "/sales/credit-notes/{id}/issue", body: false, idempotent: false },
|
|
914
|
+
erpIssueInvoice: { method: "POST", path: "/sales/invoices/{id}/issue", body: false, idempotent: false },
|
|
915
|
+
erpListAccounts: { method: "GET", path: "/accounting/accounts", body: false, idempotent: false },
|
|
916
|
+
erpListBills: { method: "GET", path: "/purchasing/bills", body: false, idempotent: false },
|
|
917
|
+
erpListCreditNotes: { method: "GET", path: "/sales/credit-notes", body: false, idempotent: false },
|
|
918
|
+
erpListCustomers: { method: "GET", path: "/sales/customers", body: false, idempotent: false },
|
|
919
|
+
erpListExpenseCategories: { method: "GET", path: "/expenses/categories", body: false, idempotent: false },
|
|
920
|
+
erpListExpenses: { method: "GET", path: "/expenses", body: false, idempotent: false },
|
|
921
|
+
erpListHooks: { method: "GET", path: "/hooks", body: false, idempotent: false },
|
|
922
|
+
erpListInvoices: { method: "GET", path: "/sales/invoices", body: false, idempotent: false },
|
|
923
|
+
erpListItems: { method: "GET", path: "/inventory/items", body: false, idempotent: false },
|
|
924
|
+
erpListJournalEntries: { method: "GET", path: "/accounting/journal-entries", body: false, idempotent: false },
|
|
925
|
+
erpListPayments: { method: "GET", path: "/sales/payments", body: false, idempotent: false },
|
|
926
|
+
erpListPurchaseOrders: { method: "GET", path: "/purchasing/purchase-orders", body: false, idempotent: false },
|
|
927
|
+
erpListSalesOrders: { method: "GET", path: "/sales/orders", body: false, idempotent: false },
|
|
928
|
+
erpListStockLevels: { method: "GET", path: "/inventory/stock-levels", body: false, idempotent: false },
|
|
929
|
+
erpListStockMoves: { method: "GET", path: "/inventory/stock-moves", body: false, idempotent: false },
|
|
930
|
+
erpListSuppliers: { method: "GET", path: "/purchasing/suppliers", body: false, idempotent: false },
|
|
931
|
+
erpListVariants: { method: "GET", path: "/inventory/variants", body: false, idempotent: false },
|
|
932
|
+
erpListWarehouses: { method: "GET", path: "/inventory/warehouses", body: false, idempotent: false },
|
|
933
|
+
erpRecordPayment: { method: "POST", path: "/sales/payments", body: true, idempotent: true },
|
|
934
|
+
erpReportBalanceSheet: { method: "GET", path: "/accounting/reports/balance-sheet", body: false, idempotent: false },
|
|
935
|
+
erpReportProfitAndLoss: { method: "GET", path: "/accounting/reports/profit-and-loss", body: false, idempotent: false },
|
|
936
|
+
erpReportVat: { method: "GET", path: "/accounting/reports/vat", body: false, idempotent: false },
|
|
937
|
+
erpSubscribeHook: { method: "POST", path: "/hooks", body: true, idempotent: false },
|
|
938
|
+
erpUnsubscribeHook: { method: "DELETE", path: "/hooks/{id}", body: false, idempotent: false }
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
// src/erp.ts
|
|
942
|
+
var ERP_DEFAULT_RATE_LIMIT = 120;
|
|
943
|
+
var ERP_WEBHOOK_EVENTS = [
|
|
944
|
+
"invoice.issued",
|
|
945
|
+
"invoice.paid",
|
|
946
|
+
"invoice.cleared",
|
|
947
|
+
"invoice.rejected",
|
|
948
|
+
"credit_note.issued",
|
|
949
|
+
"payment.received",
|
|
950
|
+
"order.confirmed",
|
|
951
|
+
"stock.low",
|
|
952
|
+
"po.confirmed_by_supplier",
|
|
953
|
+
"expense.posted"
|
|
954
|
+
];
|
|
955
|
+
var erpResourceMap = {
|
|
956
|
+
items: { list: "erpListItems", get: "erpGetItem" },
|
|
957
|
+
variants: { list: "erpListVariants" },
|
|
958
|
+
warehouses: { list: "erpListWarehouses" },
|
|
959
|
+
stock: { levels: "erpListStockLevels", moves: "erpListStockMoves" },
|
|
960
|
+
customers: { list: "erpListCustomers", get: "erpGetCustomer", statement: "erpCustomerStatement" },
|
|
961
|
+
salesOrders: { list: "erpListSalesOrders", get: "erpGetSalesOrder", create: "erpCreateSalesOrder", confirm: "erpConfirmSalesOrder" },
|
|
962
|
+
invoices: {
|
|
963
|
+
list: "erpListInvoices",
|
|
964
|
+
get: "erpGetInvoice",
|
|
965
|
+
create: "erpCreateInvoice",
|
|
966
|
+
issue: "erpIssueInvoice",
|
|
967
|
+
pdfLink: "erpInvoicePdfLink",
|
|
968
|
+
createCreditNote: "erpCreateCreditNote"
|
|
969
|
+
},
|
|
970
|
+
creditNotes: { list: "erpListCreditNotes", get: "erpGetCreditNote", issue: "erpIssueCreditNote" },
|
|
971
|
+
payments: { list: "erpListPayments", get: "erpGetPayment", record: "erpRecordPayment" },
|
|
972
|
+
suppliers: { list: "erpListSuppliers", get: "erpGetSupplier" },
|
|
973
|
+
purchaseOrders: { list: "erpListPurchaseOrders", get: "erpGetPurchaseOrder", create: "erpCreatePurchaseOrder" },
|
|
974
|
+
bills: { list: "erpListBills", get: "erpGetBill" },
|
|
975
|
+
expenses: { list: "erpListExpenses", get: "erpGetExpense", create: "erpCreateExpense", categories: "erpListExpenseCategories" },
|
|
976
|
+
accounting: {
|
|
977
|
+
accounts: "erpListAccounts",
|
|
978
|
+
journalEntries: "erpListJournalEntries",
|
|
979
|
+
journalEntry: "erpGetJournalEntry",
|
|
980
|
+
profitAndLoss: "erpReportProfitAndLoss",
|
|
981
|
+
balanceSheet: "erpReportBalanceSheet",
|
|
982
|
+
vat: "erpReportVat"
|
|
983
|
+
},
|
|
984
|
+
hooks: {
|
|
985
|
+
list: "erpListHooks",
|
|
986
|
+
events: "erpHookEvents",
|
|
987
|
+
sample: "erpHookSample",
|
|
988
|
+
subscribe: "erpSubscribeHook",
|
|
989
|
+
unsubscribe: "erpUnsubscribeHook"
|
|
990
|
+
}
|
|
991
|
+
};
|
|
992
|
+
var UNSAFE2 = /* @__PURE__ */ new Set(["POST", "PATCH", "PUT", "DELETE"]);
|
|
993
|
+
function erpBaseUrl(workspace) {
|
|
994
|
+
const raw = workspace.trim();
|
|
995
|
+
if (raw === "") throw new TypeError("LetsBotErp: `workspace` is empty");
|
|
996
|
+
const host = (/^https?:\/\//i.test(raw) ? new URL(raw).host : raw.split("/")[0]).toLowerCase();
|
|
997
|
+
return `https://${host.includes(".") ? host : `${host}.letsbot.net`}/api/v1/erp`;
|
|
998
|
+
}
|
|
999
|
+
var ErpTransport = class extends LetsBotClient {
|
|
1000
|
+
authHeaders(apiKey) {
|
|
1001
|
+
return { "X-Zapier-Api-Key": apiKey };
|
|
1002
|
+
}
|
|
1003
|
+
request(operationId, method, url, json, idempotent, options) {
|
|
1004
|
+
const headers = this.baseHeaders(options);
|
|
1005
|
+
let body;
|
|
1006
|
+
if (json !== void 0) {
|
|
1007
|
+
headers["Content-Type"] = "application/json";
|
|
1008
|
+
body = JSON.stringify(json);
|
|
1009
|
+
}
|
|
1010
|
+
let idempotencyKey;
|
|
1011
|
+
if (idempotent && options.idempotencyKey !== false) {
|
|
1012
|
+
idempotencyKey = options.idempotencyKey ?? this.newKey();
|
|
1013
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
1014
|
+
}
|
|
1015
|
+
const unsafeRetryAllowed = !UNSAFE2.has(method) || idempotencyKey !== void 0;
|
|
1016
|
+
return this.perform(operationId, method, url, headers, body, { idempotencyKey, unsafeRetryAllowed }, options);
|
|
1017
|
+
}
|
|
1018
|
+
get root() {
|
|
1019
|
+
return this.baseUrl;
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
var LetsBotErp = class {
|
|
1023
|
+
items;
|
|
1024
|
+
variants;
|
|
1025
|
+
warehouses;
|
|
1026
|
+
stock;
|
|
1027
|
+
customers;
|
|
1028
|
+
salesOrders;
|
|
1029
|
+
invoices;
|
|
1030
|
+
creditNotes;
|
|
1031
|
+
payments;
|
|
1032
|
+
suppliers;
|
|
1033
|
+
purchaseOrders;
|
|
1034
|
+
bills;
|
|
1035
|
+
expenses;
|
|
1036
|
+
accounting;
|
|
1037
|
+
hooks;
|
|
1038
|
+
transport;
|
|
1039
|
+
constructor(options) {
|
|
1040
|
+
if (!options?.baseUrl && !options?.workspace) {
|
|
1041
|
+
throw new TypeError("LetsBotErp: pass `workspace` (e.g. mystore.letsbot.net) or `baseUrl`");
|
|
1042
|
+
}
|
|
1043
|
+
this.transport = new ErpTransport(
|
|
1044
|
+
{
|
|
1045
|
+
...options,
|
|
1046
|
+
baseUrl: options.baseUrl ?? erpBaseUrl(options.workspace),
|
|
1047
|
+
rateLimit: options.rateLimit === false ? false : { requestsPerMinute: options.rateLimit?.requestsPerMinute ?? ERP_DEFAULT_RATE_LIMIT }
|
|
1048
|
+
},
|
|
1049
|
+
"LetsBotErp: `apiKey` (a workspace API key with the erp scope)"
|
|
1050
|
+
);
|
|
1051
|
+
const bind = (map) => {
|
|
1052
|
+
const bound = {};
|
|
1053
|
+
for (const [name, id] of Object.entries(map)) {
|
|
1054
|
+
bound[name] = (params, options2) => this.call(id, ...[params, options2]);
|
|
1055
|
+
}
|
|
1056
|
+
return bound;
|
|
1057
|
+
};
|
|
1058
|
+
this.items = bind(erpResourceMap.items);
|
|
1059
|
+
this.variants = bind(erpResourceMap.variants);
|
|
1060
|
+
this.warehouses = bind(erpResourceMap.warehouses);
|
|
1061
|
+
this.stock = bind(erpResourceMap.stock);
|
|
1062
|
+
this.customers = bind(erpResourceMap.customers);
|
|
1063
|
+
this.salesOrders = bind(erpResourceMap.salesOrders);
|
|
1064
|
+
this.invoices = bind(erpResourceMap.invoices);
|
|
1065
|
+
this.creditNotes = bind(erpResourceMap.creditNotes);
|
|
1066
|
+
this.payments = bind(erpResourceMap.payments);
|
|
1067
|
+
this.suppliers = bind(erpResourceMap.suppliers);
|
|
1068
|
+
this.purchaseOrders = bind(erpResourceMap.purchaseOrders);
|
|
1069
|
+
this.bills = bind(erpResourceMap.bills);
|
|
1070
|
+
this.expenses = bind(erpResourceMap.expenses);
|
|
1071
|
+
this.accounting = bind(erpResourceMap.accounting);
|
|
1072
|
+
this.hooks = bind(erpResourceMap.hooks);
|
|
1073
|
+
}
|
|
1074
|
+
/** The resolved base URL, e.g. `https://mystore.letsbot.net/api/v1/erp`. */
|
|
1075
|
+
get baseUrl() {
|
|
1076
|
+
return this.transport.root;
|
|
1077
|
+
}
|
|
1078
|
+
/** Call any ERP operation by its operationId and get the body. */
|
|
1079
|
+
async call(operationId, ...args) {
|
|
1080
|
+
return (await this.callWithResponse(operationId, ...args)).data;
|
|
1081
|
+
}
|
|
1082
|
+
/** Call any ERP operation and get the body plus status, headers, Idempotency-Key and replay flag. */
|
|
1083
|
+
async callWithResponse(operationId, ...args) {
|
|
1084
|
+
const [params = {}, options = {}] = args;
|
|
1085
|
+
const meta = erpOperations[operationId];
|
|
1086
|
+
if (!meta) throw new TypeError(`Unknown LetsBot ERP operation: ${String(operationId)}`);
|
|
1087
|
+
const rest = { ...params };
|
|
1088
|
+
const path = meta.path.replace(/\{(\w+)\}/g, (_, name) => {
|
|
1089
|
+
const value = rest[name];
|
|
1090
|
+
if (value === void 0 || value === null || value === "") {
|
|
1091
|
+
throw new TypeError(`${operationId}: \`${name}\` is required`);
|
|
1092
|
+
}
|
|
1093
|
+
delete rest[name];
|
|
1094
|
+
return encodeURIComponent(String(value));
|
|
1095
|
+
});
|
|
1096
|
+
const url = new URL(this.transport.root + path);
|
|
1097
|
+
if (!meta.body) {
|
|
1098
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
1099
|
+
if (value === void 0 || value === null) continue;
|
|
1100
|
+
url.searchParams.append(key, typeof value === "object" ? JSON.stringify(value) : String(value));
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
return this.transport.request(operationId, meta.method, url, meta.body ? rest : void 0, meta.idempotent, options);
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Every row of a list, page by page (`meta.last_page`).
|
|
1107
|
+
*
|
|
1108
|
+
* ```ts
|
|
1109
|
+
* for await (const invoice of erp.iterate('erpListInvoices', { status: 'issued,partially_paid', overdue: true })) { … }
|
|
1110
|
+
* ```
|
|
1111
|
+
*/
|
|
1112
|
+
async *iterate(operationId, params = {}, options) {
|
|
1113
|
+
for (let page = 1; ; page++) {
|
|
1114
|
+
const body = await this.call(operationId, ...[{ per_page: 100, ...params, page }, options]);
|
|
1115
|
+
yield* body.data;
|
|
1116
|
+
if (body.data.length === 0 || page >= (body.meta?.last_page ?? page)) return;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
function verifyErpWebhookSignature(rawBody, header, secret, options = {}) {
|
|
1121
|
+
return verifyCrmWebhookSignature(rawBody, header, secret, options);
|
|
1122
|
+
}
|
|
814
1123
|
var IDENTITY_MAX_SUB_LENGTH = 191;
|
|
815
1124
|
var IDENTITY_MAX_TTL_SECONDS = 7 * 24 * 60 * 60;
|
|
816
1125
|
var IDENTITY_DEFAULT_TTL = "24h";
|
|
@@ -887,6 +1196,8 @@ var LetsBot = class extends LetsBotClient {
|
|
|
887
1196
|
user;
|
|
888
1197
|
instance;
|
|
889
1198
|
products;
|
|
1199
|
+
/** Store orders: record one (order journey + invoice) or stop its journey. */
|
|
1200
|
+
orders;
|
|
890
1201
|
session;
|
|
891
1202
|
archive;
|
|
892
1203
|
constructor(options) {
|
|
@@ -902,6 +1213,7 @@ var LetsBot = class extends LetsBotClient {
|
|
|
902
1213
|
this.user = bindResource(this, resourceMap.user);
|
|
903
1214
|
this.instance = bindResource(this, resourceMap.instance);
|
|
904
1215
|
this.products = bindResource(this, resourceMap.products);
|
|
1216
|
+
this.orders = bindResource(this, resourceMap.orders);
|
|
905
1217
|
this.session = bindResource(this, resourceMap.session);
|
|
906
1218
|
this.archive = {
|
|
907
1219
|
...bindResource(this, resourceMap.archive),
|
|
@@ -910,6 +1222,6 @@ var LetsBot = class extends LetsBotClient {
|
|
|
910
1222
|
}
|
|
911
1223
|
};
|
|
912
1224
|
|
|
913
|
-
export { CRM_DEFAULT_RATE_LIMIT, CRM_SIGNATURE_HEADER, DEFAULT_BASE_URL, IDENTITY_DEFAULT_TTL, IDENTITY_MAX_SUB_LENGTH, IDENTITY_MAX_TTL_SECONDS, LEGACY_WEBHOOK_SECRET, LetsBot, LetsBotApiError, LetsBotClient, LetsBotConnectionError, LetsBotCrm, SDK_VERSION, TokenBucket, createIdentityToken, crmBaseUrl, crmOperations, crmResourceMap, experimental_verifyWebhookSignature, isLogicalFailure, operations, resourceMap, verifyCrmWebhookSignature };
|
|
1225
|
+
export { CRM_DEFAULT_RATE_LIMIT, CRM_SIGNATURE_HEADER, CRM_WEBHOOK_EVENTS, DEFAULT_BASE_URL, ERP_DEFAULT_RATE_LIMIT, ERP_WEBHOOK_EVENTS, IDENTITY_DEFAULT_TTL, IDENTITY_MAX_SUB_LENGTH, IDENTITY_MAX_TTL_SECONDS, LEGACY_WEBHOOK_SECRET, LetsBot, LetsBotApiError, LetsBotClient, LetsBotConnectionError, LetsBotCrm, LetsBotErp, SDK_VERSION, TokenBucket, createIdentityToken, crmBaseUrl, crmOperations, crmPossibleDuplicate, crmResourceMap, erpBaseUrl, erpOperations, erpResourceMap, experimental_verifyWebhookSignature, isLogicalFailure, operations, resourceMap, verifyCrmWebhookSignature, verifyErpWebhookSignature };
|
|
914
1226
|
//# sourceMappingURL=index.js.map
|
|
915
1227
|
//# sourceMappingURL=index.js.map
|