brainerce 1.15.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4447 -4334
- package/dist/index.d.mts +270 -15
- package/dist/index.d.ts +270 -15
- package/dist/index.js +273 -34
- package/dist/index.mjs +272 -34
- package/package.json +76 -76
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ __export(index_exports, {
|
|
|
41
41
|
getCartTotals: () => getCartTotals,
|
|
42
42
|
getDescriptionContent: () => getDescriptionContent,
|
|
43
43
|
getPriceDisplay: () => formatPrice,
|
|
44
|
+
getProductCustomizationFields: () => getProductCustomizationFields,
|
|
44
45
|
getProductMetafield: () => getProductMetafield,
|
|
45
46
|
getProductMetafieldValue: () => getProductMetafieldValue,
|
|
46
47
|
getProductMetafieldsByType: () => getProductMetafieldsByType,
|
|
@@ -241,6 +242,41 @@ var BrainerceClient = class {
|
|
|
241
242
|
this.onAuthError = options.onAuthError;
|
|
242
243
|
this.hydrateSessionCart();
|
|
243
244
|
}
|
|
245
|
+
// -------------------- Locale --------------------
|
|
246
|
+
/**
|
|
247
|
+
* Set the active locale for content translation.
|
|
248
|
+
* When set, all content endpoints (products, categories, brands) will return
|
|
249
|
+
* translated content for this locale, falling back to the store's default language.
|
|
250
|
+
*
|
|
251
|
+
* @param locale - Locale code (e.g., "he", "es", "fr") or undefined to clear
|
|
252
|
+
*/
|
|
253
|
+
setLocale(locale) {
|
|
254
|
+
this.locale = locale;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get the currently active locale.
|
|
258
|
+
*/
|
|
259
|
+
getLocale() {
|
|
260
|
+
return this.locale;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get the supported locales for this store.
|
|
264
|
+
* Fetches store info and returns the i18n config.
|
|
265
|
+
* Returns `[storeLanguage]` if multi-language is not enabled.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```typescript
|
|
269
|
+
* const locales = await client.getSupportedLocales();
|
|
270
|
+
* // ["en", "he", "es"]
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
async getSupportedLocales() {
|
|
274
|
+
const info = await this.getStoreInfo();
|
|
275
|
+
if (info.i18n?.enabled && info.i18n.supportedLocales.length > 0) {
|
|
276
|
+
return info.i18n.supportedLocales;
|
|
277
|
+
}
|
|
278
|
+
return [info.language];
|
|
279
|
+
}
|
|
244
280
|
withGuards(result, type) {
|
|
245
281
|
if (!isDevGuardsEnabled()) return result;
|
|
246
282
|
if (result && typeof result.then === "function") {
|
|
@@ -350,6 +386,9 @@ var BrainerceClient = class {
|
|
|
350
386
|
if (this.origin) {
|
|
351
387
|
headers["Origin"] = this.origin;
|
|
352
388
|
}
|
|
389
|
+
if (this.locale) {
|
|
390
|
+
headers["Accept-Language"] = this.locale;
|
|
391
|
+
}
|
|
353
392
|
const response = await fetch(url.toString(), {
|
|
354
393
|
method,
|
|
355
394
|
headers,
|
|
@@ -385,7 +424,7 @@ var BrainerceClient = class {
|
|
|
385
424
|
/**
|
|
386
425
|
* Make a request to the Vibe-Coded API (public, uses connectionId)
|
|
387
426
|
*/
|
|
388
|
-
async vibeCodedRequest(method, path, body, queryParams) {
|
|
427
|
+
async vibeCodedRequest(method, path, body, queryParams, headerOverrides) {
|
|
389
428
|
if (!this.connectionId) {
|
|
390
429
|
throw new BrainerceError("connectionId is required for vibe-coded requests", 400);
|
|
391
430
|
}
|
|
@@ -408,6 +447,12 @@ var BrainerceClient = class {
|
|
|
408
447
|
if (this.origin) {
|
|
409
448
|
headers["Origin"] = this.origin;
|
|
410
449
|
}
|
|
450
|
+
if (this.locale) {
|
|
451
|
+
headers["Accept-Language"] = this.locale;
|
|
452
|
+
}
|
|
453
|
+
if (headerOverrides) {
|
|
454
|
+
Object.assign(headers, headerOverrides);
|
|
455
|
+
}
|
|
411
456
|
if (this.proxyMode && method !== "GET") {
|
|
412
457
|
headers["X-Requested-With"] = "brainerce";
|
|
413
458
|
}
|
|
@@ -456,7 +501,7 @@ var BrainerceClient = class {
|
|
|
456
501
|
/**
|
|
457
502
|
* Make a request to the Storefront API (public, uses storeId)
|
|
458
503
|
*/
|
|
459
|
-
async storefrontRequest(method, path, body, queryParams) {
|
|
504
|
+
async storefrontRequest(method, path, body, queryParams, headerOverrides) {
|
|
460
505
|
if (!this.storeId) {
|
|
461
506
|
throw new BrainerceError("storeId is required for storefront requests", 400);
|
|
462
507
|
}
|
|
@@ -479,6 +524,12 @@ var BrainerceClient = class {
|
|
|
479
524
|
if (this.origin) {
|
|
480
525
|
headers["Origin"] = this.origin;
|
|
481
526
|
}
|
|
527
|
+
if (this.locale) {
|
|
528
|
+
headers["Accept-Language"] = this.locale;
|
|
529
|
+
}
|
|
530
|
+
if (headerOverrides) {
|
|
531
|
+
Object.assign(headers, headerOverrides);
|
|
532
|
+
}
|
|
482
533
|
if (this.customerToken) {
|
|
483
534
|
headers["Authorization"] = `Bearer ${this.customerToken}`;
|
|
484
535
|
}
|
|
@@ -610,12 +661,25 @@ var BrainerceClient = class {
|
|
|
610
661
|
* Get a single product by ID
|
|
611
662
|
* Works in vibe-coded, storefront (public), and admin mode
|
|
612
663
|
*/
|
|
613
|
-
async getProduct(productId) {
|
|
664
|
+
async getProduct(productId, options) {
|
|
665
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
614
666
|
if (this.isVibeCodedMode()) {
|
|
615
|
-
return this.vibeCodedRequest(
|
|
667
|
+
return this.vibeCodedRequest(
|
|
668
|
+
"GET",
|
|
669
|
+
`/products/${productId}`,
|
|
670
|
+
void 0,
|
|
671
|
+
void 0,
|
|
672
|
+
headerOverrides
|
|
673
|
+
);
|
|
616
674
|
}
|
|
617
675
|
if (this.storeId && !this.apiKey) {
|
|
618
|
-
return this.storefrontRequest(
|
|
676
|
+
return this.storefrontRequest(
|
|
677
|
+
"GET",
|
|
678
|
+
`/products/${productId}`,
|
|
679
|
+
void 0,
|
|
680
|
+
void 0,
|
|
681
|
+
headerOverrides
|
|
682
|
+
);
|
|
619
683
|
}
|
|
620
684
|
return this.adminRequest("GET", `/api/v1/products/${productId}`);
|
|
621
685
|
}
|
|
@@ -629,12 +693,25 @@ var BrainerceClient = class {
|
|
|
629
693
|
* const product = await client.getProductBySlug('awesome-product-name');
|
|
630
694
|
* ```
|
|
631
695
|
*/
|
|
632
|
-
async getProductBySlug(slug) {
|
|
696
|
+
async getProductBySlug(slug, options) {
|
|
697
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
633
698
|
if (this.isVibeCodedMode()) {
|
|
634
|
-
return this.vibeCodedRequest(
|
|
699
|
+
return this.vibeCodedRequest(
|
|
700
|
+
"GET",
|
|
701
|
+
`/products/slug/${slug}`,
|
|
702
|
+
void 0,
|
|
703
|
+
void 0,
|
|
704
|
+
headerOverrides
|
|
705
|
+
);
|
|
635
706
|
}
|
|
636
707
|
if (this.storeId && !this.apiKey) {
|
|
637
|
-
return this.storefrontRequest(
|
|
708
|
+
return this.storefrontRequest(
|
|
709
|
+
"GET",
|
|
710
|
+
`/products/slug/${slug}`,
|
|
711
|
+
void 0,
|
|
712
|
+
void 0,
|
|
713
|
+
headerOverrides
|
|
714
|
+
);
|
|
638
715
|
}
|
|
639
716
|
return this.adminRequest("GET", `/api/v1/products/by-slug/${slug}`);
|
|
640
717
|
}
|
|
@@ -648,9 +725,10 @@ var BrainerceClient = class {
|
|
|
648
725
|
* // categories is a tree structure with children
|
|
649
726
|
* ```
|
|
650
727
|
*/
|
|
651
|
-
async getCategories() {
|
|
728
|
+
async getCategories(options) {
|
|
729
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
652
730
|
if (this.isVibeCodedMode()) {
|
|
653
|
-
return this.vibeCodedRequest("GET", "/categories");
|
|
731
|
+
return this.vibeCodedRequest("GET", "/categories", void 0, void 0, headerOverrides);
|
|
654
732
|
}
|
|
655
733
|
throw new BrainerceError("getCategories is only available in vibe-coded mode", 400);
|
|
656
734
|
}
|
|
@@ -664,9 +742,10 @@ var BrainerceClient = class {
|
|
|
664
742
|
* // Use brand IDs in getProducts({ brands: ['brand_id'] })
|
|
665
743
|
* ```
|
|
666
744
|
*/
|
|
667
|
-
async getBrands() {
|
|
745
|
+
async getBrands(options) {
|
|
746
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
668
747
|
if (this.isVibeCodedMode()) {
|
|
669
|
-
return this.vibeCodedRequest("GET", "/brands");
|
|
748
|
+
return this.vibeCodedRequest("GET", "/brands", void 0, void 0, headerOverrides);
|
|
670
749
|
}
|
|
671
750
|
throw new BrainerceError("getBrands is only available in vibe-coded mode", 400);
|
|
672
751
|
}
|
|
@@ -680,9 +759,10 @@ var BrainerceClient = class {
|
|
|
680
759
|
* // Use tag IDs in getProducts({ tags: ['tag_id'] })
|
|
681
760
|
* ```
|
|
682
761
|
*/
|
|
683
|
-
async getTags() {
|
|
762
|
+
async getTags(options) {
|
|
763
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
684
764
|
if (this.isVibeCodedMode()) {
|
|
685
|
-
return this.vibeCodedRequest("GET", "/tags");
|
|
765
|
+
return this.vibeCodedRequest("GET", "/tags", void 0, void 0, headerOverrides);
|
|
686
766
|
}
|
|
687
767
|
throw new BrainerceError("getTags is only available in vibe-coded mode", 400);
|
|
688
768
|
}
|
|
@@ -706,6 +786,22 @@ var BrainerceClient = class {
|
|
|
706
786
|
* const suggestions = await client.getSearchSuggestions('dress', 3);
|
|
707
787
|
* ```
|
|
708
788
|
*/
|
|
789
|
+
/**
|
|
790
|
+
* Get locale alternates for a product (for SEO hreflang tags).
|
|
791
|
+
* Returns the slug for each available locale.
|
|
792
|
+
*
|
|
793
|
+
* @example
|
|
794
|
+
* ```typescript
|
|
795
|
+
* const { alternates } = await client.getProductAlternates('product_id');
|
|
796
|
+
* // alternates = [{ locale: "en", slug: "running-shoes" }, { locale: "he", slug: "נעלי-ריצה" }]
|
|
797
|
+
* ```
|
|
798
|
+
*/
|
|
799
|
+
async getProductAlternates(productId) {
|
|
800
|
+
if (this.storeId && !this.apiKey) {
|
|
801
|
+
return this.storefrontRequest("GET", `/products/${productId}/alternates`);
|
|
802
|
+
}
|
|
803
|
+
throw new BrainerceError("getProductAlternates is only available in storefront mode", 400);
|
|
804
|
+
}
|
|
709
805
|
async getSearchSuggestions(query, limit) {
|
|
710
806
|
if (!query || query.trim().length === 0) {
|
|
711
807
|
return { products: [], categories: [] };
|
|
@@ -2372,17 +2468,21 @@ var BrainerceClient = class {
|
|
|
2372
2468
|
* ```
|
|
2373
2469
|
*/
|
|
2374
2470
|
async getProductRecommendations(productId, type) {
|
|
2375
|
-
const
|
|
2471
|
+
const queryParams = type ? { type } : void 0;
|
|
2376
2472
|
if (this.isVibeCodedMode()) {
|
|
2377
2473
|
return this.vibeCodedRequest(
|
|
2378
2474
|
"GET",
|
|
2379
|
-
`/products/${productId}/recommendations
|
|
2475
|
+
`/products/${productId}/recommendations`,
|
|
2476
|
+
void 0,
|
|
2477
|
+
queryParams
|
|
2380
2478
|
);
|
|
2381
2479
|
}
|
|
2382
2480
|
if (this.storeId && !this.apiKey) {
|
|
2383
2481
|
return this.storefrontRequest(
|
|
2384
2482
|
"GET",
|
|
2385
|
-
`/products/${productId}/recommendations
|
|
2483
|
+
`/products/${productId}/recommendations`,
|
|
2484
|
+
void 0,
|
|
2485
|
+
queryParams
|
|
2386
2486
|
);
|
|
2387
2487
|
}
|
|
2388
2488
|
throw new BrainerceError(
|
|
@@ -2406,17 +2506,21 @@ var BrainerceClient = class {
|
|
|
2406
2506
|
* ```
|
|
2407
2507
|
*/
|
|
2408
2508
|
async getCartRecommendations(cartId, limit) {
|
|
2409
|
-
const
|
|
2509
|
+
const queryParams = limit ? { limit } : void 0;
|
|
2410
2510
|
if (this.isVibeCodedMode()) {
|
|
2411
2511
|
return this.vibeCodedRequest(
|
|
2412
2512
|
"GET",
|
|
2413
|
-
`/cart/${cartId}/recommendations
|
|
2513
|
+
`/cart/${cartId}/recommendations`,
|
|
2514
|
+
void 0,
|
|
2515
|
+
queryParams
|
|
2414
2516
|
);
|
|
2415
2517
|
}
|
|
2416
2518
|
if (this.storeId && !this.apiKey) {
|
|
2417
2519
|
return this.storefrontRequest(
|
|
2418
2520
|
"GET",
|
|
2419
|
-
`/cart/${cartId}/recommendations
|
|
2521
|
+
`/cart/${cartId}/recommendations`,
|
|
2522
|
+
void 0,
|
|
2523
|
+
queryParams
|
|
2420
2524
|
);
|
|
2421
2525
|
}
|
|
2422
2526
|
throw new BrainerceError(
|
|
@@ -2492,14 +2596,16 @@ var BrainerceClient = class {
|
|
|
2492
2596
|
*
|
|
2493
2597
|
* @param cartId - Cart ID
|
|
2494
2598
|
* @param bumpConfigId - Order bump config ID
|
|
2599
|
+
* @param variantId - Optional variant ID (required when bump product has variants and no admin-locked variant)
|
|
2495
2600
|
* @returns Updated cart
|
|
2496
2601
|
*/
|
|
2497
|
-
async addOrderBump(cartId, bumpConfigId) {
|
|
2602
|
+
async addOrderBump(cartId, bumpConfigId, variantId) {
|
|
2603
|
+
const body = { bumpConfigId, ...variantId && { variantId } };
|
|
2498
2604
|
if (this.isVibeCodedMode()) {
|
|
2499
|
-
return this.vibeCodedRequest("POST", `/cart/${cartId}/bump`,
|
|
2605
|
+
return this.vibeCodedRequest("POST", `/cart/${cartId}/bump`, body);
|
|
2500
2606
|
}
|
|
2501
2607
|
if (this.storeId && !this.apiKey) {
|
|
2502
|
-
return this.storefrontRequest("POST", `/cart/${cartId}/bump`,
|
|
2608
|
+
return this.storefrontRequest("POST", `/cart/${cartId}/bump`, body);
|
|
2503
2609
|
}
|
|
2504
2610
|
throw new BrainerceError("addOrderBump() requires vibe-coded or storefront mode", 400);
|
|
2505
2611
|
}
|
|
@@ -2524,20 +2630,25 @@ var BrainerceClient = class {
|
|
|
2524
2630
|
*
|
|
2525
2631
|
* @param cartId - Cart ID
|
|
2526
2632
|
* @param bundleOfferId - Bundle offer ID
|
|
2633
|
+
* @param variantId - Optional variant ID (required when bundle product has variants and no admin-locked variant)
|
|
2527
2634
|
* @returns Updated cart
|
|
2528
2635
|
*
|
|
2529
2636
|
* @example
|
|
2530
2637
|
* ```typescript
|
|
2531
2638
|
* const { bundles } = await client.getCartBundles('cart_123');
|
|
2639
|
+
* // Simple product or locked variant:
|
|
2532
2640
|
* const cart = await client.addBundleToCart('cart_123', bundles[0].id);
|
|
2641
|
+
* // Product with variants (customer selects):
|
|
2642
|
+
* const cart = await client.addBundleToCart('cart_123', bundles[0].id, selectedVariantId);
|
|
2533
2643
|
* ```
|
|
2534
2644
|
*/
|
|
2535
|
-
async addBundleToCart(cartId, bundleOfferId) {
|
|
2645
|
+
async addBundleToCart(cartId, bundleOfferId, variantId) {
|
|
2646
|
+
const body = { bundleOfferId, ...variantId && { variantId } };
|
|
2536
2647
|
if (this.isVibeCodedMode()) {
|
|
2537
|
-
return this.vibeCodedRequest("POST", `/cart/${cartId}/bundle`,
|
|
2648
|
+
return this.vibeCodedRequest("POST", `/cart/${cartId}/bundle`, body);
|
|
2538
2649
|
}
|
|
2539
2650
|
if (this.storeId && !this.apiKey) {
|
|
2540
|
-
return this.storefrontRequest("POST", `/cart/${cartId}/bundle`,
|
|
2651
|
+
return this.storefrontRequest("POST", `/cart/${cartId}/bundle`, body);
|
|
2541
2652
|
}
|
|
2542
2653
|
throw new BrainerceError("addBundleToCart() requires vibe-coded or storefront mode", 400);
|
|
2543
2654
|
}
|
|
@@ -3459,6 +3570,67 @@ var BrainerceClient = class {
|
|
|
3459
3570
|
this.clearActiveCheckoutStorage();
|
|
3460
3571
|
return result;
|
|
3461
3572
|
}
|
|
3573
|
+
// -------------------- Checkout Custom Fields --------------------
|
|
3574
|
+
/**
|
|
3575
|
+
* Get applicable custom field definitions for a checkout.
|
|
3576
|
+
* Returns fields filtered by visibility conditions (delivery type, products in cart).
|
|
3577
|
+
* Use these to render dynamic input fields in the checkout flow.
|
|
3578
|
+
*/
|
|
3579
|
+
async getCheckoutCustomFields(checkoutId) {
|
|
3580
|
+
if (this.isVibeCodedMode()) {
|
|
3581
|
+
return this.vibeCodedRequest(
|
|
3582
|
+
"GET",
|
|
3583
|
+
`/checkout/${checkoutId}/custom-fields`
|
|
3584
|
+
);
|
|
3585
|
+
}
|
|
3586
|
+
if (this.storeId && !this.apiKey) {
|
|
3587
|
+
return this.storefrontRequest(
|
|
3588
|
+
"GET",
|
|
3589
|
+
`/checkout/${checkoutId}/custom-fields`
|
|
3590
|
+
);
|
|
3591
|
+
}
|
|
3592
|
+
return this.adminRequest(
|
|
3593
|
+
"GET",
|
|
3594
|
+
`/api/v1/checkouts/${checkoutId}/custom-fields`
|
|
3595
|
+
);
|
|
3596
|
+
}
|
|
3597
|
+
/**
|
|
3598
|
+
* Set checkout custom field values and recalculate surcharges.
|
|
3599
|
+
* The checkout total is automatically updated to include surcharges.
|
|
3600
|
+
*
|
|
3601
|
+
* @example
|
|
3602
|
+
* ```typescript
|
|
3603
|
+
* const checkout = await client.setCheckoutCustomFields(checkoutId, {
|
|
3604
|
+
* gift_wrapping: 'premium', // SELECT field
|
|
3605
|
+
* floor_number: 5, // NUMBER field
|
|
3606
|
+
* installation: true, // BOOLEAN field
|
|
3607
|
+
* });
|
|
3608
|
+
* // checkout.surchargeAmount reflects the new surcharges
|
|
3609
|
+
* // checkout.total is recalculated
|
|
3610
|
+
* ```
|
|
3611
|
+
*/
|
|
3612
|
+
async setCheckoutCustomFields(checkoutId, fields) {
|
|
3613
|
+
const data = { fields };
|
|
3614
|
+
if (this.isVibeCodedMode()) {
|
|
3615
|
+
return this.vibeCodedRequest(
|
|
3616
|
+
"PATCH",
|
|
3617
|
+
`/checkout/${checkoutId}/custom-fields`,
|
|
3618
|
+
data
|
|
3619
|
+
);
|
|
3620
|
+
}
|
|
3621
|
+
if (this.storeId && !this.apiKey) {
|
|
3622
|
+
return this.storefrontRequest(
|
|
3623
|
+
"PATCH",
|
|
3624
|
+
`/checkout/${checkoutId}/custom-fields`,
|
|
3625
|
+
data
|
|
3626
|
+
);
|
|
3627
|
+
}
|
|
3628
|
+
return this.adminRequest(
|
|
3629
|
+
"PATCH",
|
|
3630
|
+
`/api/v1/checkouts/${checkoutId}/custom-fields`,
|
|
3631
|
+
data
|
|
3632
|
+
);
|
|
3633
|
+
}
|
|
3462
3634
|
/**
|
|
3463
3635
|
* Delete a checkout session. Releases inventory reservations and removes
|
|
3464
3636
|
* payment records not yet linked to an order.
|
|
@@ -5502,6 +5674,53 @@ var BrainerceClient = class {
|
|
|
5502
5674
|
`/api/v1/products/${productId}/metafields/${definitionId}`
|
|
5503
5675
|
);
|
|
5504
5676
|
}
|
|
5677
|
+
// -------------------- Product Customization Fields (Admin) --------------------
|
|
5678
|
+
/**
|
|
5679
|
+
* Get customization fields assigned to a product.
|
|
5680
|
+
* Requires Admin mode (apiKey).
|
|
5681
|
+
*/
|
|
5682
|
+
async getProductCustomizationFields(productId) {
|
|
5683
|
+
return this.adminRequest(
|
|
5684
|
+
"GET",
|
|
5685
|
+
`/api/v1/metafield-definitions/products/${productId}/customization-fields`
|
|
5686
|
+
);
|
|
5687
|
+
}
|
|
5688
|
+
/**
|
|
5689
|
+
* Set customization fields for a product (replaces all existing assignments).
|
|
5690
|
+
* Only definitions marked as `isCustomerInput: true` can be assigned.
|
|
5691
|
+
* Requires Admin mode (apiKey).
|
|
5692
|
+
*/
|
|
5693
|
+
async setProductCustomizationFields(productId, definitionIds) {
|
|
5694
|
+
return this.adminRequest(
|
|
5695
|
+
"PATCH",
|
|
5696
|
+
`/api/v1/metafield-definitions/products/${productId}/customization-fields`,
|
|
5697
|
+
{ definitionIds }
|
|
5698
|
+
);
|
|
5699
|
+
}
|
|
5700
|
+
/**
|
|
5701
|
+
* Upload a file for product customization (e.g., customer logo for printing).
|
|
5702
|
+
* Available in storefront and vibe-coded modes.
|
|
5703
|
+
* Returns the uploaded file URL and key.
|
|
5704
|
+
*/
|
|
5705
|
+
async uploadCustomizationFile(file) {
|
|
5706
|
+
const formData = new FormData();
|
|
5707
|
+
formData.append("file", file);
|
|
5708
|
+
if (this.isVibeCodedMode()) {
|
|
5709
|
+
return this.vibeCodedRequest(
|
|
5710
|
+
"POST",
|
|
5711
|
+
"/customization-upload",
|
|
5712
|
+
formData
|
|
5713
|
+
);
|
|
5714
|
+
}
|
|
5715
|
+
if (this.storeId && !this.apiKey) {
|
|
5716
|
+
return this.storefrontRequest(
|
|
5717
|
+
"POST",
|
|
5718
|
+
"/customization-upload",
|
|
5719
|
+
formData
|
|
5720
|
+
);
|
|
5721
|
+
}
|
|
5722
|
+
throw new Error("uploadCustomizationFile requires storefront or vibe-coded mode");
|
|
5723
|
+
}
|
|
5505
5724
|
// -------------------- Team Management (Admin) - DEPRECATED --------------------
|
|
5506
5725
|
// These account-level methods are deprecated. Use Store Team Management methods instead.
|
|
5507
5726
|
/**
|
|
@@ -5696,7 +5915,9 @@ var BrainerceClient = class {
|
|
|
5696
5915
|
return this.adminRequest("PUT", "/api/v1/email/settings", data);
|
|
5697
5916
|
}
|
|
5698
5917
|
/**
|
|
5699
|
-
* Get all email templates for the store
|
|
5918
|
+
* Get all email templates for the store, grouped by (eventType, language).
|
|
5919
|
+
* Response includes the store's primary language and supported languages so
|
|
5920
|
+
* the caller can render a locale selector.
|
|
5700
5921
|
* Requires Admin mode (apiKey)
|
|
5701
5922
|
*/
|
|
5702
5923
|
async getEmailTemplates() {
|
|
@@ -6001,6 +6222,19 @@ function getProductPriceInfo(product) {
|
|
|
6001
6222
|
if (!product) {
|
|
6002
6223
|
return { price: 0, originalPrice: 0, isOnSale: false, discountAmount: 0, discountPercent: 0 };
|
|
6003
6224
|
}
|
|
6225
|
+
if (product.discount) {
|
|
6226
|
+
const ruleOriginal = parseFloat(product.discount.originalPrice) || 0;
|
|
6227
|
+
const ruleDiscounted = parseFloat(product.discount.discountedPrice) || 0;
|
|
6228
|
+
const ruleAmount = Math.max(0, ruleOriginal - ruleDiscounted);
|
|
6229
|
+
const rulePercent = ruleOriginal > 0 ? Math.round(ruleAmount / ruleOriginal * 100) : 0;
|
|
6230
|
+
return {
|
|
6231
|
+
price: ruleDiscounted,
|
|
6232
|
+
originalPrice: ruleOriginal,
|
|
6233
|
+
isOnSale: ruleDiscounted < ruleOriginal,
|
|
6234
|
+
discountAmount: ruleAmount,
|
|
6235
|
+
discountPercent: rulePercent
|
|
6236
|
+
};
|
|
6237
|
+
}
|
|
6004
6238
|
const basePrice = parseFloat(product.basePrice) || 0;
|
|
6005
6239
|
const salePrice = product.salePrice ? parseFloat(product.salePrice) : null;
|
|
6006
6240
|
const isOnSale = salePrice !== null && salePrice < basePrice;
|
|
@@ -6065,14 +6299,15 @@ function getVariantOptions(variant) {
|
|
|
6065
6299
|
if (!variant?.attributes) return [];
|
|
6066
6300
|
const internalKeys = /* @__PURE__ */ new Set([
|
|
6067
6301
|
"id",
|
|
6068
|
-
"
|
|
6069
|
-
"
|
|
6070
|
-
"
|
|
6071
|
-
"
|
|
6072
|
-
"metaVariantId",
|
|
6073
|
-
"externalId"
|
|
6302
|
+
"externalId",
|
|
6303
|
+
"externalVariantId",
|
|
6304
|
+
"externalInventoryItemId",
|
|
6305
|
+
"platformVariantId"
|
|
6074
6306
|
]);
|
|
6075
|
-
|
|
6307
|
+
const isPlatformKey = (key) => /^(shopify|woocommerce|tiktok|meta)[A-Z_]/.test(key) || key.includes("VariantId") || key.includes("InventoryItemId");
|
|
6308
|
+
return Object.entries(variant.attributes).filter(
|
|
6309
|
+
([key, value]) => typeof value === "string" && !internalKeys.has(key) && !isPlatformKey(key)
|
|
6310
|
+
).map(([name, value]) => ({ name, value }));
|
|
6076
6311
|
}
|
|
6077
6312
|
function getProductSwatches(product) {
|
|
6078
6313
|
if (!product?.productAttributeOptions) return [];
|
|
@@ -6122,6 +6357,9 @@ function getProductMetafieldValue(product, key) {
|
|
|
6122
6357
|
function getProductMetafieldsByType(product, type) {
|
|
6123
6358
|
return product.metafields?.filter((m) => m.type === type) || [];
|
|
6124
6359
|
}
|
|
6360
|
+
function getProductCustomizationFields(product) {
|
|
6361
|
+
return product.customizationFields ?? [];
|
|
6362
|
+
}
|
|
6125
6363
|
function isCouponApplicableToProduct(coupon, productId) {
|
|
6126
6364
|
const getIds = (refs) => refs?.map((ref) => ref.id) ?? [];
|
|
6127
6365
|
const applicableProductIds = getIds(coupon.applicableProducts);
|
|
@@ -6143,6 +6381,7 @@ function isCouponApplicableToProduct(coupon, productId) {
|
|
|
6143
6381
|
getCartTotals,
|
|
6144
6382
|
getDescriptionContent,
|
|
6145
6383
|
getPriceDisplay,
|
|
6384
|
+
getProductCustomizationFields,
|
|
6146
6385
|
getProductMetafield,
|
|
6147
6386
|
getProductMetafieldValue,
|
|
6148
6387
|
getProductMetafieldsByType,
|