@bacano/sdk 1.0.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/index.cjs ADDED
@@ -0,0 +1,4956 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // libs/sdk/src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AuthError: () => AuthError,
24
+ CheckoutError: () => CheckoutError,
25
+ GraphQLRequestError: () => GraphQLRequestError,
26
+ NotInitializedError: () => NotInitializedError,
27
+ WebsiteError: () => WebsiteError,
28
+ buildStorageFileUrl: () => buildStorageFileUrl,
29
+ buildStorageMediaUrls: () => buildStorageMediaUrls,
30
+ createBacanoClient: () => createBacanoClient,
31
+ getPrimaryProductImage: () => getPrimaryProductImage,
32
+ getProductImages: () => getProductImages,
33
+ getProductMediaByKind: () => getProductMediaByKind,
34
+ getProductMediaKind: () => getProductMediaKind,
35
+ getProductVideos: () => getProductVideos,
36
+ getWebsitePublicConfig: () => getWebsitePublicConfig,
37
+ resolveProductPricing: () => resolveProductPricing
38
+ });
39
+ module.exports = __toCommonJS(index_exports);
40
+
41
+ // libs/sdk/src/errors.ts
42
+ var WebsiteError = class extends Error {
43
+ code;
44
+ constructor(message, code = "WEBSITE_ERROR") {
45
+ super(message);
46
+ this.name = "WebsiteError";
47
+ this.code = code;
48
+ }
49
+ };
50
+ var NotInitializedError = class extends WebsiteError {
51
+ constructor() {
52
+ super(
53
+ "BacanoClient has not been initialized. Call client.init() first.",
54
+ "NOT_INITIALIZED"
55
+ );
56
+ this.name = "NotInitializedError";
57
+ }
58
+ };
59
+ var AuthError = class extends WebsiteError {
60
+ constructor(message) {
61
+ super(message, "AUTH_ERROR");
62
+ this.name = "AuthError";
63
+ }
64
+ };
65
+ var CheckoutError = class extends WebsiteError {
66
+ errors;
67
+ constructor(errors) {
68
+ super(errors.join("; "), "CHECKOUT_ERROR");
69
+ this.name = "CheckoutError";
70
+ this.errors = errors;
71
+ }
72
+ };
73
+ var GraphQLRequestError = class extends WebsiteError {
74
+ graphqlErrors;
75
+ constructor(errors) {
76
+ const message = errors.map((e) => e.message).join("; ");
77
+ super(message, "GRAPHQL_ERROR");
78
+ this.name = "GraphQLRequestError";
79
+ this.graphqlErrors = errors;
80
+ }
81
+ };
82
+
83
+ // libs/sdk/src/modules/auth.ts
84
+ function createAuthHeaders(accessToken) {
85
+ return accessToken ? { Authorization: `Bearer ${accessToken}` } : {};
86
+ }
87
+ function createRequestHeadersProvider(websiteSlug, getAccessToken) {
88
+ return async () => {
89
+ const headers = { "X-Bacano-Website-Slug": websiteSlug };
90
+ if (!getAccessToken) return headers;
91
+ try {
92
+ return {
93
+ ...headers,
94
+ ...createAuthHeaders(await getAccessToken())
95
+ };
96
+ } catch (error) {
97
+ throw new AuthError(
98
+ `Could not obtain the buyer access token: ${error instanceof Error ? error.message : String(error)}`
99
+ );
100
+ }
101
+ };
102
+ }
103
+ async function getWebsitePublicConfig(options) {
104
+ const apiUrl = options.apiUrl.replace(/\/+$/, "");
105
+ const headers = options.origin ? { Origin: options.origin } : void 0;
106
+ const params = new URLSearchParams({ websiteSlug: options.websiteSlug });
107
+ let response;
108
+ try {
109
+ response = await fetch(
110
+ `${apiUrl}/api/v1/website/public-config?${params.toString()}`,
111
+ {
112
+ headers,
113
+ cache: "no-store"
114
+ }
115
+ );
116
+ } catch (error) {
117
+ throw new WebsiteError(
118
+ `Could not load website auth configuration: ${error instanceof Error ? error.message : String(error)}`,
119
+ "NETWORK_ERROR"
120
+ );
121
+ }
122
+ if (!response.ok) {
123
+ throw new WebsiteError(
124
+ `Could not load website auth configuration (status ${response.status})`,
125
+ response.status === 403 ? "ORIGIN_NOT_ALLOWED" : "INVALID_RESPONSE"
126
+ );
127
+ }
128
+ const raw = await response.json();
129
+ const customerIdentification = raw.customer_identification ?? {
130
+ primary_identifier: "AUTO",
131
+ require_email: false,
132
+ require_phone: false,
133
+ require_document: false,
134
+ document_types: []
135
+ };
136
+ return {
137
+ websiteId: raw.website_id,
138
+ companyId: raw.company_id,
139
+ slug: raw.slug,
140
+ name: raw.name,
141
+ domain: raw.domain,
142
+ buyerAccountsEnabled: raw.buyer_accounts_enabled,
143
+ clerkPublishableKey: raw.clerk_publishable_key,
144
+ customerIdentification: {
145
+ primaryIdentifier: customerIdentification.primary_identifier,
146
+ requireEmail: customerIdentification.require_email,
147
+ requirePhone: customerIdentification.require_phone,
148
+ requireDocument: customerIdentification.require_document,
149
+ documentTypes: customerIdentification.document_types.map(
150
+ (documentType) => ({
151
+ code: documentType.code,
152
+ name: documentType.name,
153
+ shortLabel: documentType.short_label,
154
+ isDefault: documentType.is_default
155
+ })
156
+ )
157
+ }
158
+ };
159
+ }
160
+
161
+ // libs/sdk/src/transport/graphql.ts
162
+ async function executeGraphQL(url, query, variables, headers) {
163
+ const resolvedHeaders = typeof headers === "function" ? await headers() : headers ?? {};
164
+ let res;
165
+ try {
166
+ res = await fetch(url, {
167
+ method: "POST",
168
+ headers: {
169
+ "Content-Type": "application/json",
170
+ ...resolvedHeaders
171
+ },
172
+ body: JSON.stringify({ query, variables })
173
+ });
174
+ } catch (err) {
175
+ throw new WebsiteError(
176
+ `Network error connecting to ${url}: ${err instanceof Error ? err.message : String(err)}`,
177
+ "NETWORK_ERROR"
178
+ );
179
+ }
180
+ if (res.status === 429) {
181
+ throw new WebsiteError(
182
+ "Rate limit exceeded. Please try again later.",
183
+ "RATE_LIMITED"
184
+ );
185
+ }
186
+ let body;
187
+ try {
188
+ body = await res.json();
189
+ } catch {
190
+ throw new WebsiteError(
191
+ `Non-JSON response from ${url} (status ${res.status})`,
192
+ "INVALID_RESPONSE"
193
+ );
194
+ }
195
+ if (body.errors && body.errors.length > 0) {
196
+ throw new GraphQLRequestError(body.errors);
197
+ }
198
+ if (!body.data) {
199
+ throw new WebsiteError(
200
+ "GraphQL response contains no data",
201
+ "EMPTY_RESPONSE"
202
+ );
203
+ }
204
+ return body.data;
205
+ }
206
+
207
+ // libs/sdk/src/transport/documents.ts
208
+ var RESOLVE_WEBSITE_BY_SLUG = (
209
+ /* GraphQL */
210
+ `
211
+ query ResolveWebsiteBySlug($slug: String!) {
212
+ websites(
213
+ where: { slug: { _eq: $slug }, is_active: { _eq: true } }
214
+ limit: 1
215
+ ) {
216
+ id
217
+ company_id
218
+ chain_id
219
+ name
220
+ slug
221
+ domain
222
+ config
223
+ }
224
+ }
225
+ `
226
+ );
227
+ var GET_PRODUCTS = (
228
+ /* GraphQL */
229
+ `
230
+ query GetProducts(
231
+ $companyId: uuid!
232
+ $chainId: uuid!
233
+ $websiteId: uuid!
234
+ $limit: Int = 20
235
+ $offset: Int = 0
236
+ $where: products_bool_exp = {}
237
+ $orderBy: [products_order_by!] = [{ name: asc }]
238
+ ) {
239
+ products(
240
+ where: {
241
+ _and: [
242
+ { company_id: { _eq: $companyId } }
243
+ {
244
+ product_website_publications: {
245
+ website_id: { _eq: $websiteId }
246
+ is_visible: { _eq: true }
247
+ }
248
+ }
249
+ {
250
+ chain_products: {
251
+ chain_id: { _eq: $chainId }
252
+ is_enabled: { _eq: true }
253
+ status: { _eq: active }
254
+ }
255
+ }
256
+ $where
257
+ ]
258
+ }
259
+ limit: $limit
260
+ offset: $offset
261
+ order_by: $orderBy
262
+ ) {
263
+ id
264
+ name
265
+ description
266
+ long_description
267
+ slug
268
+ seo_title
269
+ seo_description
270
+ seo_image_file_id
271
+ category
272
+ subcategory
273
+ color
274
+ measurement_unit
275
+ created_at
276
+ updated_at
277
+ brand {
278
+ id
279
+ name
280
+ }
281
+ seo_image_file {
282
+ mimeType
283
+ name
284
+ }
285
+ product_variants(
286
+ where: { is_disabled: { _eq: false } }
287
+ order_by: { order: asc }
288
+ ) {
289
+ id
290
+ sku
291
+ barcode
292
+ order
293
+ weight
294
+ depth
295
+ height
296
+ length
297
+ product_variant_prices(
298
+ where: {
299
+ price_type: { _in: [CLIENT, SALE, WHOLESALE, WHOLESALE_2] }
300
+ _or: [
301
+ { chain_id: { _eq: $chainId } }
302
+ { chain_id: { _is_null: true } }
303
+ ]
304
+ }
305
+ ) {
306
+ id
307
+ price
308
+ price_type
309
+ chain_id
310
+ }
311
+ product_variant_attributes(order_by: { order: asc }) {
312
+ id
313
+ value
314
+ order
315
+ attribute_value {
316
+ id
317
+ code
318
+ sort_order
319
+ metadata
320
+ }
321
+ attribute {
322
+ id
323
+ name
324
+ }
325
+ }
326
+ }
327
+ product_media(order_by: { order: asc }) {
328
+ id
329
+ file_id
330
+ order
331
+ file {
332
+ mimeType
333
+ name
334
+ }
335
+ }
336
+ product_related_products(
337
+ where: {
338
+ related_product: {
339
+ chain_products: {
340
+ chain_id: { _eq: $chainId }
341
+ is_enabled: { _eq: true }
342
+ status: { _eq: active }
343
+ }
344
+ }
345
+ }
346
+ order_by: { sort_order: asc }
347
+ ) {
348
+ id
349
+ related_product_id
350
+ display_label
351
+ sort_order
352
+ related_product {
353
+ id
354
+ slug
355
+ name
356
+ sku
357
+ product_media(
358
+ where: { file: { mimeType: { _ilike: "image/%" } } }
359
+ order_by: { order: asc }
360
+ limit: 1
361
+ ) {
362
+ id
363
+ file_id
364
+ order
365
+ file {
366
+ mimeType
367
+ name
368
+ }
369
+ }
370
+ }
371
+ }
372
+ product_attributes {
373
+ id
374
+ value
375
+ attribute_value {
376
+ id
377
+ code
378
+ sort_order
379
+ metadata
380
+ }
381
+ attribute {
382
+ id
383
+ name
384
+ }
385
+ }
386
+ }
387
+ catalog_attribute_lists(
388
+ where: { company_id: { _eq: $companyId }, status: { _eq: published } }
389
+ order_by: { updated_at: desc }
390
+ ) {
391
+ id
392
+ key
393
+ name
394
+ description
395
+ status
396
+ items(
397
+ where: { is_visible: { _eq: true } }
398
+ order_by: [{ sort_order: asc }, { public_label: asc }]
399
+ ) {
400
+ id
401
+ attribute_id
402
+ public_label
403
+ public_slug
404
+ sort_order
405
+ attribute {
406
+ id
407
+ name
408
+ type
409
+ }
410
+ values(
411
+ where: { is_visible: { _eq: true } }
412
+ order_by: [{ sort_order: asc }, { public_label: asc }]
413
+ ) {
414
+ id
415
+ attribute_value_id
416
+ public_label
417
+ public_slug
418
+ sort_order
419
+ attribute_value {
420
+ id
421
+ code
422
+ metadata
423
+ }
424
+ }
425
+ }
426
+ }
427
+ }
428
+ `
429
+ );
430
+ var GET_PRODUCT_BY_PK = (
431
+ /* GraphQL */
432
+ `
433
+ query GetProductByPk(
434
+ $productId: uuid!
435
+ $companyId: uuid!
436
+ $chainId: uuid!
437
+ $websiteId: uuid!
438
+ ) {
439
+ products(
440
+ where: {
441
+ id: { _eq: $productId }
442
+ company_id: { _eq: $companyId }
443
+ product_website_publications: {
444
+ website_id: { _eq: $websiteId }
445
+ is_visible: { _eq: true }
446
+ }
447
+ chain_products: {
448
+ chain_id: { _eq: $chainId }
449
+ is_enabled: { _eq: true }
450
+ status: { _eq: active }
451
+ }
452
+ }
453
+ limit: 1
454
+ ) {
455
+ id
456
+ name
457
+ description
458
+ long_description
459
+ slug
460
+ seo_title
461
+ seo_description
462
+ seo_image_file_id
463
+ category
464
+ subcategory
465
+ color
466
+ measurement_unit
467
+ created_at
468
+ updated_at
469
+ brand {
470
+ id
471
+ name
472
+ }
473
+ seo_image_file {
474
+ mimeType
475
+ name
476
+ }
477
+ product_variants(
478
+ where: { is_disabled: { _eq: false } }
479
+ order_by: { order: asc }
480
+ ) {
481
+ id
482
+ sku
483
+ barcode
484
+ order
485
+ weight
486
+ depth
487
+ height
488
+ length
489
+ product_variant_prices(
490
+ where: {
491
+ price_type: { _in: [CLIENT, SALE, WHOLESALE, WHOLESALE_2] }
492
+ _or: [
493
+ { chain_id: { _eq: $chainId } }
494
+ { chain_id: { _is_null: true } }
495
+ ]
496
+ }
497
+ ) {
498
+ id
499
+ price
500
+ price_type
501
+ chain_id
502
+ }
503
+ product_variant_attributes(order_by: { order: asc }) {
504
+ id
505
+ value
506
+ order
507
+ attribute_value {
508
+ id
509
+ code
510
+ sort_order
511
+ metadata
512
+ }
513
+ attribute {
514
+ id
515
+ name
516
+ }
517
+ }
518
+ }
519
+ product_media(order_by: { order: asc }) {
520
+ id
521
+ file_id
522
+ order
523
+ file {
524
+ mimeType
525
+ name
526
+ }
527
+ }
528
+ product_related_products(
529
+ where: {
530
+ related_product: {
531
+ chain_products: {
532
+ chain_id: { _eq: $chainId }
533
+ is_enabled: { _eq: true }
534
+ status: { _eq: active }
535
+ }
536
+ }
537
+ }
538
+ order_by: { sort_order: asc }
539
+ ) {
540
+ id
541
+ related_product_id
542
+ display_label
543
+ sort_order
544
+ related_product {
545
+ id
546
+ slug
547
+ name
548
+ sku
549
+ product_media(
550
+ where: { file: { mimeType: { _ilike: "image/%" } } }
551
+ order_by: { order: asc }
552
+ limit: 1
553
+ ) {
554
+ id
555
+ file_id
556
+ order
557
+ file {
558
+ mimeType
559
+ name
560
+ }
561
+ }
562
+ }
563
+ }
564
+ product_attributes {
565
+ id
566
+ value
567
+ attribute_value {
568
+ id
569
+ code
570
+ sort_order
571
+ metadata
572
+ }
573
+ attribute {
574
+ id
575
+ name
576
+ }
577
+ }
578
+ }
579
+ catalog_attribute_lists(
580
+ where: { company_id: { _eq: $companyId }, status: { _eq: published } }
581
+ order_by: { updated_at: desc }
582
+ ) {
583
+ id
584
+ key
585
+ name
586
+ description
587
+ status
588
+ items(
589
+ where: { is_visible: { _eq: true } }
590
+ order_by: [{ sort_order: asc }, { public_label: asc }]
591
+ ) {
592
+ id
593
+ attribute_id
594
+ public_label
595
+ public_slug
596
+ sort_order
597
+ attribute {
598
+ id
599
+ name
600
+ type
601
+ }
602
+ values(
603
+ where: { is_visible: { _eq: true } }
604
+ order_by: [{ sort_order: asc }, { public_label: asc }]
605
+ ) {
606
+ id
607
+ attribute_value_id
608
+ public_label
609
+ public_slug
610
+ sort_order
611
+ attribute_value {
612
+ id
613
+ code
614
+ metadata
615
+ }
616
+ }
617
+ }
618
+ }
619
+ }
620
+ `
621
+ );
622
+ var GET_PRODUCT_BY_SLUG = (
623
+ /* GraphQL */
624
+ GET_PRODUCT_BY_PK.replace(
625
+ "query GetProductByPk(",
626
+ "query GetProductBySlug("
627
+ ).replace("$productId: uuid!", "$slug: String!").replace("id: { _eq: $productId }", "slug: { _eq: $slug }")
628
+ );
629
+ var GET_PRODUCT_SEO_ENTRIES = (
630
+ /* GraphQL */
631
+ `
632
+ query GetProductSeoEntries(
633
+ $companyId: uuid!
634
+ $chainId: uuid!
635
+ $websiteId: uuid!
636
+ $limit: Int!
637
+ $offset: Int!
638
+ ) {
639
+ products(
640
+ where: {
641
+ company_id: { _eq: $companyId }
642
+ slug: { _is_null: false }
643
+ product_website_publications: {
644
+ website_id: { _eq: $websiteId }
645
+ is_visible: { _eq: true }
646
+ }
647
+ chain_products: {
648
+ chain_id: { _eq: $chainId }
649
+ is_enabled: { _eq: true }
650
+ status: { _eq: active }
651
+ }
652
+ }
653
+ limit: $limit
654
+ offset: $offset
655
+ order_by: [{ updated_at: desc }, { created_at: desc }]
656
+ ) {
657
+ id
658
+ name
659
+ slug
660
+ seo_title
661
+ seo_description
662
+ seo_image_file_id
663
+ category
664
+ subcategory
665
+ created_at
666
+ updated_at
667
+ seo_image_file {
668
+ mimeType
669
+ name
670
+ }
671
+ product_media(
672
+ where: { file: { mimeType: { _ilike: "image/%" } } }
673
+ order_by: { order: asc }
674
+ limit: 1
675
+ ) {
676
+ id
677
+ file_id
678
+ order
679
+ file {
680
+ mimeType
681
+ name
682
+ }
683
+ }
684
+ product_variants(
685
+ where: { is_disabled: { _eq: false } }
686
+ order_by: { order: asc }
687
+ ) {
688
+ id
689
+ product_variant_prices(
690
+ where: {
691
+ price_type: { _in: [CLIENT, SALE, WHOLESALE, WHOLESALE_2] }
692
+ _or: [
693
+ { chain_id: { _eq: $chainId } }
694
+ { chain_id: { _is_null: true } }
695
+ ]
696
+ }
697
+ ) {
698
+ id
699
+ price
700
+ price_type
701
+ chain_id
702
+ }
703
+ }
704
+ }
705
+ }
706
+ `
707
+ );
708
+ var GET_CATEGORIES = (
709
+ /* GraphQL */
710
+ `
711
+ query GetCategories {
712
+ product_categories {
713
+ name
714
+ description
715
+ product_subcategories {
716
+ id
717
+ name
718
+ description
719
+ }
720
+ }
721
+ }
722
+ `
723
+ );
724
+ var GET_CATALOG_CATEGORY_LIST = (
725
+ /* GraphQL */
726
+ `
727
+ query GetCatalogCategoryList($companyId: uuid!, $key: String!) {
728
+ list: catalog_category_lists(
729
+ where: {
730
+ company_id: { _eq: $companyId }
731
+ key: { _eq: $key }
732
+ status: { _eq: published }
733
+ }
734
+ limit: 1
735
+ ) {
736
+ id
737
+ key
738
+ name
739
+ description
740
+ status
741
+ items(
742
+ where: { is_visible: { _eq: true } }
743
+ order_by: [{ sort_order: asc }, { public_label: asc }]
744
+ ) {
745
+ id
746
+ source_type
747
+ product_category
748
+ product_subcategory_id
749
+ public_label
750
+ public_slug
751
+ sort_order
752
+ category_ref {
753
+ name
754
+ description
755
+ }
756
+ subcategory_ref {
757
+ id
758
+ name
759
+ description
760
+ category
761
+ }
762
+ }
763
+ }
764
+ }
765
+ `
766
+ );
767
+ var GET_CATALOG_ATTRIBUTE_LIST = (
768
+ /* GraphQL */
769
+ `
770
+ query GetCatalogAttributeList($companyId: uuid!, $key: String!) {
771
+ list: catalog_attribute_lists(
772
+ where: {
773
+ company_id: { _eq: $companyId }
774
+ key: { _eq: $key }
775
+ status: { _eq: published }
776
+ }
777
+ limit: 1
778
+ ) {
779
+ id
780
+ key
781
+ name
782
+ description
783
+ status
784
+ items(
785
+ where: { is_visible: { _eq: true } }
786
+ order_by: [{ sort_order: asc }, { public_label: asc }]
787
+ ) {
788
+ id
789
+ attribute_id
790
+ public_label
791
+ public_slug
792
+ sort_order
793
+ attribute {
794
+ id
795
+ name
796
+ type
797
+ }
798
+ values(
799
+ where: { is_visible: { _eq: true } }
800
+ order_by: [{ sort_order: asc }, { public_label: asc }]
801
+ ) {
802
+ id
803
+ attribute_value_id
804
+ public_label
805
+ public_slug
806
+ sort_order
807
+ attribute_value {
808
+ id
809
+ code
810
+ metadata
811
+ }
812
+ }
813
+ }
814
+ }
815
+ }
816
+ `
817
+ );
818
+ var GET_CONTEXTUAL_CATALOG_ATTRIBUTE_LIST = (
819
+ /* GraphQL */
820
+ `
821
+ mutation GetContextualCatalogAttributeList(
822
+ $websiteId: uuid!
823
+ $key: String!
824
+ $onlyApplicable: Boolean
825
+ $filters: WebsiteCatalogFiltersInput
826
+ ) {
827
+ websiteGetAttributeList(
828
+ website_id: $websiteId
829
+ key: $key
830
+ only_applicable: $onlyApplicable
831
+ filters: $filters
832
+ ) {
833
+ success
834
+ errors
835
+ list {
836
+ id
837
+ key
838
+ name
839
+ description
840
+ status
841
+ items {
842
+ id
843
+ attribute_id
844
+ attribute_name
845
+ attribute_type
846
+ public_label
847
+ public_slug
848
+ sort_order
849
+ values {
850
+ id
851
+ attribute_value_id
852
+ code
853
+ public_label
854
+ public_slug
855
+ sort_order
856
+ metadata
857
+ }
858
+ }
859
+ }
860
+ }
861
+ }
862
+ `
863
+ );
864
+ var WEBSITE_GET_CATALOG_PAGE = (
865
+ /* GraphQL */
866
+ `
867
+ mutation WebsiteGetCatalogPage(
868
+ $websiteId: uuid!
869
+ $categoryListKey: String!
870
+ $attributeListKey: String!
871
+ $filters: WebsiteCatalogPageFiltersInput
872
+ $include: WebsiteCatalogPageIncludeInput
873
+ ) {
874
+ result: websiteGetCatalogPage(
875
+ website_id: $websiteId
876
+ category_list_key: $categoryListKey
877
+ attribute_list_key: $attributeListKey
878
+ filters: $filters
879
+ include: $include
880
+ ) {
881
+ success
882
+ products
883
+ category_list
884
+ attribute_list
885
+ filters
886
+ brands
887
+ pagination
888
+ applied_filters
889
+ debug
890
+ errors
891
+ }
892
+ }
893
+ `
894
+ );
895
+ var WEBSITE_GET_PRODUCT_RECOMMENDATIONS = (
896
+ /* GraphQL */
897
+ `
898
+ mutation WebsiteGetProductRecommendations(
899
+ $websiteId: uuid!
900
+ $productId: uuid!
901
+ $limit: Int
902
+ ) {
903
+ result: websiteGetProductRecommendations(
904
+ website_id: $websiteId
905
+ product_id: $productId
906
+ limit: $limit
907
+ ) {
908
+ success
909
+ products
910
+ strategy
911
+ errors
912
+ }
913
+ }
914
+ `
915
+ );
916
+ var GET_BRANDS = (
917
+ /* GraphQL */
918
+ `
919
+ query GetBrands($companyId: uuid!, $chainId: uuid!) {
920
+ brands(
921
+ where: {
922
+ company_id: { _eq: $companyId }
923
+ products: {
924
+ chain_products: {
925
+ chain_id: { _eq: $chainId }
926
+ is_enabled: { _eq: true }
927
+ status: { _eq: active }
928
+ }
929
+ }
930
+ }
931
+ order_by: { name: asc }
932
+ ) {
933
+ id
934
+ name
935
+ }
936
+ }
937
+ `
938
+ );
939
+ var CONTENT_ENTRY_FIELDS = (
940
+ /* GraphQL */
941
+ `
942
+ id
943
+ key
944
+ category_key
945
+ name
946
+ locale
947
+ status
948
+ tags
949
+ content_json
950
+ resolved_fields
951
+ published_at
952
+ updated_at
953
+ content_type {
954
+ id
955
+ key
956
+ name
957
+ kind
958
+ }
959
+ `
960
+ );
961
+ var WEBSITE_GET_CONTENT = (
962
+ /* GraphQL */
963
+ `
964
+ mutation WebsiteGetContent(
965
+ $websiteId: uuid!
966
+ $key: String
967
+ $categoryKey: String
968
+ $tag: String
969
+ $locale: String
970
+ ) {
971
+ result: websiteGetContent(
972
+ website_id: $websiteId
973
+ key: $key
974
+ category_key: $categoryKey
975
+ tag: $tag
976
+ locale: $locale
977
+ ) {
978
+ success
979
+ errors
980
+ entries {
981
+ ${CONTENT_ENTRY_FIELDS}
982
+ }
983
+ }
984
+ }
985
+ `
986
+ );
987
+ var WEBSITE_GET_PRODUCT_CONTENT = (
988
+ /* GraphQL */
989
+ `
990
+ mutation WebsiteGetProductContent(
991
+ $websiteId: uuid!
992
+ $productId: uuid!
993
+ $locale: String
994
+ ) {
995
+ result: websiteGetProductContent(
996
+ website_id: $websiteId
997
+ product_id: $productId
998
+ locale: $locale
999
+ ) {
1000
+ success
1001
+ errors
1002
+ blocks {
1003
+ id
1004
+ product_id
1005
+ locale
1006
+ content_json
1007
+ resolved_fields
1008
+ sort_order
1009
+ updated_at
1010
+ content_type {
1011
+ id
1012
+ key
1013
+ name
1014
+ kind
1015
+ }
1016
+ }
1017
+ }
1018
+ }
1019
+ `
1020
+ );
1021
+ var CHECK_AVAILABILITY = (
1022
+ /* GraphQL */
1023
+ `
1024
+ query CheckAvailability($variantIds: [uuid!]!, $chainId: uuid!) {
1025
+ websiteProductAvailability(
1026
+ product_variant_ids: $variantIds
1027
+ chain_id: $chainId
1028
+ ) {
1029
+ product_variant_id
1030
+ in_stock
1031
+ label
1032
+ }
1033
+ }
1034
+ `
1035
+ );
1036
+ var CREATE_CART = (
1037
+ /* GraphQL */
1038
+ `
1039
+ mutation CreateCart(
1040
+ $websiteId: uuid!
1041
+ $cartToken: String
1042
+ $contact: WebsiteGuestContactInput
1043
+ $fulfillmentFamily: String
1044
+ ) {
1045
+ websiteCreateCart(
1046
+ website_id: $websiteId
1047
+ cart_token: $cartToken
1048
+ contact: $contact
1049
+ fulfillment_family: $fulfillmentFamily
1050
+ ) {
1051
+ success
1052
+ order_id
1053
+ cart_token
1054
+ cart {
1055
+ id
1056
+ status
1057
+ discount
1058
+ tax
1059
+ total_without_tax
1060
+ total_with_tax
1061
+ total_with_discount
1062
+ created_at
1063
+ updated_at
1064
+ items {
1065
+ id
1066
+ product_variant_id
1067
+ quantity
1068
+ product_variant {
1069
+ id
1070
+ sku
1071
+ product {
1072
+ id
1073
+ name
1074
+ }
1075
+ prices {
1076
+ id
1077
+ price
1078
+ price_type
1079
+ chain_id
1080
+ }
1081
+ }
1082
+ }
1083
+ }
1084
+ errors
1085
+ }
1086
+ }
1087
+ `
1088
+ );
1089
+ var GET_CART = (
1090
+ /* GraphQL */
1091
+ `
1092
+ mutation GetCart($orderId: uuid!, $cartToken: String!) {
1093
+ websiteGetCart(order_id: $orderId, cart_token: $cartToken) {
1094
+ success
1095
+ order_id
1096
+ cart_token
1097
+ cart {
1098
+ id
1099
+ status
1100
+ discount
1101
+ tax
1102
+ total_without_tax
1103
+ total_with_tax
1104
+ total_with_discount
1105
+ created_at
1106
+ updated_at
1107
+ items {
1108
+ id
1109
+ product_variant_id
1110
+ quantity
1111
+ product_variant {
1112
+ id
1113
+ sku
1114
+ product {
1115
+ id
1116
+ name
1117
+ }
1118
+ prices {
1119
+ id
1120
+ price
1121
+ price_type
1122
+ chain_id
1123
+ }
1124
+ }
1125
+ }
1126
+ }
1127
+ errors
1128
+ }
1129
+ }
1130
+ `
1131
+ );
1132
+ var START_GUEST_CHECKOUT = (
1133
+ /* GraphQL */
1134
+ `
1135
+ mutation StartGuestCheckout(
1136
+ $websiteId: uuid!
1137
+ $cartToken: String
1138
+ $contact: WebsiteGuestContactInput!
1139
+ $items: [WebsiteCheckoutItemInput!]!
1140
+ $fulfillmentFamily: String
1141
+ ) {
1142
+ websiteStartGuestCheckout(
1143
+ website_id: $websiteId
1144
+ cart_token: $cartToken
1145
+ contact: $contact
1146
+ items: $items
1147
+ fulfillment_family: $fulfillmentFamily
1148
+ ) {
1149
+ success
1150
+ order_id
1151
+ cart_token
1152
+ cart {
1153
+ id
1154
+ status
1155
+ discount
1156
+ tax
1157
+ total_without_tax
1158
+ total_with_tax
1159
+ total_with_discount
1160
+ created_at
1161
+ updated_at
1162
+ items {
1163
+ id
1164
+ product_variant_id
1165
+ quantity
1166
+ product_variant {
1167
+ id
1168
+ sku
1169
+ product {
1170
+ id
1171
+ name
1172
+ }
1173
+ prices {
1174
+ id
1175
+ price
1176
+ price_type
1177
+ chain_id
1178
+ }
1179
+ }
1180
+ }
1181
+ }
1182
+ errors
1183
+ }
1184
+ }
1185
+ `
1186
+ );
1187
+ var SET_CART_ITEM = (
1188
+ /* GraphQL */
1189
+ `
1190
+ mutation SetCartItem(
1191
+ $orderId: uuid!
1192
+ $cartToken: String!
1193
+ $variantId: uuid!
1194
+ $quantity: numeric!
1195
+ ) {
1196
+ websiteSetCartItem(
1197
+ order_id: $orderId
1198
+ cart_token: $cartToken
1199
+ product_variant_id: $variantId
1200
+ quantity: $quantity
1201
+ ) {
1202
+ success
1203
+ order_id
1204
+ cart_token
1205
+ cart {
1206
+ id
1207
+ status
1208
+ discount
1209
+ tax
1210
+ total_without_tax
1211
+ total_with_tax
1212
+ total_with_discount
1213
+ created_at
1214
+ updated_at
1215
+ items {
1216
+ id
1217
+ product_variant_id
1218
+ quantity
1219
+ product_variant {
1220
+ id
1221
+ sku
1222
+ product {
1223
+ id
1224
+ name
1225
+ }
1226
+ prices {
1227
+ id
1228
+ price
1229
+ price_type
1230
+ chain_id
1231
+ }
1232
+ }
1233
+ }
1234
+ }
1235
+ errors
1236
+ }
1237
+ }
1238
+ `
1239
+ );
1240
+ var REMOVE_CART_ITEM = (
1241
+ /* GraphQL */
1242
+ `
1243
+ mutation RemoveCartItem(
1244
+ $orderId: uuid!
1245
+ $cartToken: String!
1246
+ $itemId: uuid!
1247
+ ) {
1248
+ websiteRemoveCartItem(
1249
+ order_id: $orderId
1250
+ cart_token: $cartToken
1251
+ item_id: $itemId
1252
+ ) {
1253
+ success
1254
+ order_id
1255
+ cart_token
1256
+ cart {
1257
+ id
1258
+ status
1259
+ discount
1260
+ tax
1261
+ total_without_tax
1262
+ total_with_tax
1263
+ total_with_discount
1264
+ created_at
1265
+ updated_at
1266
+ items {
1267
+ id
1268
+ product_variant_id
1269
+ quantity
1270
+ product_variant {
1271
+ id
1272
+ sku
1273
+ product {
1274
+ id
1275
+ name
1276
+ }
1277
+ prices {
1278
+ id
1279
+ price
1280
+ price_type
1281
+ chain_id
1282
+ }
1283
+ }
1284
+ }
1285
+ }
1286
+ errors
1287
+ }
1288
+ }
1289
+ `
1290
+ );
1291
+ var CHECKOUT = (
1292
+ /* GraphQL */
1293
+ `
1294
+ mutation Checkout(
1295
+ $orderId: uuid!
1296
+ $cartToken: String!
1297
+ $contact: WebsiteGuestContactInput!
1298
+ $fulfillmentFamily: String
1299
+ $address: WebsiteAddressInput
1300
+ $shippingQuoteId: uuid
1301
+ $paymentMode: String
1302
+ $paymentMethodId: uuid
1303
+ $buyerAccountOptIn: Boolean
1304
+ $initialPayment: WebsiteInitialPaymentInput
1305
+ ) {
1306
+ websiteCheckout(
1307
+ order_id: $orderId
1308
+ cart_token: $cartToken
1309
+ contact: $contact
1310
+ fulfillment_family: $fulfillmentFamily
1311
+ address: $address
1312
+ shipping_quote_id: $shippingQuoteId
1313
+ payment_mode: $paymentMode
1314
+ payment_method_id: $paymentMethodId
1315
+ buyer_account_opt_in: $buyerAccountOptIn
1316
+ initial_payment: $initialPayment
1317
+ ) {
1318
+ success
1319
+ order_id
1320
+ order_number
1321
+ payment_method_id
1322
+ public_order_token
1323
+ requires_payment_session
1324
+ buyer_account_invitation_requested
1325
+ errors
1326
+ }
1327
+ }
1328
+ `
1329
+ );
1330
+ var GET_LOCATION_OPTIONS = (
1331
+ /* GraphQL */
1332
+ `
1333
+ mutation GetLocationOptions($websiteId: uuid!) {
1334
+ websiteGetLocationOptions(website_id: $websiteId) {
1335
+ success
1336
+ country_code
1337
+ departments {
1338
+ department_id
1339
+ department_name
1340
+ department_code
1341
+ municipalities {
1342
+ municipality_id
1343
+ municipality_name
1344
+ municipality_code
1345
+ department_id
1346
+ department_code
1347
+ }
1348
+ }
1349
+ errors
1350
+ }
1351
+ }
1352
+ `
1353
+ );
1354
+ var GET_DELIVERY_OPTIONS = (
1355
+ /* GraphQL */
1356
+ `
1357
+ mutation GetDeliveryOptions($websiteId: uuid!) {
1358
+ websiteGetDeliveryOptions(website_id: $websiteId) {
1359
+ success
1360
+ delivery_options {
1361
+ id
1362
+ fulfillment_family
1363
+ label
1364
+ description
1365
+ is_enabled
1366
+ pickup_info {
1367
+ label
1368
+ address
1369
+ schedule
1370
+ notes
1371
+ }
1372
+ }
1373
+ errors
1374
+ }
1375
+ }
1376
+ `
1377
+ );
1378
+ var GET_SHIPPING_QUOTES = (
1379
+ /* GraphQL */
1380
+ `
1381
+ mutation GetShippingQuotes(
1382
+ $websiteId: uuid!
1383
+ $orderId: uuid
1384
+ $cartToken: String
1385
+ $items: [WebsiteCheckoutItemInput!]
1386
+ $address: WebsiteAddressInput!
1387
+ ) {
1388
+ websiteGetShippingQuotes(
1389
+ website_id: $websiteId
1390
+ order_id: $orderId
1391
+ cart_token: $cartToken
1392
+ items: $items
1393
+ address: $address
1394
+ ) {
1395
+ success
1396
+ quotes {
1397
+ quote_id
1398
+ shipping_service_id
1399
+ label
1400
+ service_name
1401
+ base_amount
1402
+ amount
1403
+ currency
1404
+ collection_mode
1405
+ total_policy
1406
+ estimated_delivery
1407
+ free_shipping_eligible
1408
+ free_shipping_applied
1409
+ free_shipping_threshold
1410
+ free_shipping_remaining
1411
+ free_shipping_eligible_subtotal
1412
+ }
1413
+ errors
1414
+ }
1415
+ }
1416
+ `
1417
+ );
1418
+ var GET_SHIPPING_POLICY = (
1419
+ /* GraphQL */
1420
+ `
1421
+ mutation GetShippingPolicy($websiteId: uuid!) {
1422
+ websiteGetShippingPolicy(website_id: $websiteId) {
1423
+ success
1424
+ policy {
1425
+ free_shipping_enabled
1426
+ free_shipping_threshold
1427
+ currency
1428
+ }
1429
+ errors
1430
+ }
1431
+ }
1432
+ `
1433
+ );
1434
+ var GET_FREE_SHIPPING_PROGRESS = (
1435
+ /* GraphQL */
1436
+ `
1437
+ mutation GetFreeShippingProgress(
1438
+ $websiteId: uuid!
1439
+ $items: [WebsiteCheckoutItemInput!]!
1440
+ ) {
1441
+ websiteGetFreeShippingProgress(website_id: $websiteId, items: $items) {
1442
+ success
1443
+ progress {
1444
+ enabled
1445
+ threshold
1446
+ remaining
1447
+ eligible_subtotal
1448
+ threshold_reached
1449
+ currency
1450
+ }
1451
+ errors
1452
+ }
1453
+ }
1454
+ `
1455
+ );
1456
+ var GET_PAYMENT_METHODS = (
1457
+ /* GraphQL */
1458
+ `
1459
+ mutation GetPaymentMethods($websiteId: uuid!) {
1460
+ websiteGetPaymentMethods(website_id: $websiteId) {
1461
+ success
1462
+ payment_methods {
1463
+ id
1464
+ code
1465
+ label
1466
+ payment_method_type
1467
+ gateway_code
1468
+ description
1469
+ is_enabled
1470
+ sort_order
1471
+ requires_payment_session
1472
+ public_config
1473
+ }
1474
+ errors
1475
+ }
1476
+ }
1477
+ `
1478
+ );
1479
+ var GET_PAYMENT_OPTIONS = (
1480
+ /* GraphQL */
1481
+ `
1482
+ mutation GetPaymentOptions($websiteId: uuid!, $fulfillmentFamily: String!) {
1483
+ websiteGetPaymentOptions(
1484
+ website_id: $websiteId
1485
+ fulfillment_family: $fulfillmentFamily
1486
+ ) {
1487
+ success
1488
+ payment_options {
1489
+ id
1490
+ mode
1491
+ fulfillment_family
1492
+ label
1493
+ description
1494
+ requires_payment_method
1495
+ allows_initial_payment
1496
+ initial_payment_policy
1497
+ requires_initial_payment
1498
+ min_initial_amount
1499
+ suggested_initial_amount
1500
+ sort_order
1501
+ methods {
1502
+ id
1503
+ payment_method_id
1504
+ code
1505
+ label
1506
+ payment_method_type
1507
+ gateway_code
1508
+ description
1509
+ instructions
1510
+ qr_file_id
1511
+ requires_payment_session
1512
+ public_config
1513
+ sort_order
1514
+ }
1515
+ }
1516
+ errors
1517
+ }
1518
+ }
1519
+ `
1520
+ );
1521
+ var VALIDATE_COUPON = (
1522
+ /* GraphQL */
1523
+ `
1524
+ mutation ValidateCoupon(
1525
+ $orderId: uuid!
1526
+ $cartToken: String!
1527
+ $code: String!
1528
+ ) {
1529
+ websiteValidateCoupon(
1530
+ order_id: $orderId
1531
+ cart_token: $cartToken
1532
+ code: $code
1533
+ ) {
1534
+ success
1535
+ order_id
1536
+ coupon_id
1537
+ code
1538
+ name
1539
+ coupon_type
1540
+ discount_amount
1541
+ eligible_subtotal
1542
+ message
1543
+ cart {
1544
+ id
1545
+ status
1546
+ discount
1547
+ total_without_tax
1548
+ tax
1549
+ total_with_tax
1550
+ total_with_discount
1551
+ created_at
1552
+ updated_at
1553
+ items {
1554
+ id
1555
+ product_variant_id
1556
+ quantity
1557
+ product_variant {
1558
+ id
1559
+ sku
1560
+ product {
1561
+ id
1562
+ name
1563
+ }
1564
+ prices {
1565
+ id
1566
+ price
1567
+ price_type
1568
+ chain_id
1569
+ }
1570
+ }
1571
+ }
1572
+ }
1573
+ errors
1574
+ }
1575
+ }
1576
+ `
1577
+ );
1578
+ var APPLY_COUPON = (
1579
+ /* GraphQL */
1580
+ `
1581
+ mutation ApplyCoupon($orderId: uuid!, $cartToken: String!, $code: String!) {
1582
+ websiteApplyCoupon(
1583
+ order_id: $orderId
1584
+ cart_token: $cartToken
1585
+ code: $code
1586
+ ) {
1587
+ success
1588
+ order_id
1589
+ coupon_id
1590
+ code
1591
+ name
1592
+ coupon_type
1593
+ discount_amount
1594
+ eligible_subtotal
1595
+ message
1596
+ cart {
1597
+ id
1598
+ status
1599
+ discount
1600
+ total_without_tax
1601
+ tax
1602
+ total_with_tax
1603
+ total_with_discount
1604
+ created_at
1605
+ updated_at
1606
+ items {
1607
+ id
1608
+ product_variant_id
1609
+ quantity
1610
+ product_variant {
1611
+ id
1612
+ sku
1613
+ product {
1614
+ id
1615
+ name
1616
+ }
1617
+ prices {
1618
+ id
1619
+ price
1620
+ price_type
1621
+ chain_id
1622
+ }
1623
+ }
1624
+ }
1625
+ }
1626
+ errors
1627
+ }
1628
+ }
1629
+ `
1630
+ );
1631
+ var REMOVE_COUPON = (
1632
+ /* GraphQL */
1633
+ `
1634
+ mutation RemoveCoupon(
1635
+ $orderId: uuid!
1636
+ $cartToken: String!
1637
+ $couponId: uuid!
1638
+ ) {
1639
+ websiteRemoveCoupon(
1640
+ order_id: $orderId
1641
+ cart_token: $cartToken
1642
+ coupon_id: $couponId
1643
+ ) {
1644
+ success
1645
+ order_id
1646
+ coupon_id
1647
+ code
1648
+ name
1649
+ coupon_type
1650
+ discount_amount
1651
+ eligible_subtotal
1652
+ message
1653
+ cart {
1654
+ id
1655
+ status
1656
+ discount
1657
+ total_without_tax
1658
+ tax
1659
+ total_with_tax
1660
+ total_with_discount
1661
+ created_at
1662
+ updated_at
1663
+ items {
1664
+ id
1665
+ product_variant_id
1666
+ quantity
1667
+ product_variant {
1668
+ id
1669
+ sku
1670
+ product {
1671
+ id
1672
+ name
1673
+ }
1674
+ prices {
1675
+ id
1676
+ price
1677
+ price_type
1678
+ chain_id
1679
+ }
1680
+ }
1681
+ }
1682
+ }
1683
+ errors
1684
+ }
1685
+ }
1686
+ `
1687
+ );
1688
+ var CREATE_PAYMENT_SESSION = (
1689
+ /* GraphQL */
1690
+ `
1691
+ mutation CreatePaymentSession(
1692
+ $orderId: uuid!
1693
+ $cartToken: String
1694
+ $publicOrderToken: String
1695
+ $paymentMethodId: uuid!
1696
+ $returnUrl: String!
1697
+ ) {
1698
+ websiteCreatePaymentSession(
1699
+ order_id: $orderId
1700
+ cart_token: $cartToken
1701
+ public_order_token: $publicOrderToken
1702
+ payment_method_id: $paymentMethodId
1703
+ return_url: $returnUrl
1704
+ ) {
1705
+ success
1706
+ order_id
1707
+ payment_method_id
1708
+ payment_session_id
1709
+ gateway_code
1710
+ integration_mode
1711
+ status
1712
+ redirect_url
1713
+ public_payload
1714
+ errors
1715
+ }
1716
+ }
1717
+ `
1718
+ );
1719
+ var RECONCILE_PAYMENT_SESSION = (
1720
+ /* GraphQL */
1721
+ `
1722
+ mutation ReconcilePaymentSession(
1723
+ $orderId: uuid!
1724
+ $publicOrderToken: String!
1725
+ $paymentSessionId: uuid!
1726
+ $gatewayTransactionId: String!
1727
+ ) {
1728
+ websiteReconcilePaymentSession(
1729
+ order_id: $orderId
1730
+ public_order_token: $publicOrderToken
1731
+ payment_session_id: $paymentSessionId
1732
+ gateway_transaction_id: $gatewayTransactionId
1733
+ ) {
1734
+ success
1735
+ order_id
1736
+ payment_method_id
1737
+ payment_session_id
1738
+ gateway_code
1739
+ integration_mode
1740
+ status
1741
+ redirect_url
1742
+ public_payload
1743
+ errors
1744
+ }
1745
+ }
1746
+ `
1747
+ );
1748
+ var GET_ORDERS = (
1749
+ /* GraphQL */
1750
+ `
1751
+ query GetOrders($limit: Int = 20, $offset: Int = 0) {
1752
+ orders(
1753
+ where: { order_number: { _is_null: false } }
1754
+ order_by: { created_at: desc }
1755
+ limit: $limit
1756
+ offset: $offset
1757
+ ) {
1758
+ id
1759
+ order_number
1760
+ status
1761
+ fulfillment_family
1762
+ discount
1763
+ tax
1764
+ total_without_tax
1765
+ total_with_tax
1766
+ total_with_discount
1767
+ created_at
1768
+ updated_at
1769
+ order_product_variants {
1770
+ id
1771
+ product_variant_id
1772
+ quantity
1773
+ product_variant {
1774
+ sku
1775
+ product {
1776
+ id
1777
+ name
1778
+ }
1779
+ }
1780
+ }
1781
+ }
1782
+ }
1783
+ `
1784
+ );
1785
+ var GET_ORDER_BY_PK = (
1786
+ /* GraphQL */
1787
+ `
1788
+ query GetOrderByPk($orderId: uuid!) {
1789
+ orders(where: { id: { _eq: $orderId } }) {
1790
+ id
1791
+ order_number
1792
+ status
1793
+ fulfillment_family
1794
+ discount
1795
+ tax
1796
+ total_without_tax
1797
+ total_with_tax
1798
+ total_with_discount
1799
+ created_at
1800
+ updated_at
1801
+ order_product_variants {
1802
+ id
1803
+ product_variant_id
1804
+ quantity
1805
+ product_variant {
1806
+ sku
1807
+ product {
1808
+ id
1809
+ name
1810
+ }
1811
+ }
1812
+ }
1813
+ }
1814
+ }
1815
+ `
1816
+ );
1817
+ var GET_PUBLIC_ORDER = (
1818
+ /* GraphQL */
1819
+ `
1820
+ mutation GetPublicOrder($websiteId: uuid!, $orderId: uuid!, $token: String!) {
1821
+ websiteGetPublicOrder(
1822
+ website_id: $websiteId
1823
+ order_id: $orderId
1824
+ token: $token
1825
+ ) {
1826
+ success
1827
+ order {
1828
+ order_id
1829
+ order_number
1830
+ status
1831
+ payment_status
1832
+ fulfillment_family
1833
+ delivery {
1834
+ fulfillment_family
1835
+ shipping {
1836
+ label
1837
+ amount
1838
+ method_type
1839
+ collection_mode
1840
+ total_policy
1841
+ address
1842
+ }
1843
+ pickup {
1844
+ label
1845
+ }
1846
+ }
1847
+ payment {
1848
+ mode
1849
+ label
1850
+ method {
1851
+ id
1852
+ label
1853
+ payment_method_type
1854
+ gateway_code
1855
+ requires_payment_session
1856
+ }
1857
+ initial_payment {
1858
+ amount
1859
+ payment_method_id
1860
+ method_label
1861
+ payment_method_type
1862
+ gateway_code
1863
+ requires_payment_session
1864
+ }
1865
+ requires_payment_session
1866
+ next_action
1867
+ session {
1868
+ id
1869
+ gateway_code
1870
+ integration_mode
1871
+ status
1872
+ reference
1873
+ amount
1874
+ currency
1875
+ gateway_transaction_id
1876
+ error_message
1877
+ expires_at
1878
+ created_at
1879
+ updated_at
1880
+ }
1881
+ }
1882
+ totals {
1883
+ subtotal
1884
+ tax
1885
+ discount
1886
+ total
1887
+ total_with_discount
1888
+ }
1889
+ items {
1890
+ id
1891
+ product_variant_id
1892
+ sku
1893
+ name
1894
+ image_file_id
1895
+ quantity
1896
+ unit_price
1897
+ line_total
1898
+ }
1899
+ next_steps
1900
+ created_at
1901
+ updated_at
1902
+ }
1903
+ errors
1904
+ }
1905
+ }
1906
+ `
1907
+ );
1908
+ var GET_PROFILE = (
1909
+ /* GraphQL */
1910
+ `
1911
+ query GetProfile {
1912
+ clients {
1913
+ id
1914
+ party_id
1915
+ party {
1916
+ first_name
1917
+ last_name
1918
+ email
1919
+ phone_e164
1920
+ phone_national_number
1921
+ address
1922
+ address_complement
1923
+ birthdate
1924
+ legal_name
1925
+ commercial_name
1926
+ country_code
1927
+ department_code
1928
+ municipality_code
1929
+ geo_country {
1930
+ name
1931
+ }
1932
+ geo_department {
1933
+ name
1934
+ }
1935
+ geo_municipality {
1936
+ name
1937
+ }
1938
+ shipping_addresses(
1939
+ where: { is_primary: { _eq: true } }
1940
+ order_by: { created_at: asc }
1941
+ limit: 1
1942
+ ) {
1943
+ address
1944
+ address_complement
1945
+ country_code
1946
+ department_code
1947
+ municipality_code
1948
+ geo_country {
1949
+ name
1950
+ }
1951
+ geo_department {
1952
+ name
1953
+ }
1954
+ geo_municipality {
1955
+ name
1956
+ }
1957
+ }
1958
+ }
1959
+ }
1960
+ }
1961
+ `
1962
+ );
1963
+ var GET_PROFILE_ADDRESSES = (
1964
+ /* GraphQL */
1965
+ `
1966
+ query GetProfileAddresses {
1967
+ clients {
1968
+ party_id
1969
+ party {
1970
+ first_name
1971
+ last_name
1972
+ display_name
1973
+ phone_e164
1974
+ phone_national_number
1975
+ address
1976
+ address_complement
1977
+ country_code
1978
+ department_code
1979
+ municipality_code
1980
+ geo_country {
1981
+ name
1982
+ }
1983
+ geo_department {
1984
+ name
1985
+ }
1986
+ geo_municipality {
1987
+ name
1988
+ }
1989
+ shipping_addresses(
1990
+ order_by: [{ is_primary: desc }, { created_at: asc }]
1991
+ ) {
1992
+ id
1993
+ label
1994
+ recipient_name
1995
+ phone_e164
1996
+ address
1997
+ address_complement
1998
+ notes
1999
+ is_primary
2000
+ country_code
2001
+ department_code
2002
+ municipality_code
2003
+ geo_country {
2004
+ name
2005
+ }
2006
+ geo_department {
2007
+ name
2008
+ }
2009
+ geo_municipality {
2010
+ name
2011
+ }
2012
+ }
2013
+ }
2014
+ }
2015
+ }
2016
+ `
2017
+ );
2018
+ var UPDATE_PROFILE = (
2019
+ /* GraphQL */
2020
+ `
2021
+ mutation UpdateProfile($partyId: uuid!, $data: business_parties_set_input!) {
2022
+ update_business_parties_by_pk(pk_columns: { id: $partyId }, _set: $data) {
2023
+ email
2024
+ first_name
2025
+ last_name
2026
+ phone_e164
2027
+ phone_national_number
2028
+ address
2029
+ address_complement
2030
+ birthdate
2031
+ legal_name
2032
+ commercial_name
2033
+ country_code
2034
+ department_code
2035
+ municipality_code
2036
+ geo_country {
2037
+ name
2038
+ }
2039
+ geo_department {
2040
+ name
2041
+ }
2042
+ geo_municipality {
2043
+ name
2044
+ }
2045
+ shipping_addresses(
2046
+ where: { is_primary: { _eq: true } }
2047
+ order_by: { created_at: asc }
2048
+ limit: 1
2049
+ ) {
2050
+ address
2051
+ address_complement
2052
+ country_code
2053
+ department_code
2054
+ municipality_code
2055
+ geo_country {
2056
+ name
2057
+ }
2058
+ geo_department {
2059
+ name
2060
+ }
2061
+ geo_municipality {
2062
+ name
2063
+ }
2064
+ }
2065
+ }
2066
+ }
2067
+ `
2068
+ );
2069
+ var GET_PRODUCT_FILTERS = (
2070
+ /* GraphQL */
2071
+ `
2072
+ query GetProductFilters(
2073
+ $companyId: uuid!
2074
+ $chainId: uuid!
2075
+ $where: products_bool_exp = {}
2076
+ $attributeListKey: String!
2077
+ ) {
2078
+ products(
2079
+ where: {
2080
+ _and: [
2081
+ { company_id: { _eq: $companyId } }
2082
+ {
2083
+ chain_products: {
2084
+ chain_id: { _eq: $chainId }
2085
+ is_enabled: { _eq: true }
2086
+ status: { _eq: active }
2087
+ }
2088
+ }
2089
+ $where
2090
+ ]
2091
+ }
2092
+ ) {
2093
+ id
2094
+ category
2095
+ subcategory
2096
+ color
2097
+ brand {
2098
+ id
2099
+ name
2100
+ }
2101
+ product_attributes {
2102
+ id
2103
+ value
2104
+ attribute_value {
2105
+ id
2106
+ code
2107
+ sort_order
2108
+ metadata
2109
+ }
2110
+ attribute {
2111
+ id
2112
+ name
2113
+ }
2114
+ }
2115
+ product_variants(where: { is_disabled: { _eq: false } }) {
2116
+ id
2117
+ product_variant_prices(
2118
+ where: {
2119
+ price_type: { _in: [CLIENT, SALE, WHOLESALE, WHOLESALE_2] }
2120
+ _or: [
2121
+ { chain_id: { _eq: $chainId } }
2122
+ { chain_id: { _is_null: true } }
2123
+ ]
2124
+ }
2125
+ ) {
2126
+ id
2127
+ price
2128
+ price_type
2129
+ chain_id
2130
+ }
2131
+ product_variant_attributes(order_by: { order: asc }) {
2132
+ id
2133
+ value
2134
+ order
2135
+ attribute_value {
2136
+ id
2137
+ code
2138
+ sort_order
2139
+ metadata
2140
+ }
2141
+ attribute {
2142
+ id
2143
+ name
2144
+ }
2145
+ }
2146
+ }
2147
+ }
2148
+ catalog_attribute_lists(
2149
+ where: {
2150
+ company_id: { _eq: $companyId }
2151
+ key: { _eq: $attributeListKey }
2152
+ status: { _eq: published }
2153
+ }
2154
+ limit: 1
2155
+ ) {
2156
+ id
2157
+ key
2158
+ name
2159
+ description
2160
+ status
2161
+ items(
2162
+ where: { is_visible: { _eq: true } }
2163
+ order_by: [{ sort_order: asc }, { public_label: asc }]
2164
+ ) {
2165
+ id
2166
+ attribute_id
2167
+ public_label
2168
+ public_slug
2169
+ sort_order
2170
+ attribute {
2171
+ id
2172
+ name
2173
+ type
2174
+ }
2175
+ values(
2176
+ where: { is_visible: { _eq: true } }
2177
+ order_by: [{ sort_order: asc }, { public_label: asc }]
2178
+ ) {
2179
+ id
2180
+ attribute_value_id
2181
+ public_label
2182
+ public_slug
2183
+ sort_order
2184
+ attribute_value {
2185
+ id
2186
+ code
2187
+ metadata
2188
+ }
2189
+ }
2190
+ }
2191
+ }
2192
+ }
2193
+ `
2194
+ );
2195
+ var GET_SEARCH_SUGGESTIONS = (
2196
+ /* GraphQL */
2197
+ `
2198
+ query GetSearchSuggestions(
2199
+ $companyId: uuid!
2200
+ $chainId: uuid!
2201
+ $term: String!
2202
+ $productLimit: Int = 5
2203
+ $brandLimit: Int = 3
2204
+ ) {
2205
+ products(
2206
+ where: {
2207
+ company_id: { _eq: $companyId }
2208
+ chain_products: {
2209
+ chain_id: { _eq: $chainId }
2210
+ is_enabled: { _eq: true }
2211
+ status: { _eq: active }
2212
+ }
2213
+ name: { _ilike: $term }
2214
+ }
2215
+ limit: $productLimit
2216
+ order_by: { name: asc }
2217
+ ) {
2218
+ id
2219
+ name
2220
+ }
2221
+ brands(
2222
+ where: {
2223
+ company_id: { _eq: $companyId }
2224
+ name: { _ilike: $term }
2225
+ products: {
2226
+ chain_products: {
2227
+ chain_id: { _eq: $chainId }
2228
+ is_enabled: { _eq: true }
2229
+ status: { _eq: active }
2230
+ }
2231
+ }
2232
+ }
2233
+ limit: $brandLimit
2234
+ order_by: { name: asc }
2235
+ ) {
2236
+ id
2237
+ name
2238
+ }
2239
+ }
2240
+ `
2241
+ );
2242
+
2243
+ // libs/sdk/src/modules/availability.ts
2244
+ var MAX_AVAILABILITY_VARIANT_IDS = 100;
2245
+ function mapAvailability(raw) {
2246
+ return {
2247
+ productVariantId: raw.product_variant_id,
2248
+ inStock: raw.in_stock,
2249
+ label: raw.label
2250
+ };
2251
+ }
2252
+ function chunkArray(items, chunkSize) {
2253
+ const chunks = [];
2254
+ for (let index = 0; index < items.length; index += chunkSize) {
2255
+ chunks.push(items.slice(index, index + chunkSize));
2256
+ }
2257
+ return chunks;
2258
+ }
2259
+ function uniqueValues(values) {
2260
+ return Array.from(new Set(values));
2261
+ }
2262
+ function createAvailabilityModule(graphqlUrl, getHeaders, getContext) {
2263
+ return {
2264
+ async checkAvailability(productVariantIds) {
2265
+ const ctx = getContext();
2266
+ if (!ctx.chainId) {
2267
+ throw new WebsiteError(
2268
+ "This website has no chain configured. Stock availability requires a chain_id.",
2269
+ "NO_CHAIN"
2270
+ );
2271
+ }
2272
+ if (productVariantIds.length === 0) return [];
2273
+ const variantIds = uniqueValues(productVariantIds);
2274
+ const results = [];
2275
+ for (const chunk of chunkArray(variantIds, MAX_AVAILABILITY_VARIANT_IDS)) {
2276
+ const data = await executeGraphQL(
2277
+ graphqlUrl,
2278
+ CHECK_AVAILABILITY,
2279
+ {
2280
+ variantIds: chunk,
2281
+ chainId: ctx.chainId
2282
+ },
2283
+ getHeaders
2284
+ );
2285
+ results.push(
2286
+ ...(data.websiteProductAvailability ?? []).map(mapAvailability)
2287
+ );
2288
+ }
2289
+ return results;
2290
+ }
2291
+ };
2292
+ }
2293
+
2294
+ // libs/sdk/src/modules/cart.ts
2295
+ function mapCartItem(raw) {
2296
+ return {
2297
+ id: raw.id,
2298
+ productVariantId: raw.product_variant_id,
2299
+ quantity: raw.quantity,
2300
+ productVariant: {
2301
+ sku: raw.product_variant.sku,
2302
+ product: raw.product_variant.product,
2303
+ prices: raw.product_variant.prices.map((p) => ({
2304
+ id: p.id,
2305
+ price: p.price,
2306
+ priceType: p.price_type,
2307
+ chainId: p.chain_id
2308
+ }))
2309
+ }
2310
+ };
2311
+ }
2312
+ function mapCart(raw, cartToken) {
2313
+ return {
2314
+ id: raw.id,
2315
+ cartToken,
2316
+ items: raw.items.map(mapCartItem),
2317
+ totals: {
2318
+ subtotal: raw.total_without_tax,
2319
+ tax: raw.tax,
2320
+ discount: raw.discount,
2321
+ total: raw.total_with_tax
2322
+ },
2323
+ status: raw.status,
2324
+ createdAt: raw.created_at,
2325
+ updatedAt: raw.updated_at
2326
+ };
2327
+ }
2328
+ function assertActionSuccess(result, fallbackCode) {
2329
+ if (!result.success || !result.order_id || !result.cart_token || !result.cart) {
2330
+ const message = result.errors?.join("; ") || "Cart action failed";
2331
+ throw new WebsiteError(message, fallbackCode);
2332
+ }
2333
+ }
2334
+ function requireCartSession(storage) {
2335
+ const session = storage.get();
2336
+ if (!session) {
2337
+ throw new WebsiteError(
2338
+ "No guest cart session found",
2339
+ "CART_SESSION_MISSING"
2340
+ );
2341
+ }
2342
+ return session;
2343
+ }
2344
+ function createCartModule(graphqlUrl, getHeaders, getContext, cartSessionStorage) {
2345
+ async function fetchCart(orderId, cartToken) {
2346
+ const data = await executeGraphQL(graphqlUrl, GET_CART, { orderId, cartToken }, getHeaders);
2347
+ const result = data.websiteGetCart;
2348
+ if (!result.success) {
2349
+ if (result.errors?.includes("CART_NOT_FOUND")) {
2350
+ cartSessionStorage.clear();
2351
+ return null;
2352
+ }
2353
+ throw new WebsiteError(
2354
+ result.errors?.join("; ") || "Cart could not be retrieved",
2355
+ "CART_FETCH_ERROR"
2356
+ );
2357
+ }
2358
+ assertActionSuccess(result, "CART_FETCH_ERROR");
2359
+ cartSessionStorage.set({
2360
+ orderId: result.order_id,
2361
+ cartToken: result.cart_token
2362
+ });
2363
+ return mapCart(result.cart, result.cart_token);
2364
+ }
2365
+ return {
2366
+ async getOrCreate(contact, fulfillmentFamily) {
2367
+ const ctx = getContext();
2368
+ if (!ctx.chainId) {
2369
+ throw new WebsiteError(
2370
+ "This website has no chain configured. Cart requires a chain_id.",
2371
+ "NO_CHAIN"
2372
+ );
2373
+ }
2374
+ const existing = cartSessionStorage.get();
2375
+ const data = await executeGraphQL(
2376
+ graphqlUrl,
2377
+ CREATE_CART,
2378
+ {
2379
+ websiteId: ctx.websiteId,
2380
+ cartToken: existing?.cartToken,
2381
+ contact,
2382
+ fulfillmentFamily
2383
+ },
2384
+ getHeaders
2385
+ );
2386
+ const result = data.websiteCreateCart;
2387
+ assertActionSuccess(result, "CART_CREATE_ERROR");
2388
+ cartSessionStorage.set({
2389
+ orderId: result.order_id,
2390
+ cartToken: result.cart_token
2391
+ });
2392
+ return mapCart(result.cart, result.cart_token);
2393
+ },
2394
+ async startCheckout(input) {
2395
+ const ctx = getContext();
2396
+ if (!ctx.chainId) {
2397
+ throw new WebsiteError(
2398
+ "This website has no chain configured. Checkout requires a chain_id.",
2399
+ "NO_CHAIN"
2400
+ );
2401
+ }
2402
+ const existing = cartSessionStorage.get();
2403
+ const data = await executeGraphQL(
2404
+ graphqlUrl,
2405
+ START_GUEST_CHECKOUT,
2406
+ {
2407
+ websiteId: ctx.websiteId,
2408
+ cartToken: existing?.cartToken,
2409
+ contact: input.contact,
2410
+ fulfillmentFamily: input.fulfillmentFamily,
2411
+ items: input.items.map((item) => ({
2412
+ product_variant_id: item.productVariantId,
2413
+ quantity: item.quantity
2414
+ }))
2415
+ },
2416
+ getHeaders
2417
+ );
2418
+ const result = data.websiteStartGuestCheckout;
2419
+ assertActionSuccess(result, "CHECKOUT_START_ERROR");
2420
+ cartSessionStorage.set({
2421
+ orderId: result.order_id,
2422
+ cartToken: result.cart_token
2423
+ });
2424
+ return mapCart(result.cart, result.cart_token);
2425
+ },
2426
+ async get() {
2427
+ const session = cartSessionStorage.get();
2428
+ if (!session) return null;
2429
+ return fetchCart(session.orderId, session.cartToken);
2430
+ },
2431
+ async setItem(productVariantId, quantity) {
2432
+ if (quantity <= 0) {
2433
+ throw new WebsiteError(
2434
+ "Quantity must be greater than zero",
2435
+ "INVALID_QUANTITY"
2436
+ );
2437
+ }
2438
+ const session = cartSessionStorage.get();
2439
+ if (!session) {
2440
+ throw new WebsiteError(
2441
+ "Start checkout with contact before syncing cart items to Bacano",
2442
+ "CART_SESSION_MISSING"
2443
+ );
2444
+ }
2445
+ const data = await executeGraphQL(
2446
+ graphqlUrl,
2447
+ SET_CART_ITEM,
2448
+ {
2449
+ orderId: session.orderId,
2450
+ cartToken: session.cartToken,
2451
+ variantId: productVariantId,
2452
+ quantity
2453
+ },
2454
+ getHeaders
2455
+ );
2456
+ const result = data.websiteSetCartItem;
2457
+ assertActionSuccess(result, "CART_ITEM_ERROR");
2458
+ cartSessionStorage.set({
2459
+ orderId: result.order_id,
2460
+ cartToken: result.cart_token
2461
+ });
2462
+ return mapCart(result.cart, result.cart_token);
2463
+ },
2464
+ async addItem(productVariantId, quantity) {
2465
+ const cart = await this.setItem(productVariantId, quantity);
2466
+ const item = cart.items.find(
2467
+ (entry) => entry.productVariantId === productVariantId
2468
+ );
2469
+ if (!item) {
2470
+ throw new WebsiteError(
2471
+ "Cart item was not returned by the server",
2472
+ "CART_ITEM_ERROR"
2473
+ );
2474
+ }
2475
+ return item;
2476
+ },
2477
+ async updateItem(cartItemId, quantity) {
2478
+ const cart = await this.get();
2479
+ const item = cart?.items.find((entry) => entry.id === cartItemId);
2480
+ if (!item) {
2481
+ throw new WebsiteError(
2482
+ "Cart item was not found",
2483
+ "CART_ITEM_NOT_FOUND"
2484
+ );
2485
+ }
2486
+ const updatedCart = await this.setItem(item.productVariantId, quantity);
2487
+ const updatedItem = updatedCart.items.find(
2488
+ (entry) => entry.id === cartItemId
2489
+ );
2490
+ return {
2491
+ id: cartItemId,
2492
+ quantity: updatedItem?.quantity ?? quantity
2493
+ };
2494
+ },
2495
+ async removeItem(cartItemId) {
2496
+ const session = requireCartSession(cartSessionStorage);
2497
+ const data = await executeGraphQL(
2498
+ graphqlUrl,
2499
+ REMOVE_CART_ITEM,
2500
+ {
2501
+ orderId: session.orderId,
2502
+ cartToken: session.cartToken,
2503
+ itemId: cartItemId
2504
+ },
2505
+ getHeaders
2506
+ );
2507
+ const result = data.websiteRemoveCartItem;
2508
+ assertActionSuccess(result, "CART_ITEM_ERROR");
2509
+ cartSessionStorage.set({
2510
+ orderId: result.order_id,
2511
+ cartToken: result.cart_token
2512
+ });
2513
+ return mapCart(result.cart, result.cart_token);
2514
+ }
2515
+ };
2516
+ }
2517
+
2518
+ // libs/sdk/src/modules/cart-session.ts
2519
+ function getStorageKey(slug) {
2520
+ return `@bacano/sdk:cart:${slug}`;
2521
+ }
2522
+ function createCartSessionStorage(kind, getSlug) {
2523
+ let memorySession = null;
2524
+ function readKey() {
2525
+ return getStorageKey(getSlug());
2526
+ }
2527
+ return {
2528
+ get() {
2529
+ if (kind === "memory") return memorySession;
2530
+ if (kind === "cookie") {
2531
+ if (typeof document === "undefined") return null;
2532
+ try {
2533
+ const key = readKey();
2534
+ const match = document.cookie.split("; ").find((row) => row.startsWith(`${key}=`));
2535
+ if (!match) return null;
2536
+ return JSON.parse(decodeURIComponent(match.split("=").slice(1).join("=")));
2537
+ } catch {
2538
+ return null;
2539
+ }
2540
+ }
2541
+ if (typeof localStorage === "undefined") return null;
2542
+ try {
2543
+ const raw = localStorage.getItem(readKey());
2544
+ return raw ? JSON.parse(raw) : null;
2545
+ } catch {
2546
+ return null;
2547
+ }
2548
+ },
2549
+ set(session) {
2550
+ memorySession = session;
2551
+ if (kind === "memory") return;
2552
+ if (kind === "cookie") {
2553
+ if (typeof document === "undefined") return;
2554
+ const maxAge = 30 * 24 * 60 * 60;
2555
+ const value = encodeURIComponent(JSON.stringify(session));
2556
+ document.cookie = `${readKey()}=${value}; max-age=${maxAge}; path=/; SameSite=Lax`;
2557
+ return;
2558
+ }
2559
+ if (typeof localStorage === "undefined") return;
2560
+ localStorage.setItem(readKey(), JSON.stringify(session));
2561
+ },
2562
+ clear() {
2563
+ memorySession = null;
2564
+ if (kind === "memory") return;
2565
+ if (kind === "cookie") {
2566
+ if (typeof document === "undefined") return;
2567
+ document.cookie = `${readKey()}=; max-age=0; path=/; SameSite=Lax`;
2568
+ return;
2569
+ }
2570
+ if (typeof localStorage === "undefined") return;
2571
+ localStorage.removeItem(readKey());
2572
+ }
2573
+ };
2574
+ }
2575
+
2576
+ // libs/sdk/src/media.ts
2577
+ var MEDIA_VARIANTS = {
2578
+ thumbnail: { width: 240, quality: 75, format: "webp" },
2579
+ card: { width: 640, quality: 80, format: "webp" },
2580
+ detail: { width: 1400, quality: 85, format: "webp" }
2581
+ };
2582
+ function toSafeInteger(value) {
2583
+ if (!Number.isFinite(value)) return void 0;
2584
+ return Math.max(1, Math.floor(value));
2585
+ }
2586
+ function buildQuery(options) {
2587
+ const params = new URLSearchParams();
2588
+ const width = toSafeInteger(options.width);
2589
+ const height = toSafeInteger(options.height);
2590
+ const quality = toSafeInteger(options.quality);
2591
+ if (width) params.set("w", String(width));
2592
+ if (height) params.set("h", String(height));
2593
+ if (quality) params.set("q", String(Math.min(100, quality)));
2594
+ if (options.format) params.set("f", options.format);
2595
+ const query = params.toString();
2596
+ return query ? `?${query}` : "";
2597
+ }
2598
+ function buildStorageFileUrl(storageUrl, fileId, variant = "original") {
2599
+ if (!storageUrl || !fileId) return "";
2600
+ const baseUrl = `${storageUrl.replace(/\/+$/, "")}/files/${fileId}`;
2601
+ if (variant === "original") return baseUrl;
2602
+ return `${baseUrl}${buildQuery(MEDIA_VARIANTS[variant])}`;
2603
+ }
2604
+ function buildStorageMediaUrls(storageUrl, fileId) {
2605
+ return {
2606
+ originalUrl: buildStorageFileUrl(storageUrl, fileId, "original"),
2607
+ thumbnailUrl: buildStorageFileUrl(storageUrl, fileId, "thumbnail"),
2608
+ cardUrl: buildStorageFileUrl(storageUrl, fileId, "card"),
2609
+ detailUrl: buildStorageFileUrl(storageUrl, fileId, "detail")
2610
+ };
2611
+ }
2612
+
2613
+ // libs/sdk/src/modules/catalog.ts
2614
+ var MAX_AVAILABILITY_VARIANT_IDS2 = 100;
2615
+ var DEFAULT_FILTER_ATTRIBUTE_LIST_KEY = "atributos";
2616
+ function mapPrice(raw) {
2617
+ return {
2618
+ id: raw.id,
2619
+ price: raw.price,
2620
+ priceType: raw.price_type,
2621
+ chainId: raw.chain_id
2622
+ };
2623
+ }
2624
+ function parseActionJson(value, fallback) {
2625
+ if (value == null) return fallback;
2626
+ if (typeof value !== "string") return value;
2627
+ try {
2628
+ return JSON.parse(value);
2629
+ } catch {
2630
+ return fallback;
2631
+ }
2632
+ }
2633
+ function getProductMediaKind(mimeType) {
2634
+ if (mimeType?.startsWith("image/")) return "image";
2635
+ if (mimeType?.startsWith("video/")) return "video";
2636
+ if (mimeType?.startsWith("application/")) return "document";
2637
+ return "file";
2638
+ }
2639
+ function getProductMediaByKind(media, kind) {
2640
+ return (media ?? []).filter((item) => item.mediaKind === kind);
2641
+ }
2642
+ function getProductImages(media) {
2643
+ return getProductMediaByKind(media, "image");
2644
+ }
2645
+ function getProductVideos(media) {
2646
+ return getProductMediaByKind(media, "video");
2647
+ }
2648
+ function getPrimaryProductImage(media) {
2649
+ return getProductImages(media)[0] ?? null;
2650
+ }
2651
+ function mapMedia(raw, storageUrl) {
2652
+ const mimeType = raw.file?.mimeType ?? null;
2653
+ const fileName = raw.file?.name ?? null;
2654
+ const urls = buildStorageMediaUrls(storageUrl, raw.file_id);
2655
+ return {
2656
+ id: raw.id,
2657
+ fileId: raw.file_id,
2658
+ order: raw.order ?? 0,
2659
+ url: urls.originalUrl,
2660
+ ...urls,
2661
+ mediaKind: getProductMediaKind(mimeType),
2662
+ mimeType,
2663
+ fileName,
2664
+ alt: fileName
2665
+ };
2666
+ }
2667
+ function mapProductRecommendation(raw, storageUrl) {
2668
+ return {
2669
+ id: raw.id,
2670
+ name: raw.name,
2671
+ slug: raw.slug,
2672
+ category: raw.category,
2673
+ subcategory: raw.subcategory,
2674
+ brand: raw.brand,
2675
+ primaryImage: raw.primary_media ? mapMedia(raw.primary_media, storageUrl) : null,
2676
+ pricing: {
2677
+ currentPriceMin: Number(raw.pricing.current_price_min),
2678
+ currentPriceMax: Number(raw.pricing.current_price_max),
2679
+ regularPriceMin: Number(raw.pricing.regular_price_min),
2680
+ regularPriceMax: Number(raw.pricing.regular_price_max),
2681
+ hasDiscount: raw.pricing.has_discount
2682
+ },
2683
+ source: raw.recommendation_source
2684
+ };
2685
+ }
2686
+ function mapSeoMedia(raw, storageUrl) {
2687
+ if (!raw.seo_image_file_id) return null;
2688
+ return mapMedia(
2689
+ {
2690
+ id: `seo:${raw.seo_image_file_id}`,
2691
+ file_id: raw.seo_image_file_id,
2692
+ order: 0,
2693
+ file: raw.seo_image_file ?? null
2694
+ },
2695
+ storageUrl
2696
+ );
2697
+ }
2698
+ function attributeValueCode(raw) {
2699
+ return raw.attribute_value?.code ?? raw.value;
2700
+ }
2701
+ function attributeValueLabelKey(attributeId, valueCode) {
2702
+ return `${attributeId}:${valueCode}`;
2703
+ }
2704
+ function buildPublicAttributeLabels(lists) {
2705
+ const attributeLabelsById = /* @__PURE__ */ new Map();
2706
+ const valueLabelsById = /* @__PURE__ */ new Map();
2707
+ const valueLabelsByAttributeAndCode = /* @__PURE__ */ new Map();
2708
+ for (const list of lists ?? []) {
2709
+ for (const item of list.items ?? []) {
2710
+ if (!attributeLabelsById.has(item.attribute_id)) {
2711
+ attributeLabelsById.set(item.attribute_id, item.public_label);
2712
+ }
2713
+ for (const value of item.values ?? []) {
2714
+ if (!valueLabelsById.has(value.attribute_value_id)) {
2715
+ valueLabelsById.set(value.attribute_value_id, value.public_label);
2716
+ }
2717
+ const valueCode = value.attribute_value.code;
2718
+ const key = attributeValueLabelKey(item.attribute_id, valueCode);
2719
+ if (!valueLabelsByAttributeAndCode.has(key)) {
2720
+ valueLabelsByAttributeAndCode.set(key, value.public_label);
2721
+ }
2722
+ }
2723
+ }
2724
+ }
2725
+ return {
2726
+ attributeLabelsById,
2727
+ valueLabelsById,
2728
+ valueLabelsByAttributeAndCode
2729
+ };
2730
+ }
2731
+ function resolvePublicAttributeValueLabel(raw, labels) {
2732
+ const valueCode = attributeValueCode(raw);
2733
+ if (raw.attribute_value?.public_label) {
2734
+ return raw.attribute_value.public_label;
2735
+ }
2736
+ const byId = raw.attribute_value?.id ? labels.valueLabelsById.get(raw.attribute_value.id) : null;
2737
+ const byAttributeAndCode = labels.valueLabelsByAttributeAndCode.get(
2738
+ attributeValueLabelKey(raw.attribute.id, valueCode)
2739
+ );
2740
+ return byId ?? byAttributeAndCode ?? valueCode;
2741
+ }
2742
+ function mapProductAttribute(raw, labels) {
2743
+ const valueCode = attributeValueCode(raw);
2744
+ return {
2745
+ id: raw.id,
2746
+ name: raw.attribute.public_label ?? labels.attributeLabelsById.get(raw.attribute.id) ?? raw.attribute.name,
2747
+ value: resolvePublicAttributeValueLabel(raw, labels),
2748
+ attributeValueId: raw.attribute_value?.id ?? null,
2749
+ code: raw.attribute.name,
2750
+ valueCode,
2751
+ metadata: raw.attribute_value?.metadata ?? null,
2752
+ sortOrder: raw.attribute_value?.sort_order ?? null
2753
+ };
2754
+ }
2755
+ function mapVariantAttribute(raw, labels) {
2756
+ const valueCode = attributeValueCode(raw);
2757
+ return {
2758
+ id: raw.id,
2759
+ name: raw.attribute.public_label ?? labels.attributeLabelsById.get(raw.attribute.id) ?? raw.attribute.name,
2760
+ value: resolvePublicAttributeValueLabel(raw, labels),
2761
+ order: raw.order,
2762
+ attributeValueId: raw.attribute_value?.id ?? null,
2763
+ code: raw.attribute.name,
2764
+ valueCode,
2765
+ metadata: raw.attribute_value?.metadata ?? null,
2766
+ sortOrder: raw.attribute_value?.sort_order ?? null
2767
+ };
2768
+ }
2769
+ function mapVariant(raw, labels, chainId) {
2770
+ const prices = selectPublicPrices(
2771
+ raw.product_variant_prices.map(mapPrice),
2772
+ chainId
2773
+ );
2774
+ return {
2775
+ id: raw.id,
2776
+ sku: raw.sku,
2777
+ barcode: raw.barcode,
2778
+ order: raw.order,
2779
+ weight: raw.weight,
2780
+ depth: raw.depth,
2781
+ height: raw.height,
2782
+ length: raw.length,
2783
+ prices,
2784
+ pricing: resolveProductPricing(prices),
2785
+ attributes: raw.product_variant_attributes.map(
2786
+ (attribute) => mapVariantAttribute(attribute, labels)
2787
+ )
2788
+ };
2789
+ }
2790
+ function mapRelatedProduct(raw, storageUrl) {
2791
+ return {
2792
+ id: raw.id,
2793
+ productId: raw.related_product_id,
2794
+ slug: raw.related_product.slug,
2795
+ name: raw.related_product.name,
2796
+ sku: raw.related_product.sku,
2797
+ displayLabel: raw.display_label,
2798
+ sortOrder: raw.sort_order ?? 0,
2799
+ media: raw.related_product.product_media.map(
2800
+ (m) => mapMedia(m, storageUrl)
2801
+ )
2802
+ };
2803
+ }
2804
+ function mapProduct(raw, storageUrl, labels, chainId) {
2805
+ return {
2806
+ id: raw.id,
2807
+ name: raw.name,
2808
+ description: raw.description,
2809
+ longDescription: raw.long_description ?? null,
2810
+ slug: raw.slug ?? null,
2811
+ seoTitle: raw.seo_title ?? null,
2812
+ seoDescription: raw.seo_description ?? null,
2813
+ seoImage: mapSeoMedia(raw, storageUrl),
2814
+ color: raw.color,
2815
+ category: raw.category,
2816
+ subcategory: raw.subcategory,
2817
+ brand: raw.brand,
2818
+ measurementUnit: raw.measurement_unit,
2819
+ createdAt: raw.created_at,
2820
+ updatedAt: raw.updated_at ?? raw.created_at,
2821
+ variants: raw.product_variants.map(
2822
+ (variant) => mapVariant(variant, labels, chainId)
2823
+ ),
2824
+ media: raw.product_media.map((m) => mapMedia(m, storageUrl)),
2825
+ attributes: raw.product_attributes.map(
2826
+ (attribute) => mapProductAttribute(attribute, labels)
2827
+ ),
2828
+ relatedProducts: (raw.product_related_products ?? []).map(
2829
+ (relation) => mapRelatedProduct(relation, storageUrl)
2830
+ )
2831
+ };
2832
+ }
2833
+ function mapCategory(raw) {
2834
+ return {
2835
+ name: raw.name,
2836
+ description: raw.description,
2837
+ subcategories: raw.product_subcategories.map((sub) => ({
2838
+ id: sub.id,
2839
+ name: sub.name,
2840
+ description: sub.description
2841
+ }))
2842
+ };
2843
+ }
2844
+ function mapCategoryListItem(raw, categoriesByName) {
2845
+ const parentCategory = raw.subcategory_ref?.category ?? null;
2846
+ const parent = parentCategory ? categoriesByName?.get(parentCategory) ?? null : null;
2847
+ return {
2848
+ id: raw.id,
2849
+ sourceType: raw.source_type,
2850
+ productCategory: raw.product_category,
2851
+ productSubcategoryId: raw.product_subcategory_id,
2852
+ label: raw.public_label,
2853
+ slug: raw.public_slug,
2854
+ sortOrder: raw.sort_order,
2855
+ category: raw.category_ref,
2856
+ subcategory: raw.subcategory_ref,
2857
+ parentCategory,
2858
+ parentId: parent?.id ?? null,
2859
+ parentSlug: parent?.slug ?? null
2860
+ };
2861
+ }
2862
+ function mapCategoryList(raw) {
2863
+ const categoryItems = raw.items.filter((item) => item.source_type === "category" && item.product_category).map((item) => mapCategoryListItem(item));
2864
+ const categoriesByName = new Map(
2865
+ categoryItems.filter((item) => item.productCategory).map((item) => [item.productCategory, item])
2866
+ );
2867
+ const items = raw.items.map(
2868
+ (item) => mapCategoryListItem(item, categoriesByName)
2869
+ );
2870
+ return {
2871
+ id: raw.id,
2872
+ key: raw.key,
2873
+ name: raw.name,
2874
+ description: raw.description,
2875
+ status: raw.status,
2876
+ items,
2877
+ categories: categoryItems.map((category) => ({
2878
+ id: category.id,
2879
+ productCategory: category.productCategory,
2880
+ label: category.label,
2881
+ slug: category.slug,
2882
+ sortOrder: category.sortOrder,
2883
+ category: category.category,
2884
+ subcategories: items.filter(
2885
+ (item) => item.sourceType === "subcategory" && item.parentCategory === category.productCategory
2886
+ ).sort(
2887
+ (a, b) => a.sortOrder === b.sortOrder ? a.label.localeCompare(b.label) : a.sortOrder - b.sortOrder
2888
+ )
2889
+ }))
2890
+ };
2891
+ }
2892
+ function filterCategoryListByApplicability(raw, applicableCategories, applicableSubcategoryIds) {
2893
+ const categoryNamesWithApplicableSubcategories = new Set(
2894
+ raw.items.filter(
2895
+ (item) => item.source_type === "subcategory" && item.product_subcategory_id && applicableSubcategoryIds.has(item.product_subcategory_id)
2896
+ ).map((item) => item.subcategory_ref?.category).filter((category) => Boolean(category))
2897
+ );
2898
+ const filteredItems = raw.items.filter((item) => {
2899
+ if (item.source_type === "category") {
2900
+ const category = item.product_category;
2901
+ return Boolean(
2902
+ category && (applicableCategories.has(category) || categoryNamesWithApplicableSubcategories.has(category))
2903
+ );
2904
+ }
2905
+ const subcategoryId = item.product_subcategory_id;
2906
+ return Boolean(
2907
+ subcategoryId && applicableSubcategoryIds.has(subcategoryId)
2908
+ );
2909
+ });
2910
+ return mapCategoryList({
2911
+ ...raw,
2912
+ items: filteredItems
2913
+ });
2914
+ }
2915
+ function mapAttributeListValue(raw) {
2916
+ return {
2917
+ id: raw.id,
2918
+ attributeValueId: raw.attribute_value_id,
2919
+ code: raw.attribute_value.code,
2920
+ label: raw.public_label,
2921
+ slug: raw.public_slug,
2922
+ sortOrder: raw.sort_order,
2923
+ metadata: raw.attribute_value.metadata
2924
+ };
2925
+ }
2926
+ function mapAttributeListItem(raw) {
2927
+ return {
2928
+ id: raw.id,
2929
+ attributeId: raw.attribute_id,
2930
+ attributeName: raw.attribute.name,
2931
+ attributeType: raw.attribute.type,
2932
+ label: raw.public_label,
2933
+ slug: raw.public_slug,
2934
+ sortOrder: raw.sort_order,
2935
+ values: raw.values.map(mapAttributeListValue)
2936
+ };
2937
+ }
2938
+ function mapAttributeList(raw) {
2939
+ return {
2940
+ id: raw.id,
2941
+ key: raw.key,
2942
+ name: raw.name,
2943
+ description: raw.description,
2944
+ status: raw.status,
2945
+ items: raw.items.map(mapAttributeListItem)
2946
+ };
2947
+ }
2948
+ function mapContextualAttributeListValue(raw) {
2949
+ return {
2950
+ id: raw.id,
2951
+ attributeValueId: raw.attribute_value_id,
2952
+ code: raw.code,
2953
+ label: raw.public_label,
2954
+ slug: raw.public_slug,
2955
+ sortOrder: raw.sort_order,
2956
+ metadata: raw.metadata
2957
+ };
2958
+ }
2959
+ function mapContextualAttributeListItem(raw) {
2960
+ return {
2961
+ id: raw.id,
2962
+ attributeId: raw.attribute_id,
2963
+ attributeName: raw.attribute_name,
2964
+ attributeType: raw.attribute_type,
2965
+ label: raw.public_label,
2966
+ slug: raw.public_slug,
2967
+ sortOrder: raw.sort_order,
2968
+ values: raw.values.map(mapContextualAttributeListValue)
2969
+ };
2970
+ }
2971
+ function mapContextualAttributeList(raw) {
2972
+ return {
2973
+ id: raw.id,
2974
+ key: raw.key,
2975
+ name: raw.name,
2976
+ description: raw.description,
2977
+ status: raw.status,
2978
+ items: raw.items.map(mapContextualAttributeListItem)
2979
+ };
2980
+ }
2981
+ function buildOrderBy(sortBy) {
2982
+ switch (sortBy) {
2983
+ case "name_asc":
2984
+ return [{ name: "asc" }];
2985
+ case "name_desc":
2986
+ return [{ name: "desc" }];
2987
+ case "newest":
2988
+ return [{ created_at: "desc" }];
2989
+ case "price_asc":
2990
+ case "price_desc":
2991
+ return void 0;
2992
+ // Client-side sort after fetch
2993
+ default:
2994
+ return void 0;
2995
+ }
2996
+ }
2997
+ function scoreSearchRelevance(product, search) {
2998
+ const term = search.toLowerCase();
2999
+ const name = product.name.toLowerCase();
3000
+ if (name.startsWith(term)) return 100;
3001
+ if (name.includes(term)) return 80;
3002
+ if (product.brand?.name.toLowerCase().includes(term)) return 60;
3003
+ if (product.attributes.some((a) => a.value.toLowerCase().includes(term)))
3004
+ return 40;
3005
+ if (product.description?.toLowerCase().includes(term)) return 20;
3006
+ return 0;
3007
+ }
3008
+ function getMinVariantPrice(product) {
3009
+ let min = Infinity;
3010
+ for (const v of product.variants) {
3011
+ if (v.pricing.currentPrice != null && v.pricing.currentPrice < min) {
3012
+ min = v.pricing.currentPrice;
3013
+ }
3014
+ }
3015
+ return min === Infinity ? 0 : min;
3016
+ }
3017
+ function resolveProductPricing(prices) {
3018
+ const positivePrice = (priceType) => {
3019
+ const price = prices.find((item) => item.priceType === priceType)?.price;
3020
+ return price != null && Number.isFinite(price) && price > 0 ? price : null;
3021
+ };
3022
+ const regularPrice = positivePrice("CLIENT");
3023
+ const candidateSalePrice = positivePrice("SALE");
3024
+ const salePrice = regularPrice != null && candidateSalePrice != null && candidateSalePrice < regularPrice ? candidateSalePrice : null;
3025
+ const hasDiscount = salePrice != null;
3026
+ const discountPercentage = salePrice != null && regularPrice != null ? Math.round((regularPrice - salePrice) / regularPrice * 1e4) / 100 : null;
3027
+ return {
3028
+ currentPrice: salePrice ?? regularPrice,
3029
+ regularPrice,
3030
+ salePrice,
3031
+ hasDiscount,
3032
+ discountPercentage,
3033
+ wholesalePrice: positivePrice("WHOLESALE"),
3034
+ wholesale2Price: positivePrice("WHOLESALE_2")
3035
+ };
3036
+ }
3037
+ function selectPublicPrices(prices, chainId) {
3038
+ const selected = [];
3039
+ for (const priceType of [
3040
+ "SALE",
3041
+ "CLIENT",
3042
+ "WHOLESALE",
3043
+ "WHOLESALE_2"
3044
+ ]) {
3045
+ const chainPrice = prices.find(
3046
+ (price2) => price2.priceType === priceType && price2.chainId === chainId
3047
+ );
3048
+ const globalPrice = prices.find(
3049
+ (price2) => price2.priceType === priceType && price2.chainId === null
3050
+ );
3051
+ const price = chainPrice ?? globalPrice;
3052
+ if (price) selected.push(price);
3053
+ }
3054
+ return selected;
3055
+ }
3056
+ function hasMeaningfulAttributeListFilters(filters) {
3057
+ if (!filters) return false;
3058
+ return Boolean(
3059
+ filters.categoryName || filters.subcategoryId || filters.brandId || filters.search || filters.minPrice !== void 0 || filters.maxPrice !== void 0 || (filters.tags?.some((tag) => tag.trim().length > 0) ?? false)
3060
+ );
3061
+ }
3062
+ function chunkArray2(items, chunkSize) {
3063
+ const chunks = [];
3064
+ for (let index = 0; index < items.length; index += chunkSize) {
3065
+ chunks.push(items.slice(index, index + chunkSize));
3066
+ }
3067
+ return chunks;
3068
+ }
3069
+ function uniqueValues2(values) {
3070
+ return Array.from(new Set(values));
3071
+ }
3072
+ function buildProductWhere(filters, chainId) {
3073
+ const whereConditions = [];
3074
+ if (filters.categoryName) {
3075
+ whereConditions.push({ category: { _eq: filters.categoryName } });
3076
+ }
3077
+ if (filters.subcategoryId) {
3078
+ whereConditions.push({ subcategory: { _eq: filters.subcategoryId } });
3079
+ }
3080
+ if (filters.brandId) {
3081
+ whereConditions.push({ brand_id: { _eq: filters.brandId } });
3082
+ }
3083
+ if (filters.search) {
3084
+ const term = `%${filters.search}%`;
3085
+ whereConditions.push({
3086
+ _or: [
3087
+ { name: { _ilike: term } },
3088
+ { description: { _ilike: term } },
3089
+ { brand: { name: { _ilike: term } } },
3090
+ { product_attributes: { value: { _ilike: term } } }
3091
+ ]
3092
+ });
3093
+ }
3094
+ if (filters.colors && filters.colors.length > 0) {
3095
+ whereConditions.push({ color: { _in: filters.colors } });
3096
+ }
3097
+ if (filters.tags && filters.tags.length > 0) {
3098
+ const tags = filters.tags.map((tag) => tag.trim()).filter(Boolean);
3099
+ if (tags.length > 0) {
3100
+ whereConditions.push({
3101
+ product_tag_assignments: {
3102
+ tag: {
3103
+ key: { _in: tags },
3104
+ is_active: { _eq: true }
3105
+ }
3106
+ }
3107
+ });
3108
+ }
3109
+ }
3110
+ if (filters.minPrice !== void 0 || filters.maxPrice !== void 0) {
3111
+ const priceCondition = {};
3112
+ if (filters.minPrice !== void 0) priceCondition._gte = filters.minPrice;
3113
+ if (filters.maxPrice !== void 0) priceCondition._lte = filters.maxPrice;
3114
+ whereConditions.push({
3115
+ product_variants: {
3116
+ product_variant_prices: {
3117
+ price: priceCondition,
3118
+ price_type: { _in: ["CLIENT", "SALE"] },
3119
+ _or: [
3120
+ { chain_id: { _eq: chainId } },
3121
+ { chain_id: { _is_null: true } }
3122
+ ]
3123
+ }
3124
+ }
3125
+ });
3126
+ }
3127
+ if (filters.attributes) {
3128
+ for (const [attrName, values] of Object.entries(filters.attributes)) {
3129
+ if (values.length > 0) {
3130
+ whereConditions.push({
3131
+ _or: [
3132
+ {
3133
+ product_attributes: {
3134
+ attribute: { name: { _eq: attrName } },
3135
+ value: { _in: values }
3136
+ }
3137
+ },
3138
+ {
3139
+ product_variants: {
3140
+ product_variant_attributes: {
3141
+ attribute: { name: { _eq: attrName } },
3142
+ value: { _in: values }
3143
+ }
3144
+ }
3145
+ }
3146
+ ]
3147
+ });
3148
+ }
3149
+ }
3150
+ }
3151
+ return whereConditions.length > 0 ? { _and: whereConditions } : {};
3152
+ }
3153
+ function hasMeaningfulCategoryListFilters(filters) {
3154
+ if (!filters) return false;
3155
+ return Boolean(
3156
+ filters.search || filters.brandId || filters.minPrice !== void 0 || filters.maxPrice !== void 0 || (filters.tags?.some((tag) => tag.trim().length > 0) ?? false) || Object.values(filters.attributes ?? {}).some(
3157
+ (values) => values.length > 0
3158
+ )
3159
+ );
3160
+ }
3161
+ async function getWebsiteAvailabilityByVariantId(graphqlUrl, getHeaders, variantIds, chainId) {
3162
+ const uniqueVariantIds = uniqueValues2(variantIds);
3163
+ const availabilityByVariantId = /* @__PURE__ */ new Map();
3164
+ for (const chunk of chunkArray2(
3165
+ uniqueVariantIds,
3166
+ MAX_AVAILABILITY_VARIANT_IDS2
3167
+ )) {
3168
+ const data = await executeGraphQL(
3169
+ graphqlUrl,
3170
+ CHECK_AVAILABILITY,
3171
+ { variantIds: chunk, chainId },
3172
+ getHeaders
3173
+ );
3174
+ for (const item of data.websiteProductAvailability ?? []) {
3175
+ availabilityByVariantId.set(item.product_variant_id, {
3176
+ inStock: item.in_stock
3177
+ });
3178
+ }
3179
+ }
3180
+ return availabilityByVariantId;
3181
+ }
3182
+ async function filterProductsForWebsiteStock(graphqlUrl, getHeaders, products, chainId) {
3183
+ const variantIds = products.flatMap(
3184
+ (product) => product.variants.map((variant) => variant.id)
3185
+ );
3186
+ if (variantIds.length === 0) return [];
3187
+ const inStockVariantIds = new Set(
3188
+ Array.from(
3189
+ (await getWebsiteAvailabilityByVariantId(
3190
+ graphqlUrl,
3191
+ getHeaders,
3192
+ variantIds,
3193
+ chainId
3194
+ )).entries()
3195
+ ).filter(([, item]) => item.inStock).map(([variantId]) => variantId)
3196
+ );
3197
+ return products.map((product) => ({
3198
+ ...product,
3199
+ variants: product.variants.map((variant) => {
3200
+ const prices = selectPublicPrices(variant.prices, chainId);
3201
+ return {
3202
+ ...variant,
3203
+ prices,
3204
+ pricing: resolveProductPricing(prices)
3205
+ };
3206
+ }).filter(
3207
+ (variant) => inStockVariantIds.has(variant.id) && variant.pricing.currentPrice != null
3208
+ )
3209
+ })).filter((product) => product.variants.length > 0);
3210
+ }
3211
+ async function filterSeoProductsForWebsiteStock(graphqlUrl, getHeaders, products, chainId) {
3212
+ const variantIds = products.flatMap(
3213
+ (product) => product.product_variants.map((variant) => variant.id)
3214
+ );
3215
+ if (variantIds.length === 0) return [];
3216
+ const inStockVariantIds = new Set(
3217
+ Array.from(
3218
+ (await getWebsiteAvailabilityByVariantId(
3219
+ graphqlUrl,
3220
+ getHeaders,
3221
+ variantIds,
3222
+ chainId
3223
+ )).entries()
3224
+ ).filter(([, item]) => item.inStock).map(([variantId]) => variantId)
3225
+ );
3226
+ return products.filter(
3227
+ (product) => product.product_variants.some((variant) => {
3228
+ const prices = variant.product_variant_prices.map(mapPrice);
3229
+ const pricing = resolveProductPricing(
3230
+ selectPublicPrices(prices, chainId)
3231
+ );
3232
+ return inStockVariantIds.has(variant.id) && pricing.currentPrice != null;
3233
+ })
3234
+ );
3235
+ }
3236
+ function mapProductSeoEntry(raw, storageUrl) {
3237
+ if (!raw.slug) return null;
3238
+ return {
3239
+ id: raw.id,
3240
+ name: raw.name,
3241
+ slug: raw.slug,
3242
+ createdAt: raw.created_at,
3243
+ updatedAt: raw.updated_at,
3244
+ seoTitle: raw.seo_title ?? null,
3245
+ seoDescription: raw.seo_description ?? null,
3246
+ seoImage: mapSeoMedia(raw, storageUrl),
3247
+ primaryImage: raw.product_media[0] ? mapMedia(raw.product_media[0], storageUrl) : null,
3248
+ category: raw.category,
3249
+ subcategory: raw.subcategory
3250
+ };
3251
+ }
3252
+ function createCatalogModule(graphqlUrl, getHeaders, getContext, storageUrl) {
3253
+ const mapSingleProductResult = async (data) => {
3254
+ const ctx = getContext();
3255
+ if (!ctx.chainId) {
3256
+ throw new WebsiteError(
3257
+ "This website has no chain configured. Catalog requires a chain_id.",
3258
+ "NO_CHAIN"
3259
+ );
3260
+ }
3261
+ const product = data.products?.[0];
3262
+ if (!product) return null;
3263
+ const publicAttributeLabels = buildPublicAttributeLabels(
3264
+ data.catalog_attribute_lists
3265
+ );
3266
+ const filteredProducts = await filterProductsForWebsiteStock(
3267
+ graphqlUrl,
3268
+ getHeaders,
3269
+ [mapProduct(product, storageUrl, publicAttributeLabels, ctx.chainId)],
3270
+ ctx.chainId
3271
+ );
3272
+ return filteredProducts[0] ?? null;
3273
+ };
3274
+ return {
3275
+ async getProductRecommendations(opts) {
3276
+ const ctx = getContext();
3277
+ const limit = opts.limit ?? 16;
3278
+ if (!Number.isInteger(limit) || limit < 1 || limit > 32) {
3279
+ throw new WebsiteError(
3280
+ "Recommendation limit must be an integer between 1 and 32.",
3281
+ "INVALID_RECOMMENDATION_LIMIT"
3282
+ );
3283
+ }
3284
+ const data = await executeGraphQL(
3285
+ graphqlUrl,
3286
+ WEBSITE_GET_PRODUCT_RECOMMENDATIONS,
3287
+ {
3288
+ websiteId: ctx.websiteId,
3289
+ productId: opts.productId,
3290
+ limit
3291
+ },
3292
+ getHeaders
3293
+ );
3294
+ if (!data.result.success) {
3295
+ throw new WebsiteError(
3296
+ data.result.errors.join("; ") || "Unable to resolve product recommendations",
3297
+ "PRODUCT_RECOMMENDATIONS_ERROR"
3298
+ );
3299
+ }
3300
+ const products = parseActionJson(
3301
+ data.result.products,
3302
+ []
3303
+ );
3304
+ return {
3305
+ products: products.map(
3306
+ (product) => mapProductRecommendation(product, storageUrl)
3307
+ ),
3308
+ strategy: data.result.strategy
3309
+ };
3310
+ },
3311
+ async getProductSeoEntries(opts) {
3312
+ const ctx = getContext();
3313
+ if (!ctx.chainId) {
3314
+ throw new WebsiteError(
3315
+ "This website has no chain configured. Catalog requires a chain_id.",
3316
+ "NO_CHAIN"
3317
+ );
3318
+ }
3319
+ const limit = opts?.limit ?? 100;
3320
+ const offset = opts?.offset ?? 0;
3321
+ const data = await executeGraphQL(
3322
+ graphqlUrl,
3323
+ GET_PRODUCT_SEO_ENTRIES,
3324
+ {
3325
+ companyId: ctx.companyId,
3326
+ chainId: ctx.chainId,
3327
+ websiteId: ctx.websiteId,
3328
+ limit: limit + 1,
3329
+ offset
3330
+ },
3331
+ getHeaders
3332
+ );
3333
+ const availableProducts = await filterSeoProductsForWebsiteStock(
3334
+ graphqlUrl,
3335
+ getHeaders,
3336
+ data.products ?? [],
3337
+ ctx.chainId
3338
+ );
3339
+ const entries = availableProducts.slice(0, limit).map((product) => mapProductSeoEntry(product, storageUrl)).filter((entry) => Boolean(entry));
3340
+ return {
3341
+ entries,
3342
+ pagination: {
3343
+ limit,
3344
+ offset,
3345
+ hasMore: (data.products ?? []).length > limit
3346
+ }
3347
+ };
3348
+ },
3349
+ async getCatalogPage(opts) {
3350
+ const ctx = getContext();
3351
+ if (!ctx.chainId) {
3352
+ throw new WebsiteError(
3353
+ "This website has no chain configured. Catalog requires a chain_id.",
3354
+ "NO_CHAIN"
3355
+ );
3356
+ }
3357
+ const chainId = ctx.chainId;
3358
+ const filters = {
3359
+ category_slug: opts.categorySlug,
3360
+ subcategory_slug: opts.subcategorySlug,
3361
+ tags: opts.tags,
3362
+ search: opts.search,
3363
+ brand_id: opts.brandId,
3364
+ min_price: opts.minPrice,
3365
+ max_price: opts.maxPrice,
3366
+ attributes_by_slug: opts.attributesBySlug,
3367
+ sort_by: opts.sortBy,
3368
+ limit: opts.limit,
3369
+ offset: opts.offset
3370
+ };
3371
+ const data = await executeGraphQL(
3372
+ graphqlUrl,
3373
+ WEBSITE_GET_CATALOG_PAGE,
3374
+ {
3375
+ websiteId: ctx.websiteId,
3376
+ categoryListKey: opts.categoryListKey,
3377
+ attributeListKey: opts.attributeListKey,
3378
+ filters,
3379
+ include: opts.include
3380
+ },
3381
+ getHeaders
3382
+ );
3383
+ if (!data.result.success) {
3384
+ throw new WebsiteError(
3385
+ data.result.errors.join("; ") || "Unable to resolve catalog page",
3386
+ "CATALOG_PAGE_ERROR"
3387
+ );
3388
+ }
3389
+ const products = parseActionJson(data.result.products, []);
3390
+ const categoryList = parseActionJson(
3391
+ data.result.category_list,
3392
+ null
3393
+ );
3394
+ const attributeList = parseActionJson(
3395
+ data.result.attribute_list,
3396
+ null
3397
+ );
3398
+ const filtersResult = parseActionJson(
3399
+ data.result.filters,
3400
+ null
3401
+ );
3402
+ const brands = parseActionJson(data.result.brands, []);
3403
+ const pagination = parseActionJson(
3404
+ data.result.pagination,
3405
+ { limit: opts.limit ?? 24, offset: opts.offset ?? 0, total: 0, hasMore: false }
3406
+ );
3407
+ const appliedFilters = parseActionJson(
3408
+ data.result.applied_filters,
3409
+ {}
3410
+ );
3411
+ const debug = parseActionJson(
3412
+ data.result.debug,
3413
+ null
3414
+ );
3415
+ const labels = buildPublicAttributeLabels(
3416
+ attributeList ? [attributeList] : []
3417
+ );
3418
+ return {
3419
+ products: products.map(
3420
+ (product) => mapProduct(product, storageUrl, labels, chainId)
3421
+ ),
3422
+ categories: categoryList ? mapCategoryList(categoryList) : null,
3423
+ attributes: attributeList ? mapAttributeList(attributeList) : null,
3424
+ filters: filtersResult,
3425
+ brands,
3426
+ pagination,
3427
+ appliedFilters,
3428
+ debug
3429
+ };
3430
+ },
3431
+ async getProducts(opts) {
3432
+ const ctx = getContext();
3433
+ if (!ctx.chainId) {
3434
+ throw new WebsiteError(
3435
+ "This website has no chain configured. Catalog requires a chain_id.",
3436
+ "NO_CHAIN"
3437
+ );
3438
+ }
3439
+ const chainId = ctx.chainId;
3440
+ const where = buildProductWhere(opts ?? {}, chainId);
3441
+ const orderBy = buildOrderBy(opts?.sortBy);
3442
+ const variables = {
3443
+ companyId: ctx.companyId,
3444
+ chainId,
3445
+ websiteId: ctx.websiteId,
3446
+ limit: opts?.limit ?? 20,
3447
+ offset: opts?.offset ?? 0,
3448
+ where
3449
+ };
3450
+ if (orderBy) {
3451
+ variables.orderBy = orderBy;
3452
+ }
3453
+ const data = await executeGraphQL(graphqlUrl, GET_PRODUCTS, variables, getHeaders);
3454
+ const publicAttributeLabels = buildPublicAttributeLabels(
3455
+ data.catalog_attribute_lists
3456
+ );
3457
+ let products = await filterProductsForWebsiteStock(
3458
+ graphqlUrl,
3459
+ getHeaders,
3460
+ (data.products ?? []).map(
3461
+ (p) => mapProduct(p, storageUrl, publicAttributeLabels, chainId)
3462
+ ),
3463
+ chainId
3464
+ );
3465
+ if (opts?.minPrice !== void 0 || opts?.maxPrice !== void 0) {
3466
+ products = products.filter(
3467
+ (product) => product.variants.some((variant) => {
3468
+ const currentPrice = variant.pricing.currentPrice;
3469
+ if (currentPrice == null) return false;
3470
+ if (opts.minPrice !== void 0 && currentPrice < opts.minPrice) {
3471
+ return false;
3472
+ }
3473
+ return !(opts.maxPrice !== void 0 && currentPrice > opts.maxPrice);
3474
+ })
3475
+ );
3476
+ }
3477
+ if (opts?.sortBy === "price_asc") {
3478
+ products.sort((a, b) => getMinVariantPrice(a) - getMinVariantPrice(b));
3479
+ } else if (opts?.sortBy === "price_desc") {
3480
+ products.sort((a, b) => getMinVariantPrice(b) - getMinVariantPrice(a));
3481
+ } else if (opts?.search && !opts?.sortBy) {
3482
+ const search = opts.search;
3483
+ products.sort((a, b) => {
3484
+ const diff = scoreSearchRelevance(b, search) - scoreSearchRelevance(a, search);
3485
+ return diff !== 0 ? diff : a.name.localeCompare(b.name);
3486
+ });
3487
+ }
3488
+ return products;
3489
+ },
3490
+ async getProduct(productId) {
3491
+ const ctx = getContext();
3492
+ if (!ctx.chainId) {
3493
+ throw new WebsiteError(
3494
+ "This website has no chain configured. Catalog requires a chain_id.",
3495
+ "NO_CHAIN"
3496
+ );
3497
+ }
3498
+ const data = await executeGraphQL(
3499
+ graphqlUrl,
3500
+ GET_PRODUCT_BY_PK,
3501
+ {
3502
+ productId,
3503
+ companyId: ctx.companyId,
3504
+ chainId: ctx.chainId,
3505
+ websiteId: ctx.websiteId
3506
+ },
3507
+ getHeaders
3508
+ );
3509
+ return mapSingleProductResult(data);
3510
+ },
3511
+ async getProductBySlug(slug) {
3512
+ const ctx = getContext();
3513
+ if (!ctx.chainId) {
3514
+ throw new WebsiteError(
3515
+ "This website has no chain configured. Catalog requires a chain_id.",
3516
+ "NO_CHAIN"
3517
+ );
3518
+ }
3519
+ const data = await executeGraphQL(
3520
+ graphqlUrl,
3521
+ GET_PRODUCT_BY_SLUG,
3522
+ {
3523
+ slug,
3524
+ companyId: ctx.companyId,
3525
+ chainId: ctx.chainId,
3526
+ websiteId: ctx.websiteId
3527
+ },
3528
+ getHeaders
3529
+ );
3530
+ return mapSingleProductResult(data);
3531
+ },
3532
+ async getCategories() {
3533
+ const data = await executeGraphQL(graphqlUrl, GET_CATEGORIES, {}, getHeaders);
3534
+ return (data.product_categories ?? []).map(mapCategory);
3535
+ },
3536
+ async getCategoryList(opts) {
3537
+ const ctx = getContext();
3538
+ const data = await executeGraphQL(
3539
+ graphqlUrl,
3540
+ GET_CATALOG_CATEGORY_LIST,
3541
+ {
3542
+ companyId: ctx.companyId,
3543
+ key: opts.key
3544
+ },
3545
+ getHeaders
3546
+ );
3547
+ const list = data.list?.[0] ?? null;
3548
+ if (!list) return null;
3549
+ if (opts.onlyApplicable || hasMeaningfulCategoryListFilters(opts.filters)) {
3550
+ if (!ctx.chainId) {
3551
+ throw new WebsiteError(
3552
+ "This website has no chain configured. Applicable category lists require a chain_id.",
3553
+ "NO_CHAIN"
3554
+ );
3555
+ }
3556
+ const chainId = ctx.chainId;
3557
+ const applicableProductsData = await executeGraphQL(
3558
+ graphqlUrl,
3559
+ GET_PRODUCT_FILTERS,
3560
+ {
3561
+ companyId: ctx.companyId,
3562
+ chainId,
3563
+ attributeListKey: DEFAULT_FILTER_ATTRIBUTE_LIST_KEY,
3564
+ where: buildProductWhere(opts.filters ?? {}, chainId)
3565
+ },
3566
+ getHeaders
3567
+ );
3568
+ const variantIds = (applicableProductsData.products ?? []).flatMap(
3569
+ (product) => product.product_variants.map((variant) => variant.id)
3570
+ );
3571
+ const availabilityByVariantId = await getWebsiteAvailabilityByVariantId(
3572
+ graphqlUrl,
3573
+ getHeaders,
3574
+ variantIds,
3575
+ chainId
3576
+ );
3577
+ const applicableCategories = /* @__PURE__ */ new Set();
3578
+ const applicableSubcategoryIds = /* @__PURE__ */ new Set();
3579
+ for (const product of applicableProductsData.products ?? []) {
3580
+ const hasVisibleVariant = product.product_variants.some((variant) => {
3581
+ const prices = selectPublicPrices(
3582
+ variant.product_variant_prices.map(mapPrice),
3583
+ chainId
3584
+ );
3585
+ return prices.length > 0 && (availabilityByVariantId.get(variant.id)?.inStock ?? false);
3586
+ });
3587
+ if (!hasVisibleVariant) continue;
3588
+ applicableCategories.add(product.category);
3589
+ if (product.subcategory) {
3590
+ applicableSubcategoryIds.add(product.subcategory);
3591
+ }
3592
+ }
3593
+ return filterCategoryListByApplicability(
3594
+ list,
3595
+ applicableCategories,
3596
+ applicableSubcategoryIds
3597
+ );
3598
+ }
3599
+ return mapCategoryList(list);
3600
+ },
3601
+ async getAttributeList(opts) {
3602
+ const ctx = getContext();
3603
+ if (opts.onlyApplicable || hasMeaningfulAttributeListFilters(opts.filters)) {
3604
+ if (!ctx.websiteId) {
3605
+ throw new WebsiteError(
3606
+ "This client has no website configured. Contextual attribute lists require a website_id.",
3607
+ "NO_WEBSITE"
3608
+ );
3609
+ }
3610
+ const data2 = await executeGraphQL(
3611
+ graphqlUrl,
3612
+ GET_CONTEXTUAL_CATALOG_ATTRIBUTE_LIST,
3613
+ {
3614
+ websiteId: ctx.websiteId,
3615
+ key: opts.key,
3616
+ onlyApplicable: opts.onlyApplicable ? true : void 0,
3617
+ filters: opts.filters
3618
+ },
3619
+ getHeaders
3620
+ );
3621
+ const result = data2.websiteGetAttributeList;
3622
+ if (!result.success) {
3623
+ throw new WebsiteError(
3624
+ result.errors?.join("; ") || "Unable to resolve attribute list",
3625
+ "ATTRIBUTE_LIST_ERROR"
3626
+ );
3627
+ }
3628
+ return result.list ? mapContextualAttributeList(result.list) : null;
3629
+ }
3630
+ const data = await executeGraphQL(
3631
+ graphqlUrl,
3632
+ GET_CATALOG_ATTRIBUTE_LIST,
3633
+ {
3634
+ companyId: ctx.companyId,
3635
+ key: opts.key
3636
+ },
3637
+ getHeaders
3638
+ );
3639
+ const list = data.list?.[0] ?? null;
3640
+ return list ? mapAttributeList(list) : null;
3641
+ },
3642
+ async getBrands() {
3643
+ const ctx = getContext();
3644
+ if (!ctx.chainId) {
3645
+ throw new WebsiteError(
3646
+ "This website has no chain configured. Brands require a chain_id.",
3647
+ "NO_CHAIN"
3648
+ );
3649
+ }
3650
+ const data = await executeGraphQL(
3651
+ graphqlUrl,
3652
+ GET_BRANDS,
3653
+ { companyId: ctx.companyId, chainId: ctx.chainId },
3654
+ getHeaders
3655
+ );
3656
+ return data.brands ?? [];
3657
+ },
3658
+ async getProductFilters(opts) {
3659
+ const ctx = getContext();
3660
+ if (!ctx.chainId) {
3661
+ throw new WebsiteError(
3662
+ "This website has no chain configured. Catalog filters require a chain_id.",
3663
+ "NO_CHAIN"
3664
+ );
3665
+ }
3666
+ const chainId = ctx.chainId;
3667
+ const data = await executeGraphQL(
3668
+ graphqlUrl,
3669
+ GET_PRODUCT_FILTERS,
3670
+ {
3671
+ companyId: ctx.companyId,
3672
+ chainId,
3673
+ attributeListKey: opts?.attributeListKey ?? DEFAULT_FILTER_ATTRIBUTE_LIST_KEY,
3674
+ where: {
3675
+ ...opts?.categoryName ? { category: { _eq: opts.categoryName } } : {},
3676
+ ...opts?.subcategoryId ? { subcategory: { _eq: opts.subcategoryId } } : {}
3677
+ }
3678
+ },
3679
+ getHeaders
3680
+ );
3681
+ const categoryCounts = /* @__PURE__ */ new Map();
3682
+ const colorCounts = /* @__PURE__ */ new Map();
3683
+ const brandCounts = /* @__PURE__ */ new Map();
3684
+ const publicPrices = [];
3685
+ const attributeValueCounts = /* @__PURE__ */ new Map();
3686
+ const variantIds = (data.products ?? []).flatMap(
3687
+ (product) => product.product_variants.map((variant) => variant.id)
3688
+ );
3689
+ const availabilityByVariantId = await getWebsiteAvailabilityByVariantId(
3690
+ graphqlUrl,
3691
+ getHeaders,
3692
+ variantIds,
3693
+ chainId
3694
+ );
3695
+ const publicAttributeLabels = buildPublicAttributeLabels(
3696
+ data.catalog_attribute_lists
3697
+ );
3698
+ const configuredAttributeIds = new Set(
3699
+ (data.catalog_attribute_lists?.[0]?.items ?? []).map(
3700
+ (item) => item.attribute_id
3701
+ )
3702
+ );
3703
+ const registerAttributeValue = (raw) => {
3704
+ if (!configuredAttributeIds.has(raw.attribute.id)) return;
3705
+ const valueCode = attributeValueCode(raw);
3706
+ const value = raw.attribute_value ?? null;
3707
+ const counts = attributeValueCounts.get(raw.attribute.id) ?? /* @__PURE__ */ new Map();
3708
+ const current = counts.get(valueCode);
3709
+ counts.set(valueCode, {
3710
+ count: (current?.count ?? 0) + 1,
3711
+ value: value ?? current?.value ?? null
3712
+ });
3713
+ attributeValueCounts.set(raw.attribute.id, counts);
3714
+ };
3715
+ for (const product of data.products ?? []) {
3716
+ if (opts?.categoryName && product.category !== opts.categoryName) {
3717
+ continue;
3718
+ }
3719
+ const visibleVariants = product.product_variants.map((variant) => ({
3720
+ ...variant,
3721
+ prices: selectPublicPrices(
3722
+ variant.product_variant_prices.map(mapPrice),
3723
+ chainId
3724
+ ),
3725
+ inStock: availabilityByVariantId.get(variant.id)?.inStock ?? false
3726
+ })).filter((variant) => variant.inStock && variant.prices.length > 0);
3727
+ if (visibleVariants.length === 0) continue;
3728
+ categoryCounts.set(
3729
+ product.category,
3730
+ (categoryCounts.get(product.category) ?? 0) + 1
3731
+ );
3732
+ if (product.color) {
3733
+ colorCounts.set(
3734
+ product.color,
3735
+ (colorCounts.get(product.color) ?? 0) + 1
3736
+ );
3737
+ }
3738
+ if (product.brand) {
3739
+ const current = brandCounts.get(product.brand.id);
3740
+ brandCounts.set(product.brand.id, {
3741
+ id: product.brand.id,
3742
+ name: product.brand.name,
3743
+ count: (current?.count ?? 0) + 1
3744
+ });
3745
+ }
3746
+ for (const variant of visibleVariants) {
3747
+ for (const price of variant.prices) {
3748
+ publicPrices.push(price.price);
3749
+ }
3750
+ if (opts?.categoryName) {
3751
+ for (const attribute of variant.product_variant_attributes) {
3752
+ registerAttributeValue(attribute);
3753
+ }
3754
+ }
3755
+ }
3756
+ if (opts?.categoryName) {
3757
+ for (const attribute of product.product_attributes) {
3758
+ registerAttributeValue(attribute);
3759
+ }
3760
+ }
3761
+ }
3762
+ const attributes = opts?.categoryName ? (data.catalog_attribute_lists?.[0]?.items ?? []).map((item) => {
3763
+ const counts = attributeValueCounts.get(item.attribute_id);
3764
+ if (!counts || counts.size === 0) return null;
3765
+ return {
3766
+ id: item.attribute_id,
3767
+ name: item.public_label,
3768
+ values: Array.from(counts.entries()).map(([valueCode, countItem]) => ({
3769
+ value: publicAttributeLabels.valueLabelsById.get(
3770
+ countItem.value?.id ?? ""
3771
+ ) ?? publicAttributeLabels.valueLabelsByAttributeAndCode.get(
3772
+ attributeValueLabelKey(item.attribute_id, valueCode)
3773
+ ) ?? valueCode,
3774
+ count: countItem.count,
3775
+ attributeValueId: countItem.value?.id ?? null,
3776
+ code: countItem.value?.code ?? valueCode,
3777
+ metadata: countItem.value?.metadata ?? null,
3778
+ sortOrder: countItem.value?.sort_order ?? null
3779
+ })).sort((a, b) => {
3780
+ const orderA = a.sortOrder ?? Number.MAX_SAFE_INTEGER;
3781
+ const orderB = b.sortOrder ?? Number.MAX_SAFE_INTEGER;
3782
+ return orderA === orderB ? a.value.localeCompare(b.value) : orderA - orderB;
3783
+ })
3784
+ };
3785
+ }).filter((item) => Boolean(item)) : [];
3786
+ const minPrice = publicPrices.length > 0 ? Math.min(...publicPrices) : 0;
3787
+ const maxPrice = publicPrices.length > 0 ? Math.max(...publicPrices) : 0;
3788
+ return {
3789
+ categories: Array.from(categoryCounts.entries()).map(([name, count]) => ({ name, count })).sort((a, b) => a.name.localeCompare(b.name)),
3790
+ brands: Array.from(brandCounts.values()).sort(
3791
+ (a, b) => a.name.localeCompare(b.name)
3792
+ ),
3793
+ colors: Array.from(colorCounts.entries()).map(([value, count]) => ({ value, count })).sort((a, b) => a.value.localeCompare(b.value)),
3794
+ priceRange: {
3795
+ min: minPrice,
3796
+ max: maxPrice
3797
+ },
3798
+ attributes
3799
+ };
3800
+ },
3801
+ async getSearchSuggestions(opts) {
3802
+ if (!opts.query || opts.query.trim().length === 0) return [];
3803
+ const ctx = getContext();
3804
+ if (!ctx.chainId) {
3805
+ throw new WebsiteError(
3806
+ "This website has no chain configured. Search suggestions require a chain_id.",
3807
+ "NO_CHAIN"
3808
+ );
3809
+ }
3810
+ const term = `%${opts.query}%`;
3811
+ const limit = opts.limit ?? 8;
3812
+ const data = await executeGraphQL(
3813
+ graphqlUrl,
3814
+ GET_SEARCH_SUGGESTIONS,
3815
+ {
3816
+ companyId: ctx.companyId,
3817
+ chainId: ctx.chainId,
3818
+ term,
3819
+ productLimit: Math.min(limit, 5),
3820
+ brandLimit: Math.max(limit - 5, 3)
3821
+ },
3822
+ getHeaders
3823
+ );
3824
+ const suggestions = [];
3825
+ for (const p of data.products ?? []) {
3826
+ suggestions.push({ type: "product", text: p.name, id: p.id });
3827
+ }
3828
+ for (const b of data.brands ?? []) {
3829
+ suggestions.push({ type: "brand", text: b.name, id: b.id });
3830
+ }
3831
+ return suggestions.slice(0, limit);
3832
+ }
3833
+ };
3834
+ }
3835
+
3836
+ // libs/sdk/src/modules/checkout.ts
3837
+ function requireCartSession2(storage) {
3838
+ const session = storage.get();
3839
+ if (!session) {
3840
+ throw new WebsiteError(
3841
+ "No guest cart session found",
3842
+ "CART_SESSION_MISSING"
3843
+ );
3844
+ }
3845
+ return session;
3846
+ }
3847
+ function mapCartItem2(raw) {
3848
+ return {
3849
+ id: raw.id,
3850
+ productVariantId: raw.product_variant_id,
3851
+ quantity: raw.quantity,
3852
+ productVariant: {
3853
+ sku: raw.product_variant.sku,
3854
+ product: raw.product_variant.product,
3855
+ prices: raw.product_variant.prices.map((price) => ({
3856
+ id: price.id,
3857
+ price: price.price,
3858
+ priceType: price.price_type,
3859
+ chainId: price.chain_id
3860
+ }))
3861
+ }
3862
+ };
3863
+ }
3864
+ function mapCart2(raw) {
3865
+ return {
3866
+ id: raw.id,
3867
+ items: raw.items.map(mapCartItem2),
3868
+ totals: {
3869
+ subtotal: raw.total_without_tax,
3870
+ tax: raw.tax,
3871
+ discount: raw.discount,
3872
+ total: raw.total_with_tax
3873
+ },
3874
+ status: raw.status,
3875
+ createdAt: raw.created_at,
3876
+ updatedAt: raw.updated_at
3877
+ };
3878
+ }
3879
+ function mapCouponResult(raw) {
3880
+ return {
3881
+ success: raw.success,
3882
+ orderId: raw.order_id,
3883
+ couponId: raw.coupon_id,
3884
+ code: raw.code,
3885
+ name: raw.name,
3886
+ couponType: raw.coupon_type,
3887
+ discountAmount: Number(raw.discount_amount ?? 0),
3888
+ eligibleSubtotal: Number(raw.eligible_subtotal ?? 0),
3889
+ message: raw.message,
3890
+ cart: raw.cart ? mapCart2(raw.cart) : null,
3891
+ errors: raw.errors
3892
+ };
3893
+ }
3894
+ function createCheckoutModule(graphqlUrl, getHeaders, getContext, cartSessionStorage) {
3895
+ return {
3896
+ async getLocationOptions() {
3897
+ const context = getContext();
3898
+ const data = await executeGraphQL(
3899
+ graphqlUrl,
3900
+ GET_LOCATION_OPTIONS,
3901
+ { websiteId: context.websiteId },
3902
+ getHeaders
3903
+ );
3904
+ const result = data.websiteGetLocationOptions;
3905
+ if (!result.success) {
3906
+ throw new CheckoutError(result.errors ?? ["LOCATION_OPTIONS_FAILED"]);
3907
+ }
3908
+ return {
3909
+ countryCode: result.country_code,
3910
+ departments: result.departments.map((department) => ({
3911
+ departmentId: department.department_id,
3912
+ departmentName: department.department_name,
3913
+ departmentCode: department.department_code,
3914
+ municipalities: department.municipalities.map((municipality) => ({
3915
+ municipalityId: municipality.municipality_id,
3916
+ municipalityName: municipality.municipality_name,
3917
+ municipalityCode: municipality.municipality_code,
3918
+ departmentId: municipality.department_id,
3919
+ departmentCode: municipality.department_code
3920
+ }))
3921
+ }))
3922
+ };
3923
+ },
3924
+ async getDeliveryOptions() {
3925
+ const context = getContext();
3926
+ const data = await executeGraphQL(
3927
+ graphqlUrl,
3928
+ GET_DELIVERY_OPTIONS,
3929
+ { websiteId: context.websiteId },
3930
+ getHeaders
3931
+ );
3932
+ const result = data.websiteGetDeliveryOptions;
3933
+ if (!result.success) {
3934
+ throw new CheckoutError(result.errors ?? ["DELIVERY_OPTIONS_FAILED"]);
3935
+ }
3936
+ return result.delivery_options.map((option) => ({
3937
+ id: option.id,
3938
+ fulfillmentFamily: option.fulfillment_family,
3939
+ label: option.label,
3940
+ description: option.description,
3941
+ isEnabled: option.is_enabled,
3942
+ pickupInfo: option.pickup_info ? {
3943
+ label: option.pickup_info.label,
3944
+ address: option.pickup_info.address,
3945
+ schedule: option.pickup_info.schedule,
3946
+ notes: option.pickup_info.notes
3947
+ } : null
3948
+ }));
3949
+ },
3950
+ async getShippingQuotes(input) {
3951
+ const context = getContext();
3952
+ const session = cartSessionStorage.get();
3953
+ const items = session ? null : input.items?.length ? input.items : null;
3954
+ const data = await executeGraphQL(
3955
+ graphqlUrl,
3956
+ GET_SHIPPING_QUOTES,
3957
+ {
3958
+ websiteId: context.websiteId,
3959
+ orderId: session?.orderId ?? null,
3960
+ cartToken: session?.cartToken ?? null,
3961
+ items: items?.map((item) => ({
3962
+ product_variant_id: item.productVariantId,
3963
+ quantity: item.quantity
3964
+ })),
3965
+ address: input.address
3966
+ },
3967
+ getHeaders
3968
+ );
3969
+ const result = data.websiteGetShippingQuotes;
3970
+ if (!result.success) {
3971
+ throw new CheckoutError(result.errors ?? ["SHIPPING_QUOTES_FAILED"]);
3972
+ }
3973
+ return result.quotes.map((quote) => ({
3974
+ quoteId: quote.quote_id,
3975
+ shippingServiceId: quote.shipping_service_id,
3976
+ label: quote.label,
3977
+ serviceName: quote.service_name,
3978
+ baseAmount: quote.base_amount,
3979
+ amount: quote.amount,
3980
+ currency: quote.currency,
3981
+ collectionMode: quote.collection_mode,
3982
+ totalPolicy: quote.total_policy,
3983
+ estimatedDelivery: quote.estimated_delivery,
3984
+ freeShippingEligible: quote.free_shipping_eligible,
3985
+ freeShippingApplied: quote.free_shipping_applied,
3986
+ freeShippingThreshold: quote.free_shipping_threshold,
3987
+ freeShippingRemaining: quote.free_shipping_remaining,
3988
+ freeShippingEligibleSubtotal: quote.free_shipping_eligible_subtotal
3989
+ }));
3990
+ },
3991
+ async getShippingPolicy() {
3992
+ const context = getContext();
3993
+ const data = await executeGraphQL(
3994
+ graphqlUrl,
3995
+ GET_SHIPPING_POLICY,
3996
+ { websiteId: context.websiteId },
3997
+ getHeaders
3998
+ );
3999
+ const result = data.websiteGetShippingPolicy;
4000
+ if (!result.success || !result.policy) {
4001
+ throw new CheckoutError(result.errors ?? ["SHIPPING_POLICY_FAILED"]);
4002
+ }
4003
+ return {
4004
+ freeShippingEnabled: result.policy.free_shipping_enabled,
4005
+ freeShippingThreshold: result.policy.free_shipping_threshold,
4006
+ currency: result.policy.currency
4007
+ };
4008
+ },
4009
+ async getFreeShippingProgress(input) {
4010
+ if (input.items.length === 0) {
4011
+ throw new WebsiteError(
4012
+ "At least one cart item is required",
4013
+ "CART_ITEMS_REQUIRED"
4014
+ );
4015
+ }
4016
+ const context = getContext();
4017
+ const data = await executeGraphQL(
4018
+ graphqlUrl,
4019
+ GET_FREE_SHIPPING_PROGRESS,
4020
+ {
4021
+ websiteId: context.websiteId,
4022
+ items: input.items.map((item) => ({
4023
+ product_variant_id: item.productVariantId,
4024
+ quantity: item.quantity
4025
+ }))
4026
+ },
4027
+ getHeaders
4028
+ );
4029
+ const result = data.websiteGetFreeShippingProgress;
4030
+ if (!result.success || !result.progress) {
4031
+ throw new CheckoutError(
4032
+ result.errors ?? ["FREE_SHIPPING_PROGRESS_FAILED"]
4033
+ );
4034
+ }
4035
+ return {
4036
+ enabled: result.progress.enabled,
4037
+ threshold: result.progress.threshold,
4038
+ remaining: result.progress.remaining,
4039
+ eligibleSubtotal: result.progress.eligible_subtotal,
4040
+ thresholdReached: result.progress.threshold_reached,
4041
+ currency: result.progress.currency
4042
+ };
4043
+ },
4044
+ async getPaymentMethods() {
4045
+ const context = getContext();
4046
+ const data = await executeGraphQL(
4047
+ graphqlUrl,
4048
+ GET_PAYMENT_METHODS,
4049
+ { websiteId: context.websiteId },
4050
+ getHeaders
4051
+ );
4052
+ const result = data.websiteGetPaymentMethods;
4053
+ if (!result.success) {
4054
+ throw new CheckoutError(result.errors ?? ["PAYMENT_METHODS_FAILED"]);
4055
+ }
4056
+ return result.payment_methods.map((method) => ({
4057
+ id: method.id,
4058
+ code: method.code,
4059
+ label: method.label,
4060
+ paymentMethodType: method.payment_method_type,
4061
+ gatewayCode: method.gateway_code,
4062
+ description: method.description,
4063
+ isEnabled: method.is_enabled,
4064
+ sortOrder: method.sort_order,
4065
+ requiresPaymentSession: method.requires_payment_session,
4066
+ publicConfig: method.public_config
4067
+ }));
4068
+ },
4069
+ async getPaymentOptions(input) {
4070
+ const context = getContext();
4071
+ const data = await executeGraphQL(
4072
+ graphqlUrl,
4073
+ GET_PAYMENT_OPTIONS,
4074
+ {
4075
+ websiteId: context.websiteId,
4076
+ fulfillmentFamily: input.fulfillmentFamily
4077
+ },
4078
+ getHeaders
4079
+ );
4080
+ const result = data.websiteGetPaymentOptions;
4081
+ if (!result.success) {
4082
+ throw new CheckoutError(result.errors ?? ["PAYMENT_OPTIONS_FAILED"]);
4083
+ }
4084
+ return result.payment_options.map((option) => ({
4085
+ id: option.id,
4086
+ mode: option.mode,
4087
+ fulfillmentFamily: option.fulfillment_family,
4088
+ label: option.label,
4089
+ description: option.description,
4090
+ requiresPaymentMethod: option.requires_payment_method,
4091
+ allowsInitialPayment: option.allows_initial_payment,
4092
+ initialPaymentPolicy: option.initial_payment_policy,
4093
+ requiresInitialPayment: option.requires_initial_payment,
4094
+ minInitialAmount: option.min_initial_amount,
4095
+ suggestedInitialAmount: option.suggested_initial_amount,
4096
+ sortOrder: option.sort_order,
4097
+ methods: option.methods.map((method) => ({
4098
+ id: method.id,
4099
+ paymentMethodId: method.payment_method_id,
4100
+ code: method.code,
4101
+ label: method.label,
4102
+ paymentMethodType: method.payment_method_type,
4103
+ gatewayCode: method.gateway_code,
4104
+ description: method.description,
4105
+ instructions: method.instructions,
4106
+ qrFileId: method.qr_file_id,
4107
+ requiresPaymentSession: method.requires_payment_session,
4108
+ publicConfig: method.public_config ?? {},
4109
+ sortOrder: method.sort_order
4110
+ }))
4111
+ }));
4112
+ },
4113
+ async validateCoupon(input) {
4114
+ const session = requireCartSession2(cartSessionStorage);
4115
+ const data = await executeGraphQL(
4116
+ graphqlUrl,
4117
+ VALIDATE_COUPON,
4118
+ {
4119
+ orderId: session.orderId,
4120
+ cartToken: session.cartToken,
4121
+ code: input.code
4122
+ },
4123
+ getHeaders
4124
+ );
4125
+ return mapCouponResult(data.websiteValidateCoupon);
4126
+ },
4127
+ async applyCoupon(input) {
4128
+ const session = requireCartSession2(cartSessionStorage);
4129
+ const data = await executeGraphQL(
4130
+ graphqlUrl,
4131
+ APPLY_COUPON,
4132
+ {
4133
+ orderId: session.orderId,
4134
+ cartToken: session.cartToken,
4135
+ code: input.code
4136
+ },
4137
+ getHeaders
4138
+ );
4139
+ return mapCouponResult(data.websiteApplyCoupon);
4140
+ },
4141
+ async removeCoupon(input) {
4142
+ const session = requireCartSession2(cartSessionStorage);
4143
+ const data = await executeGraphQL(
4144
+ graphqlUrl,
4145
+ REMOVE_COUPON,
4146
+ {
4147
+ orderId: session.orderId,
4148
+ cartToken: session.cartToken,
4149
+ couponId: input.couponId
4150
+ },
4151
+ getHeaders
4152
+ );
4153
+ return mapCouponResult(data.websiteRemoveCoupon);
4154
+ },
4155
+ async submit(input) {
4156
+ const session = requireCartSession2(cartSessionStorage);
4157
+ const data = await executeGraphQL(
4158
+ graphqlUrl,
4159
+ CHECKOUT,
4160
+ {
4161
+ orderId: session.orderId,
4162
+ cartToken: session.cartToken,
4163
+ contact: input.contact,
4164
+ fulfillmentFamily: input.fulfillmentFamily,
4165
+ address: input.address,
4166
+ shippingQuoteId: input.shippingQuoteId,
4167
+ paymentMode: input.paymentMode,
4168
+ paymentMethodId: input.paymentMethodId,
4169
+ buyerAccountOptIn: input.buyerAccountOptIn,
4170
+ initialPayment: input.initialPayment ? {
4171
+ amount: input.initialPayment.amount,
4172
+ payment_method_id: input.initialPayment.paymentMethodId
4173
+ } : void 0
4174
+ },
4175
+ getHeaders
4176
+ );
4177
+ const result = data.websiteCheckout;
4178
+ if (!result.success && result.errors && result.errors.length > 0) {
4179
+ throw new CheckoutError(result.errors);
4180
+ }
4181
+ if (result.success && !result.requires_payment_session) {
4182
+ cartSessionStorage.clear();
4183
+ }
4184
+ return {
4185
+ success: result.success,
4186
+ orderId: result.order_id,
4187
+ orderNumber: result.order_number,
4188
+ paymentMethodId: result.payment_method_id,
4189
+ publicOrderToken: result.public_order_token,
4190
+ requiresPaymentSession: Boolean(result.requires_payment_session),
4191
+ buyerAccountInvitationRequested: Boolean(
4192
+ result.buyer_account_invitation_requested
4193
+ ),
4194
+ errors: result.errors
4195
+ };
4196
+ },
4197
+ async createPaymentSession(input) {
4198
+ const session = cartSessionStorage.get();
4199
+ const orderId = input.orderId ?? session?.orderId;
4200
+ if (!orderId || !input.publicOrderToken && !session?.cartToken) {
4201
+ throw new WebsiteError(
4202
+ "Payment retry requires an order and public order token",
4203
+ "PAYMENT_SESSION_CONTEXT_MISSING"
4204
+ );
4205
+ }
4206
+ const data = await executeGraphQL(
4207
+ graphqlUrl,
4208
+ CREATE_PAYMENT_SESSION,
4209
+ {
4210
+ orderId,
4211
+ cartToken: input.publicOrderToken ? null : session?.cartToken,
4212
+ publicOrderToken: input.publicOrderToken ?? null,
4213
+ paymentMethodId: input.paymentMethodId,
4214
+ returnUrl: input.returnUrl
4215
+ },
4216
+ getHeaders
4217
+ );
4218
+ const result = data.websiteCreatePaymentSession;
4219
+ if (result.success && result.payment_session_id && (result.integration_mode !== "redirect" || !result.redirect_url)) {
4220
+ throw new WebsiteError(
4221
+ "Payment gateway did not provide a redirect URL",
4222
+ "PAYMENT_GATEWAY_REDIRECT_NOT_AVAILABLE"
4223
+ );
4224
+ }
4225
+ if (result.success) {
4226
+ cartSessionStorage.clear();
4227
+ }
4228
+ return {
4229
+ success: result.success,
4230
+ orderId: result.order_id,
4231
+ paymentMethodId: result.payment_method_id,
4232
+ paymentSessionId: result.payment_session_id,
4233
+ gatewayCode: result.gateway_code,
4234
+ integrationMode: result.integration_mode === "redirect" ? "redirect" : null,
4235
+ status: result.status,
4236
+ redirectUrl: result.redirect_url,
4237
+ publicPayload: result.public_payload,
4238
+ errors: result.errors
4239
+ };
4240
+ },
4241
+ async reconcilePaymentSession(input) {
4242
+ const data = await executeGraphQL(
4243
+ graphqlUrl,
4244
+ RECONCILE_PAYMENT_SESSION,
4245
+ {
4246
+ orderId: input.orderId,
4247
+ publicOrderToken: input.publicOrderToken,
4248
+ paymentSessionId: input.paymentSessionId,
4249
+ gatewayTransactionId: input.gatewayTransactionId
4250
+ },
4251
+ getHeaders
4252
+ );
4253
+ const result = data.websiteReconcilePaymentSession;
4254
+ return {
4255
+ success: result.success,
4256
+ orderId: result.order_id,
4257
+ paymentMethodId: result.payment_method_id,
4258
+ paymentSessionId: result.payment_session_id,
4259
+ gatewayCode: result.gateway_code,
4260
+ integrationMode: result.integration_mode === "redirect" ? "redirect" : null,
4261
+ status: result.status,
4262
+ redirectUrl: result.redirect_url,
4263
+ publicPayload: result.public_payload,
4264
+ errors: result.errors
4265
+ };
4266
+ }
4267
+ };
4268
+ }
4269
+
4270
+ // libs/sdk/src/modules/content.ts
4271
+ var DEFAULT_LOCALE = "es-CO";
4272
+ function mapEntry(raw) {
4273
+ return {
4274
+ id: raw.id,
4275
+ key: raw.key,
4276
+ categoryKey: raw.category_key,
4277
+ name: raw.name,
4278
+ locale: raw.locale,
4279
+ status: raw.status,
4280
+ tags: raw.tags ?? [],
4281
+ contentJson: raw.content_json ?? {},
4282
+ resolvedFields: raw.resolved_fields ?? {},
4283
+ publishedAt: raw.published_at,
4284
+ updatedAt: raw.updated_at,
4285
+ contentType: {
4286
+ id: raw.content_type.id,
4287
+ key: raw.content_type.key,
4288
+ name: raw.content_type.name,
4289
+ kind: raw.content_type.kind
4290
+ }
4291
+ };
4292
+ }
4293
+ function baseVariables(ctx, opts) {
4294
+ return {
4295
+ websiteId: ctx.websiteId,
4296
+ locale: opts?.locale ?? DEFAULT_LOCALE
4297
+ };
4298
+ }
4299
+ function isRecord(value) {
4300
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4301
+ }
4302
+ function readOptionalText(value) {
4303
+ return typeof value === "string" && value.trim() ? value.trim() : null;
4304
+ }
4305
+ function enrichMediaValue(value, storageUrl) {
4306
+ const fileId = typeof value.fileId === "string" && value.fileId.trim() ? value.fileId.trim() : "";
4307
+ if (!fileId) return value;
4308
+ const urls = buildStorageMediaUrls(storageUrl, fileId);
4309
+ return {
4310
+ ...value,
4311
+ ...urls,
4312
+ url: value.url ?? urls.originalUrl
4313
+ };
4314
+ }
4315
+ function normalizeRichTextNode(value, storageUrl) {
4316
+ const type = value.type;
4317
+ const attrs = isRecord(value.attrs) ? value.attrs : null;
4318
+ if (attrs && (type === "bacanoImage" || type === "bacanoVideo") && typeof attrs.fileId === "string") {
4319
+ const urls = buildStorageMediaUrls(storageUrl, attrs.fileId);
4320
+ const altText = readOptionalText(attrs.altText) ?? readOptionalText(attrs.alt);
4321
+ const caption = readOptionalText(attrs.caption);
4322
+ const showCaption = Boolean(caption) && attrs.showCaption !== false;
4323
+ return {
4324
+ ...value,
4325
+ attrs: {
4326
+ ...attrs,
4327
+ ...urls,
4328
+ alt: altText,
4329
+ altText,
4330
+ caption,
4331
+ showCaption,
4332
+ src: type === "bacanoImage" ? urls.detailUrl : urls.originalUrl
4333
+ }
4334
+ };
4335
+ }
4336
+ return value;
4337
+ }
4338
+ function normalizeContentMedia(value, storageUrl) {
4339
+ if (Array.isArray(value)) {
4340
+ return value.map((item) => normalizeContentMedia(item, storageUrl));
4341
+ }
4342
+ if (!isRecord(value)) return value;
4343
+ const normalized = normalizeRichTextNode(value, storageUrl);
4344
+ const enriched = typeof normalized.fileId === "string" && typeof normalized.mediaKind === "string" ? enrichMediaValue(normalized, storageUrl) : normalized;
4345
+ return Object.fromEntries(
4346
+ Object.entries(enriched).map(([key, entryValue]) => [
4347
+ key,
4348
+ normalizeContentMedia(entryValue, storageUrl)
4349
+ ])
4350
+ );
4351
+ }
4352
+ function getEntries(data) {
4353
+ if (!data.result?.success) return [];
4354
+ return data.result.entries ?? [];
4355
+ }
4356
+ function chooseOne(data, storageUrl) {
4357
+ const entry = getEntries(data)[0] ?? null;
4358
+ return entry ? mapEntryWithMedia(entry, storageUrl) : null;
4359
+ }
4360
+ function chooseMany(data, storageUrl) {
4361
+ return getEntries(data).map((entry) => mapEntryWithMedia(entry, storageUrl));
4362
+ }
4363
+ function mapEntryWithMedia(raw, storageUrl) {
4364
+ return {
4365
+ ...mapEntry(raw),
4366
+ contentJson: normalizeContentMedia(
4367
+ raw.content_json ?? {},
4368
+ storageUrl
4369
+ ),
4370
+ resolvedFields: normalizeContentMedia(
4371
+ raw.resolved_fields ?? {},
4372
+ storageUrl
4373
+ )
4374
+ };
4375
+ }
4376
+ function mapProductContentBlock(raw, storageUrl) {
4377
+ return {
4378
+ id: raw.id,
4379
+ productId: raw.product_id,
4380
+ locale: raw.locale,
4381
+ contentJson: normalizeContentMedia(
4382
+ raw.content_json ?? {},
4383
+ storageUrl
4384
+ ),
4385
+ resolvedFields: normalizeContentMedia(
4386
+ raw.resolved_fields ?? {},
4387
+ storageUrl
4388
+ ),
4389
+ sortOrder: raw.sort_order,
4390
+ updatedAt: raw.updated_at,
4391
+ contentType: {
4392
+ id: raw.content_type.id,
4393
+ key: raw.content_type.key,
4394
+ name: raw.content_type.name,
4395
+ kind: raw.content_type.kind
4396
+ }
4397
+ };
4398
+ }
4399
+ function createContentModule(graphqlUrl, getHeaders, getContext, storageUrl) {
4400
+ return {
4401
+ async getByKey(key, opts) {
4402
+ const ctx = getContext();
4403
+ const data = await executeGraphQL(
4404
+ graphqlUrl,
4405
+ WEBSITE_GET_CONTENT,
4406
+ { ...baseVariables(ctx, opts), key },
4407
+ getHeaders
4408
+ );
4409
+ return chooseOne(data, storageUrl);
4410
+ },
4411
+ async getByCategory(categoryKey, opts) {
4412
+ const ctx = getContext();
4413
+ const data = await executeGraphQL(
4414
+ graphqlUrl,
4415
+ WEBSITE_GET_CONTENT,
4416
+ { ...baseVariables(ctx, opts), categoryKey },
4417
+ getHeaders
4418
+ );
4419
+ return chooseMany(data, storageUrl);
4420
+ },
4421
+ async getByTag(tag, opts) {
4422
+ const ctx = getContext();
4423
+ const data = await executeGraphQL(
4424
+ graphqlUrl,
4425
+ WEBSITE_GET_CONTENT,
4426
+ { ...baseVariables(ctx, opts), tag },
4427
+ getHeaders
4428
+ );
4429
+ return chooseMany(data, storageUrl);
4430
+ },
4431
+ async getForProduct(productId, opts) {
4432
+ const ctx = getContext();
4433
+ const data = await executeGraphQL(
4434
+ graphqlUrl,
4435
+ WEBSITE_GET_PRODUCT_CONTENT,
4436
+ {
4437
+ websiteId: ctx.websiteId,
4438
+ productId,
4439
+ locale: opts?.locale ?? DEFAULT_LOCALE
4440
+ },
4441
+ getHeaders
4442
+ );
4443
+ if (!data.result?.success) return [];
4444
+ return (data.result.blocks ?? []).map(
4445
+ (block) => mapProductContentBlock(block, storageUrl)
4446
+ );
4447
+ }
4448
+ };
4449
+ }
4450
+
4451
+ // libs/sdk/src/modules/orders.ts
4452
+ function mapOrderItem(raw) {
4453
+ return {
4454
+ id: raw.id,
4455
+ productVariantId: raw.product_variant_id,
4456
+ quantity: raw.quantity,
4457
+ productVariant: {
4458
+ sku: raw.product_variant.sku,
4459
+ product: raw.product_variant.product
4460
+ }
4461
+ };
4462
+ }
4463
+ function mapOrder(raw) {
4464
+ return {
4465
+ id: raw.id,
4466
+ orderNumber: raw.order_number,
4467
+ status: raw.status,
4468
+ fulfillmentFamily: raw.fulfillment_family,
4469
+ discount: raw.discount,
4470
+ tax: raw.tax,
4471
+ subtotal: raw.total_without_tax,
4472
+ total: raw.total_with_tax,
4473
+ totalWithDiscount: raw.total_with_discount,
4474
+ items: raw.order_product_variants.map(mapOrderItem),
4475
+ createdAt: raw.created_at,
4476
+ updatedAt: raw.updated_at
4477
+ };
4478
+ }
4479
+ function mapPublicOrder(raw) {
4480
+ return {
4481
+ orderId: raw.order_id,
4482
+ orderNumber: raw.order_number,
4483
+ status: raw.status,
4484
+ paymentStatus: raw.payment_status,
4485
+ fulfillmentFamily: raw.fulfillment_family,
4486
+ delivery: {
4487
+ fulfillmentFamily: raw.delivery.fulfillment_family,
4488
+ shipping: raw.delivery.shipping ? {
4489
+ label: raw.delivery.shipping.label,
4490
+ amount: raw.delivery.shipping.amount,
4491
+ methodType: raw.delivery.shipping.method_type,
4492
+ collectionMode: raw.delivery.shipping.collection_mode,
4493
+ totalPolicy: raw.delivery.shipping.total_policy,
4494
+ address: raw.delivery.shipping.address
4495
+ } : null,
4496
+ pickup: raw.delivery.pickup
4497
+ },
4498
+ payment: {
4499
+ mode: raw.payment.mode,
4500
+ label: raw.payment.label,
4501
+ method: raw.payment.method ? {
4502
+ id: raw.payment.method.id,
4503
+ label: raw.payment.method.label,
4504
+ paymentMethodType: raw.payment.method.payment_method_type,
4505
+ gatewayCode: raw.payment.method.gateway_code,
4506
+ requiresPaymentSession: raw.payment.method.requires_payment_session
4507
+ } : null,
4508
+ initialPayment: raw.payment.initial_payment ? {
4509
+ amount: raw.payment.initial_payment.amount,
4510
+ paymentMethodId: raw.payment.initial_payment.payment_method_id,
4511
+ methodLabel: raw.payment.initial_payment.method_label,
4512
+ paymentMethodType: raw.payment.initial_payment.payment_method_type,
4513
+ gatewayCode: raw.payment.initial_payment.gateway_code,
4514
+ requiresPaymentSession: raw.payment.initial_payment.requires_payment_session
4515
+ } : null,
4516
+ requiresPaymentSession: raw.payment.requires_payment_session,
4517
+ nextAction: raw.payment.next_action,
4518
+ session: raw.payment.session ? {
4519
+ id: raw.payment.session.id,
4520
+ gatewayCode: raw.payment.session.gateway_code,
4521
+ integrationMode: raw.payment.session.integration_mode,
4522
+ status: raw.payment.session.status,
4523
+ reference: raw.payment.session.reference,
4524
+ amount: raw.payment.session.amount,
4525
+ currency: raw.payment.session.currency,
4526
+ gatewayTransactionId: raw.payment.session.gateway_transaction_id,
4527
+ errorMessage: raw.payment.session.error_message,
4528
+ expiresAt: raw.payment.session.expires_at,
4529
+ createdAt: raw.payment.session.created_at,
4530
+ updatedAt: raw.payment.session.updated_at
4531
+ } : null
4532
+ },
4533
+ totals: {
4534
+ subtotal: raw.totals.subtotal,
4535
+ tax: raw.totals.tax,
4536
+ discount: raw.totals.discount,
4537
+ total: raw.totals.total,
4538
+ totalWithDiscount: raw.totals.total_with_discount
4539
+ },
4540
+ items: raw.items.map((item) => ({
4541
+ id: item.id,
4542
+ productVariantId: item.product_variant_id,
4543
+ sku: item.sku,
4544
+ name: item.name,
4545
+ imageFileId: item.image_file_id,
4546
+ quantity: item.quantity,
4547
+ unitPrice: item.unit_price,
4548
+ lineTotal: item.line_total
4549
+ })),
4550
+ nextSteps: raw.next_steps,
4551
+ createdAt: raw.created_at,
4552
+ updatedAt: raw.updated_at
4553
+ };
4554
+ }
4555
+ function createOrdersModule(graphqlUrl, getHeaders, getContext) {
4556
+ async function requireAuth() {
4557
+ const headers = await getHeaders();
4558
+ if (!headers.Authorization) {
4559
+ throw new AuthError("You must be logged in to view orders");
4560
+ }
4561
+ return headers;
4562
+ }
4563
+ async function fetchPublicOrder(input) {
4564
+ const context = getContext();
4565
+ const data = await executeGraphQL(
4566
+ graphqlUrl,
4567
+ GET_PUBLIC_ORDER,
4568
+ {
4569
+ websiteId: context.websiteId,
4570
+ orderId: input.orderId,
4571
+ token: input.token
4572
+ },
4573
+ getHeaders
4574
+ );
4575
+ const result = data.websiteGetPublicOrder;
4576
+ if (!result.success) {
4577
+ if (result.errors?.includes("ORDER_NOT_FOUND")) return null;
4578
+ throw new CheckoutError(result.errors ?? ["PUBLIC_ORDER_FAILED"]);
4579
+ }
4580
+ return result.order ? mapPublicOrder(result.order) : null;
4581
+ }
4582
+ return {
4583
+ async list(opts) {
4584
+ const headers = await requireAuth();
4585
+ const data = await executeGraphQL(
4586
+ graphqlUrl,
4587
+ GET_ORDERS,
4588
+ {
4589
+ limit: opts?.limit ?? 20,
4590
+ offset: opts?.offset ?? 0
4591
+ },
4592
+ headers
4593
+ );
4594
+ return (data.orders ?? []).map(mapOrder);
4595
+ },
4596
+ async get(orderId) {
4597
+ const headers = await requireAuth();
4598
+ const data = await executeGraphQL(
4599
+ graphqlUrl,
4600
+ GET_ORDER_BY_PK,
4601
+ { orderId },
4602
+ headers
4603
+ );
4604
+ const order = data.orders?.[0];
4605
+ return order ? mapOrder(order) : null;
4606
+ },
4607
+ async getPublicOrder(input) {
4608
+ return fetchPublicOrder(input);
4609
+ },
4610
+ async waitForPayment(input) {
4611
+ const intervalMs = Math.max(500, input.intervalMs ?? 1500);
4612
+ const timeoutMs = Math.max(intervalMs, input.timeoutMs ?? 12e4);
4613
+ const deadline = Date.now() + timeoutMs;
4614
+ while (Date.now() <= deadline) {
4615
+ const order = await fetchPublicOrder(input);
4616
+ if (!order) {
4617
+ throw new CheckoutError(["ORDER_NOT_FOUND"]);
4618
+ }
4619
+ const sessionStatus = order.payment.session?.status ?? null;
4620
+ if (order.paymentStatus === "PAID" || sessionStatus === "approved" || ["declined", "error", "expired", "cancelled"].includes(
4621
+ sessionStatus ?? ""
4622
+ )) {
4623
+ return order;
4624
+ }
4625
+ await wait(intervalMs);
4626
+ }
4627
+ throw new CheckoutError(["PAYMENT_STATUS_TIMEOUT"]);
4628
+ }
4629
+ };
4630
+ }
4631
+ function wait(ms) {
4632
+ return new Promise((resolve) => {
4633
+ setTimeout(resolve, ms);
4634
+ });
4635
+ }
4636
+
4637
+ // libs/sdk/src/modules/profile.ts
4638
+ function hasCanonicalLocation(address) {
4639
+ return Boolean(
4640
+ address.department_code && address.municipality_code && address.geo_department?.name && address.geo_municipality?.name
4641
+ );
4642
+ }
4643
+ function mapProfile(raw) {
4644
+ const primaryAddress = raw.party.shipping_addresses?.[0];
4645
+ return {
4646
+ id: raw.id,
4647
+ name: raw.party.first_name,
4648
+ lastname: raw.party.last_name,
4649
+ email: raw.party.email,
4650
+ cellphone: raw.party.phone_e164,
4651
+ phone: raw.party.phone_national_number,
4652
+ address: primaryAddress?.address ?? raw.party.address,
4653
+ city: primaryAddress?.geo_municipality?.name ?? raw.party.geo_municipality?.name ?? null,
4654
+ state: primaryAddress?.geo_department?.name ?? raw.party.geo_department?.name ?? null,
4655
+ country: primaryAddress?.geo_country?.name ?? raw.party.geo_country?.name ?? raw.party.country_code ?? null,
4656
+ birthday: raw.party.birthdate,
4657
+ companyName: raw.party.legal_name ?? raw.party.commercial_name
4658
+ };
4659
+ }
4660
+ function mapProfileAddresses(raw) {
4661
+ const party = raw.party;
4662
+ const recipientName = [party.first_name, party.last_name].filter(Boolean).join(" ") || party.display_name;
4663
+ const addresses = [];
4664
+ const shippingAddresses = party.shipping_addresses.filter(hasCanonicalLocation);
4665
+ const preferredShippingAddress = shippingAddresses.find((address) => address.is_primary) ?? shippingAddresses[0];
4666
+ if (party.address?.trim() && hasCanonicalLocation(party)) {
4667
+ addresses.push({
4668
+ id: raw.party_id,
4669
+ type: "PRIMARY",
4670
+ label: "Direcci\xF3n principal",
4671
+ isPrimary: !preferredShippingAddress,
4672
+ recipientName,
4673
+ cellphone: party.phone_e164 ?? party.phone_national_number,
4674
+ line1: party.address,
4675
+ line2: party.address_complement,
4676
+ notes: null,
4677
+ countryCode: party.country_code ?? "CO",
4678
+ countryName: party.geo_country?.name ?? party.country_code ?? "CO",
4679
+ departmentId: party.department_code,
4680
+ departmentCode: party.department_code,
4681
+ departmentName: party.geo_department.name,
4682
+ municipalityId: party.municipality_code,
4683
+ municipalityCode: party.municipality_code,
4684
+ municipalityName: party.geo_municipality.name
4685
+ });
4686
+ }
4687
+ addresses.push(
4688
+ ...shippingAddresses.map((address) => ({
4689
+ id: address.id,
4690
+ type: "SHIPPING",
4691
+ label: address.label,
4692
+ isPrimary: address.id === preferredShippingAddress?.id,
4693
+ recipientName: address.recipient_name,
4694
+ cellphone: address.phone_e164,
4695
+ line1: address.address,
4696
+ line2: address.address_complement,
4697
+ notes: address.notes,
4698
+ countryCode: address.country_code,
4699
+ countryName: address.geo_country?.name ?? address.country_code,
4700
+ departmentId: address.department_code,
4701
+ departmentCode: address.department_code,
4702
+ departmentName: address.geo_department.name,
4703
+ municipalityId: address.municipality_code,
4704
+ municipalityCode: address.municipality_code,
4705
+ municipalityName: address.geo_municipality.name
4706
+ }))
4707
+ );
4708
+ return addresses;
4709
+ }
4710
+ function mapProfileUpdate(data) {
4711
+ return {
4712
+ display_name: [data.name, data.lastname].filter(Boolean).join(" ") || void 0,
4713
+ first_name: data.name,
4714
+ last_name: data.lastname,
4715
+ phone_e164: data.cellphone,
4716
+ phone_national_number: data.phone,
4717
+ address: data.address,
4718
+ address_complement: data.addressComplement,
4719
+ country_code: data.countryCode,
4720
+ department_code: data.departmentId,
4721
+ municipality_code: data.municipalityId,
4722
+ birthdate: data.birthday
4723
+ };
4724
+ }
4725
+ function createProfileModule(graphqlUrl, getHeaders) {
4726
+ async function requireAuth() {
4727
+ const headers = await getHeaders();
4728
+ if (!headers.Authorization) {
4729
+ throw new AuthError("You must be logged in to access your profile");
4730
+ }
4731
+ return headers;
4732
+ }
4733
+ return {
4734
+ async get() {
4735
+ const headers = await requireAuth();
4736
+ const data = await executeGraphQL(
4737
+ graphqlUrl,
4738
+ GET_PROFILE,
4739
+ {},
4740
+ headers
4741
+ );
4742
+ const client = data.clients?.[0];
4743
+ if (!client) {
4744
+ throw new AuthError("Customer profile not found");
4745
+ }
4746
+ return mapProfile(client);
4747
+ },
4748
+ async getAddresses() {
4749
+ const headers = await requireAuth();
4750
+ const data = await executeGraphQL(
4751
+ graphqlUrl,
4752
+ GET_PROFILE_ADDRESSES,
4753
+ {},
4754
+ headers
4755
+ );
4756
+ const client = data.clients?.[0];
4757
+ if (!client) {
4758
+ throw new AuthError("Customer profile not found");
4759
+ }
4760
+ return mapProfileAddresses(client);
4761
+ },
4762
+ async update(updateData) {
4763
+ const headers = await requireAuth();
4764
+ const profileData = await executeGraphQL(
4765
+ graphqlUrl,
4766
+ GET_PROFILE,
4767
+ {},
4768
+ headers
4769
+ );
4770
+ const client = profileData.clients?.[0];
4771
+ if (!client) {
4772
+ throw new AuthError("Customer profile not found");
4773
+ }
4774
+ const data = await executeGraphQL(
4775
+ graphqlUrl,
4776
+ UPDATE_PROFILE,
4777
+ { partyId: client.party_id, data: mapProfileUpdate(updateData) },
4778
+ headers
4779
+ );
4780
+ return mapProfile({
4781
+ id: client.id,
4782
+ party_id: client.party_id,
4783
+ party: data.update_business_parties_by_pk
4784
+ });
4785
+ }
4786
+ };
4787
+ }
4788
+
4789
+ // libs/sdk/src/modules/website.ts
4790
+ function mapWebsite(raw) {
4791
+ return {
4792
+ websiteId: raw.id,
4793
+ companyId: raw.company_id,
4794
+ chainId: raw.chain_id,
4795
+ name: raw.name,
4796
+ slug: raw.slug,
4797
+ domain: raw.domain,
4798
+ config: raw.config
4799
+ };
4800
+ }
4801
+ async function resolveWebsite(graphqlUrl, slug, headers) {
4802
+ if (!slug.trim()) {
4803
+ throw new WebsiteError(
4804
+ "websiteSlug is required",
4805
+ "INVALID_CONFIG"
4806
+ );
4807
+ }
4808
+ const data = await executeGraphQL(
4809
+ graphqlUrl,
4810
+ RESOLVE_WEBSITE_BY_SLUG,
4811
+ { slug },
4812
+ headers
4813
+ );
4814
+ if (!data.websites || data.websites.length === 0) {
4815
+ throw new WebsiteError(
4816
+ `No active website found with slug "${slug}"`,
4817
+ "WEBSITE_NOT_FOUND"
4818
+ );
4819
+ }
4820
+ return mapWebsite(data.websites[0]);
4821
+ }
4822
+
4823
+ // libs/sdk/src/client.ts
4824
+ function normalizeApiUrl(apiUrl) {
4825
+ return apiUrl.replace(/\/+$/, "");
4826
+ }
4827
+ function createBacanoClient(config) {
4828
+ if (!config.apiUrl)
4829
+ throw new WebsiteError("apiUrl is required", "INVALID_CONFIG");
4830
+ if (!config.websiteSlug?.trim())
4831
+ throw new WebsiteError("websiteSlug is required", "INVALID_CONFIG");
4832
+ const apiUrl = normalizeApiUrl(config.apiUrl);
4833
+ const graphqlUrl = `${apiUrl}/api/v1/website/graphql`;
4834
+ const storageUrl = `${apiUrl}/storage/v1`;
4835
+ let context = null;
4836
+ function getContext() {
4837
+ if (!context) throw new NotInitializedError();
4838
+ return context;
4839
+ }
4840
+ const getHeaders = createRequestHeadersProvider(
4841
+ config.websiteSlug,
4842
+ config.getAccessToken
4843
+ );
4844
+ const getWebsiteHeaders = createRequestHeadersProvider(config.websiteSlug);
4845
+ const catalogModule = createCatalogModule(
4846
+ graphqlUrl,
4847
+ getHeaders,
4848
+ getContext,
4849
+ storageUrl
4850
+ );
4851
+ const availabilityModule = createAvailabilityModule(
4852
+ graphqlUrl,
4853
+ getHeaders,
4854
+ getContext
4855
+ );
4856
+ const cartSessionStorage = createCartSessionStorage(
4857
+ config.tokenStorage ?? "localStorage",
4858
+ () => getContext().slug
4859
+ );
4860
+ const cartModule = createCartModule(
4861
+ graphqlUrl,
4862
+ getHeaders,
4863
+ getContext,
4864
+ cartSessionStorage
4865
+ );
4866
+ const checkoutModule = createCheckoutModule(
4867
+ graphqlUrl,
4868
+ getHeaders,
4869
+ getContext,
4870
+ cartSessionStorage
4871
+ );
4872
+ const ordersModule = createOrdersModule(graphqlUrl, getHeaders, getContext);
4873
+ const profileModule = createProfileModule(graphqlUrl, getHeaders);
4874
+ const contentModule = createContentModule(
4875
+ graphqlUrl,
4876
+ getHeaders,
4877
+ getContext,
4878
+ storageUrl
4879
+ );
4880
+ return {
4881
+ async init() {
4882
+ context = await resolveWebsite(
4883
+ graphqlUrl,
4884
+ config.websiteSlug,
4885
+ getWebsiteHeaders
4886
+ );
4887
+ },
4888
+ getContext,
4889
+ auth: {
4890
+ async getAccessToken() {
4891
+ return config.getAccessToken ? await config.getAccessToken() : null;
4892
+ },
4893
+ async isAuthenticated() {
4894
+ return Boolean(
4895
+ config.getAccessToken ? await config.getAccessToken() : null
4896
+ );
4897
+ }
4898
+ },
4899
+ catalog: {
4900
+ getCatalogPage: catalogModule.getCatalogPage.bind(catalogModule),
4901
+ getProductSeoEntries: catalogModule.getProductSeoEntries.bind(catalogModule),
4902
+ getProductRecommendations: catalogModule.getProductRecommendations.bind(catalogModule),
4903
+ getProducts: catalogModule.getProducts.bind(catalogModule),
4904
+ getProduct: catalogModule.getProduct.bind(catalogModule),
4905
+ getProductBySlug: catalogModule.getProductBySlug.bind(catalogModule),
4906
+ getCategories: catalogModule.getCategories.bind(catalogModule),
4907
+ getCategoryList: catalogModule.getCategoryList.bind(catalogModule),
4908
+ getAttributeList: catalogModule.getAttributeList.bind(catalogModule),
4909
+ getBrands: catalogModule.getBrands.bind(catalogModule),
4910
+ getProductFilters: catalogModule.getProductFilters.bind(catalogModule),
4911
+ getSearchSuggestions: catalogModule.getSearchSuggestions.bind(catalogModule),
4912
+ checkAvailability: availabilityModule.checkAvailability.bind(availabilityModule)
4913
+ },
4914
+ content: {
4915
+ getByKey: contentModule.getByKey.bind(contentModule),
4916
+ getByCategory: contentModule.getByCategory.bind(contentModule),
4917
+ getByTag: contentModule.getByTag.bind(contentModule),
4918
+ getForProduct: contentModule.getForProduct.bind(contentModule)
4919
+ },
4920
+ cart: {
4921
+ getOrCreate: cartModule.getOrCreate.bind(cartModule),
4922
+ startCheckout: cartModule.startCheckout.bind(cartModule),
4923
+ get: cartModule.get.bind(cartModule),
4924
+ setItem: cartModule.setItem.bind(cartModule),
4925
+ addItem: cartModule.addItem.bind(cartModule),
4926
+ updateItem: cartModule.updateItem.bind(cartModule),
4927
+ removeItem: cartModule.removeItem.bind(cartModule)
4928
+ },
4929
+ checkout: {
4930
+ getLocationOptions: checkoutModule.getLocationOptions.bind(checkoutModule),
4931
+ getDeliveryOptions: checkoutModule.getDeliveryOptions.bind(checkoutModule),
4932
+ getShippingQuotes: checkoutModule.getShippingQuotes.bind(checkoutModule),
4933
+ getShippingPolicy: checkoutModule.getShippingPolicy.bind(checkoutModule),
4934
+ getFreeShippingProgress: checkoutModule.getFreeShippingProgress.bind(checkoutModule),
4935
+ getPaymentMethods: checkoutModule.getPaymentMethods.bind(checkoutModule),
4936
+ getPaymentOptions: checkoutModule.getPaymentOptions.bind(checkoutModule),
4937
+ validateCoupon: checkoutModule.validateCoupon.bind(checkoutModule),
4938
+ applyCoupon: checkoutModule.applyCoupon.bind(checkoutModule),
4939
+ removeCoupon: checkoutModule.removeCoupon.bind(checkoutModule),
4940
+ submit: checkoutModule.submit.bind(checkoutModule),
4941
+ createPaymentSession: checkoutModule.createPaymentSession.bind(checkoutModule),
4942
+ reconcilePaymentSession: checkoutModule.reconcilePaymentSession.bind(checkoutModule)
4943
+ },
4944
+ orders: {
4945
+ list: ordersModule.list.bind(ordersModule),
4946
+ get: ordersModule.get.bind(ordersModule),
4947
+ getPublicOrder: ordersModule.getPublicOrder.bind(ordersModule),
4948
+ waitForPayment: ordersModule.waitForPayment.bind(ordersModule)
4949
+ },
4950
+ profile: {
4951
+ get: profileModule.get.bind(profileModule),
4952
+ getAddresses: profileModule.getAddresses.bind(profileModule),
4953
+ update: profileModule.update.bind(profileModule)
4954
+ }
4955
+ };
4956
+ }