brainerce 1.16.0 → 1.18.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 +4487 -4447
- package/dist/index.d.mts +130 -17
- package/dist/index.d.ts +130 -17
- package/dist/index.js +184 -43
- package/dist/index.mjs +184 -43
- package/package.json +76 -76
package/dist/index.js
CHANGED
|
@@ -386,6 +386,9 @@ var BrainerceClient = class {
|
|
|
386
386
|
if (this.origin) {
|
|
387
387
|
headers["Origin"] = this.origin;
|
|
388
388
|
}
|
|
389
|
+
if (this.locale) {
|
|
390
|
+
headers["Accept-Language"] = this.locale;
|
|
391
|
+
}
|
|
389
392
|
const response = await fetch(url.toString(), {
|
|
390
393
|
method,
|
|
391
394
|
headers,
|
|
@@ -421,7 +424,7 @@ var BrainerceClient = class {
|
|
|
421
424
|
/**
|
|
422
425
|
* Make a request to the Vibe-Coded API (public, uses connectionId)
|
|
423
426
|
*/
|
|
424
|
-
async vibeCodedRequest(method, path, body, queryParams) {
|
|
427
|
+
async vibeCodedRequest(method, path, body, queryParams, headerOverrides) {
|
|
425
428
|
if (!this.connectionId) {
|
|
426
429
|
throw new BrainerceError("connectionId is required for vibe-coded requests", 400);
|
|
427
430
|
}
|
|
@@ -444,6 +447,12 @@ var BrainerceClient = class {
|
|
|
444
447
|
if (this.origin) {
|
|
445
448
|
headers["Origin"] = this.origin;
|
|
446
449
|
}
|
|
450
|
+
if (this.locale) {
|
|
451
|
+
headers["Accept-Language"] = this.locale;
|
|
452
|
+
}
|
|
453
|
+
if (headerOverrides) {
|
|
454
|
+
Object.assign(headers, headerOverrides);
|
|
455
|
+
}
|
|
447
456
|
if (this.proxyMode && method !== "GET") {
|
|
448
457
|
headers["X-Requested-With"] = "brainerce";
|
|
449
458
|
}
|
|
@@ -492,7 +501,7 @@ var BrainerceClient = class {
|
|
|
492
501
|
/**
|
|
493
502
|
* Make a request to the Storefront API (public, uses storeId)
|
|
494
503
|
*/
|
|
495
|
-
async storefrontRequest(method, path, body, queryParams) {
|
|
504
|
+
async storefrontRequest(method, path, body, queryParams, headerOverrides) {
|
|
496
505
|
if (!this.storeId) {
|
|
497
506
|
throw new BrainerceError("storeId is required for storefront requests", 400);
|
|
498
507
|
}
|
|
@@ -515,6 +524,12 @@ var BrainerceClient = class {
|
|
|
515
524
|
if (this.origin) {
|
|
516
525
|
headers["Origin"] = this.origin;
|
|
517
526
|
}
|
|
527
|
+
if (this.locale) {
|
|
528
|
+
headers["Accept-Language"] = this.locale;
|
|
529
|
+
}
|
|
530
|
+
if (headerOverrides) {
|
|
531
|
+
Object.assign(headers, headerOverrides);
|
|
532
|
+
}
|
|
518
533
|
if (this.customerToken) {
|
|
519
534
|
headers["Authorization"] = `Bearer ${this.customerToken}`;
|
|
520
535
|
}
|
|
@@ -616,7 +631,6 @@ var BrainerceClient = class {
|
|
|
616
631
|
maxPrice: params?.maxPrice,
|
|
617
632
|
sortBy: params?.sortBy,
|
|
618
633
|
sortOrder: params?.sortOrder,
|
|
619
|
-
locale: params?.locale || this.locale,
|
|
620
634
|
// Admin-only params
|
|
621
635
|
type: params?.type
|
|
622
636
|
};
|
|
@@ -648,13 +662,14 @@ var BrainerceClient = class {
|
|
|
648
662
|
* Works in vibe-coded, storefront (public), and admin mode
|
|
649
663
|
*/
|
|
650
664
|
async getProduct(productId, options) {
|
|
651
|
-
const
|
|
665
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
652
666
|
if (this.isVibeCodedMode()) {
|
|
653
667
|
return this.vibeCodedRequest(
|
|
654
668
|
"GET",
|
|
655
669
|
`/products/${productId}`,
|
|
656
670
|
void 0,
|
|
657
|
-
|
|
671
|
+
void 0,
|
|
672
|
+
headerOverrides
|
|
658
673
|
);
|
|
659
674
|
}
|
|
660
675
|
if (this.storeId && !this.apiKey) {
|
|
@@ -662,7 +677,8 @@ var BrainerceClient = class {
|
|
|
662
677
|
"GET",
|
|
663
678
|
`/products/${productId}`,
|
|
664
679
|
void 0,
|
|
665
|
-
|
|
680
|
+
void 0,
|
|
681
|
+
headerOverrides
|
|
666
682
|
);
|
|
667
683
|
}
|
|
668
684
|
return this.adminRequest("GET", `/api/v1/products/${productId}`);
|
|
@@ -678,13 +694,14 @@ var BrainerceClient = class {
|
|
|
678
694
|
* ```
|
|
679
695
|
*/
|
|
680
696
|
async getProductBySlug(slug, options) {
|
|
681
|
-
const
|
|
697
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
682
698
|
if (this.isVibeCodedMode()) {
|
|
683
699
|
return this.vibeCodedRequest(
|
|
684
700
|
"GET",
|
|
685
701
|
`/products/slug/${slug}`,
|
|
686
702
|
void 0,
|
|
687
|
-
|
|
703
|
+
void 0,
|
|
704
|
+
headerOverrides
|
|
688
705
|
);
|
|
689
706
|
}
|
|
690
707
|
if (this.storeId && !this.apiKey) {
|
|
@@ -692,7 +709,8 @@ var BrainerceClient = class {
|
|
|
692
709
|
"GET",
|
|
693
710
|
`/products/slug/${slug}`,
|
|
694
711
|
void 0,
|
|
695
|
-
|
|
712
|
+
void 0,
|
|
713
|
+
headerOverrides
|
|
696
714
|
);
|
|
697
715
|
}
|
|
698
716
|
return this.adminRequest("GET", `/api/v1/products/by-slug/${slug}`);
|
|
@@ -708,9 +726,9 @@ var BrainerceClient = class {
|
|
|
708
726
|
* ```
|
|
709
727
|
*/
|
|
710
728
|
async getCategories(options) {
|
|
711
|
-
const
|
|
729
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
712
730
|
if (this.isVibeCodedMode()) {
|
|
713
|
-
return this.vibeCodedRequest("GET", "/categories", void 0,
|
|
731
|
+
return this.vibeCodedRequest("GET", "/categories", void 0, void 0, headerOverrides);
|
|
714
732
|
}
|
|
715
733
|
throw new BrainerceError("getCategories is only available in vibe-coded mode", 400);
|
|
716
734
|
}
|
|
@@ -725,9 +743,9 @@ var BrainerceClient = class {
|
|
|
725
743
|
* ```
|
|
726
744
|
*/
|
|
727
745
|
async getBrands(options) {
|
|
728
|
-
const
|
|
746
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
729
747
|
if (this.isVibeCodedMode()) {
|
|
730
|
-
return this.vibeCodedRequest("GET", "/brands", void 0,
|
|
748
|
+
return this.vibeCodedRequest("GET", "/brands", void 0, void 0, headerOverrides);
|
|
731
749
|
}
|
|
732
750
|
throw new BrainerceError("getBrands is only available in vibe-coded mode", 400);
|
|
733
751
|
}
|
|
@@ -741,11 +759,10 @@ var BrainerceClient = class {
|
|
|
741
759
|
* // Use tag IDs in getProducts({ tags: ['tag_id'] })
|
|
742
760
|
* ```
|
|
743
761
|
*/
|
|
744
|
-
async getTags() {
|
|
762
|
+
async getTags(options) {
|
|
763
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
745
764
|
if (this.isVibeCodedMode()) {
|
|
746
|
-
return this.vibeCodedRequest("GET", "/tags", void 0,
|
|
747
|
-
locale: this.locale
|
|
748
|
-
});
|
|
765
|
+
return this.vibeCodedRequest("GET", "/tags", void 0, void 0, headerOverrides);
|
|
749
766
|
}
|
|
750
767
|
throw new BrainerceError("getTags is only available in vibe-coded mode", 400);
|
|
751
768
|
}
|
|
@@ -789,7 +806,7 @@ var BrainerceClient = class {
|
|
|
789
806
|
if (!query || query.trim().length === 0) {
|
|
790
807
|
return { products: [], categories: [] };
|
|
791
808
|
}
|
|
792
|
-
const queryParams = { q: query, limit
|
|
809
|
+
const queryParams = { q: query, limit };
|
|
793
810
|
if (this.isVibeCodedMode()) {
|
|
794
811
|
return this.vibeCodedRequest(
|
|
795
812
|
"GET",
|
|
@@ -2095,30 +2112,82 @@ var BrainerceClient = class {
|
|
|
2095
2112
|
}
|
|
2096
2113
|
/**
|
|
2097
2114
|
* Get a cart by ID
|
|
2115
|
+
*
|
|
2116
|
+
* @param cartId - The cart ID
|
|
2117
|
+
* @param options - Optional settings. Use `include` to fetch related data in a single request.
|
|
2118
|
+
*
|
|
2119
|
+
* @example
|
|
2120
|
+
* ```typescript
|
|
2121
|
+
* // Basic cart fetch
|
|
2122
|
+
* const cart = await client.getCart('cart_123');
|
|
2123
|
+
*
|
|
2124
|
+
* // Fetch cart with recommendations, upgrades, and bundles in one call
|
|
2125
|
+
* const enriched = await client.getCart('cart_123', {
|
|
2126
|
+
* include: ['recommendations', 'upgrades', 'bundles'],
|
|
2127
|
+
* });
|
|
2128
|
+
* console.log(enriched.recommendations); // { recommendations: [...] }
|
|
2129
|
+
* console.log(enriched.upgrades); // { upgrades: { ... } }
|
|
2130
|
+
* console.log(enriched.bundles); // { bundles: [...] }
|
|
2131
|
+
* ```
|
|
2098
2132
|
*/
|
|
2099
|
-
async getCart(cartId) {
|
|
2133
|
+
async getCart(cartId, options) {
|
|
2100
2134
|
if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
|
|
2101
2135
|
console.warn('getCart("__local__") is deprecated. Use smartGetCart() instead.');
|
|
2102
2136
|
return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
|
|
2103
2137
|
}
|
|
2138
|
+
const queryParams = options?.include?.length ? { include: options.include.join(",") } : void 0;
|
|
2104
2139
|
if (this.isVibeCodedMode()) {
|
|
2105
|
-
return this.withGuards(
|
|
2140
|
+
return this.withGuards(
|
|
2141
|
+
this.vibeCodedRequest("GET", `/cart/${cartId}`, void 0, queryParams),
|
|
2142
|
+
"cart"
|
|
2143
|
+
);
|
|
2106
2144
|
}
|
|
2107
2145
|
if (this.storeId && !this.apiKey) {
|
|
2108
|
-
return this.withGuards(
|
|
2146
|
+
return this.withGuards(
|
|
2147
|
+
this.storefrontRequest("GET", `/cart/${cartId}`, void 0, queryParams),
|
|
2148
|
+
"cart"
|
|
2149
|
+
);
|
|
2109
2150
|
}
|
|
2110
|
-
return this.withGuards(
|
|
2151
|
+
return this.withGuards(
|
|
2152
|
+
this.adminRequest("GET", `/api/v1/cart/${cartId}`, void 0, queryParams),
|
|
2153
|
+
"cart"
|
|
2154
|
+
);
|
|
2111
2155
|
}
|
|
2112
2156
|
/**
|
|
2113
|
-
* Add an item to the cart
|
|
2157
|
+
* Add an item to the cart.
|
|
2158
|
+
*
|
|
2159
|
+
* If the product has `customizationFields` (merchant-defined buyer input
|
|
2160
|
+
* like engraving text, uploaded photos, select options), pass the buyer's
|
|
2161
|
+
* values in `metadata`. Keys must match each field's `key`. For `IMAGE` /
|
|
2162
|
+
* `GALLERY` types, upload the file first via `uploadCustomizationFile()`
|
|
2163
|
+
* and pass the returned URL. The server validates every value against its
|
|
2164
|
+
* `MetafieldDefinition` and rejects the request with HTTP 400 if anything
|
|
2165
|
+
* fails (type mismatch, required missing, not in `enumValues`, etc.).
|
|
2166
|
+
*
|
|
2167
|
+
* Values are snapshotted onto the order line at checkout — later edits to
|
|
2168
|
+
* the field definition do not retroactively change existing orders.
|
|
2114
2169
|
*
|
|
2115
2170
|
* @example
|
|
2116
2171
|
* ```typescript
|
|
2172
|
+
* // Product with no customization fields
|
|
2117
2173
|
* const cart = await client.addToCart('cart_123', {
|
|
2118
2174
|
* productId: 'prod_abc',
|
|
2119
2175
|
* quantity: 2,
|
|
2120
2176
|
* notes: 'Gift wrap please',
|
|
2121
2177
|
* });
|
|
2178
|
+
*
|
|
2179
|
+
* // Product WITH customization fields (engraving + photo + select + multi)
|
|
2180
|
+
* const { url: photoUrl } = await client.uploadCustomizationFile(file);
|
|
2181
|
+
* const cart = await client.addToCart('cart_123', {
|
|
2182
|
+
* productId: 'prod_mug',
|
|
2183
|
+
* quantity: 1,
|
|
2184
|
+
* metadata: {
|
|
2185
|
+
* engraving_text: 'Happy Birthday!', // TEXT
|
|
2186
|
+
* frame_color: 'Gold', // SELECT (must be in enumValues)
|
|
2187
|
+
* upload_photo: photoUrl, // IMAGE
|
|
2188
|
+
* addons: ['Gift wrap'], // MULTI_SELECT (always array)
|
|
2189
|
+
* },
|
|
2190
|
+
* });
|
|
2122
2191
|
* ```
|
|
2123
2192
|
*/
|
|
2124
2193
|
async addToCart(cartId, item) {
|
|
@@ -2451,17 +2520,21 @@ var BrainerceClient = class {
|
|
|
2451
2520
|
* ```
|
|
2452
2521
|
*/
|
|
2453
2522
|
async getProductRecommendations(productId, type) {
|
|
2454
|
-
const
|
|
2523
|
+
const queryParams = type ? { type } : void 0;
|
|
2455
2524
|
if (this.isVibeCodedMode()) {
|
|
2456
2525
|
return this.vibeCodedRequest(
|
|
2457
2526
|
"GET",
|
|
2458
|
-
`/products/${productId}/recommendations
|
|
2527
|
+
`/products/${productId}/recommendations`,
|
|
2528
|
+
void 0,
|
|
2529
|
+
queryParams
|
|
2459
2530
|
);
|
|
2460
2531
|
}
|
|
2461
2532
|
if (this.storeId && !this.apiKey) {
|
|
2462
2533
|
return this.storefrontRequest(
|
|
2463
2534
|
"GET",
|
|
2464
|
-
`/products/${productId}/recommendations
|
|
2535
|
+
`/products/${productId}/recommendations`,
|
|
2536
|
+
void 0,
|
|
2537
|
+
queryParams
|
|
2465
2538
|
);
|
|
2466
2539
|
}
|
|
2467
2540
|
throw new BrainerceError(
|
|
@@ -2485,17 +2558,21 @@ var BrainerceClient = class {
|
|
|
2485
2558
|
* ```
|
|
2486
2559
|
*/
|
|
2487
2560
|
async getCartRecommendations(cartId, limit) {
|
|
2488
|
-
const
|
|
2561
|
+
const queryParams = limit ? { limit } : void 0;
|
|
2489
2562
|
if (this.isVibeCodedMode()) {
|
|
2490
2563
|
return this.vibeCodedRequest(
|
|
2491
2564
|
"GET",
|
|
2492
|
-
`/cart/${cartId}/recommendations
|
|
2565
|
+
`/cart/${cartId}/recommendations`,
|
|
2566
|
+
void 0,
|
|
2567
|
+
queryParams
|
|
2493
2568
|
);
|
|
2494
2569
|
}
|
|
2495
2570
|
if (this.storeId && !this.apiKey) {
|
|
2496
2571
|
return this.storefrontRequest(
|
|
2497
2572
|
"GET",
|
|
2498
|
-
`/cart/${cartId}/recommendations
|
|
2573
|
+
`/cart/${cartId}/recommendations`,
|
|
2574
|
+
void 0,
|
|
2575
|
+
queryParams
|
|
2499
2576
|
);
|
|
2500
2577
|
}
|
|
2501
2578
|
throw new BrainerceError(
|
|
@@ -2758,11 +2835,21 @@ var BrainerceClient = class {
|
|
|
2758
2835
|
* Uses promise dedup lock to prevent race conditions on parallel calls.
|
|
2759
2836
|
* @internal
|
|
2760
2837
|
*/
|
|
2761
|
-
async getOrCreateSessionCart() {
|
|
2762
|
-
if (this._sessionCartPromise)
|
|
2838
|
+
async getOrCreateSessionCart(options) {
|
|
2839
|
+
if (this._sessionCartPromise) {
|
|
2840
|
+
const base = await this._sessionCartPromise;
|
|
2841
|
+
if (options?.include?.length && base.id) {
|
|
2842
|
+
return this.getCart(base.id, options);
|
|
2843
|
+
}
|
|
2844
|
+
return base;
|
|
2845
|
+
}
|
|
2763
2846
|
this._sessionCartPromise = this._getOrCreateSessionCartImpl();
|
|
2764
2847
|
try {
|
|
2765
|
-
|
|
2848
|
+
const base = await this._sessionCartPromise;
|
|
2849
|
+
if (options?.include?.length && base.id) {
|
|
2850
|
+
return this.getCart(base.id, options);
|
|
2851
|
+
}
|
|
2852
|
+
return base;
|
|
2766
2853
|
} finally {
|
|
2767
2854
|
this._sessionCartPromise = null;
|
|
2768
2855
|
}
|
|
@@ -2895,10 +2982,10 @@ var BrainerceClient = class {
|
|
|
2895
2982
|
* Caches the cart ID for subsequent calls
|
|
2896
2983
|
* @internal
|
|
2897
2984
|
*/
|
|
2898
|
-
async getOrCreateCustomerCart() {
|
|
2985
|
+
async getOrCreateCustomerCart(options) {
|
|
2899
2986
|
if (this.customerCartId) {
|
|
2900
2987
|
try {
|
|
2901
|
-
const existingCart = await this.getCart(this.customerCartId);
|
|
2988
|
+
const existingCart = await this.getCart(this.customerCartId, options);
|
|
2902
2989
|
if (existingCart.status === "ACTIVE") {
|
|
2903
2990
|
return existingCart;
|
|
2904
2991
|
}
|
|
@@ -2911,6 +2998,9 @@ var BrainerceClient = class {
|
|
|
2911
2998
|
const cart2 = await this.fetchCustomerCart();
|
|
2912
2999
|
if (cart2.status === "ACTIVE") {
|
|
2913
3000
|
this.customerCartId = cart2.id;
|
|
3001
|
+
if (options?.include?.length) {
|
|
3002
|
+
return this.getCart(cart2.id, options);
|
|
3003
|
+
}
|
|
2914
3004
|
return cart2;
|
|
2915
3005
|
}
|
|
2916
3006
|
} catch {
|
|
@@ -2962,7 +3052,8 @@ var BrainerceClient = class {
|
|
|
2962
3052
|
const updated = await this.addToCart(cart.id, {
|
|
2963
3053
|
productId: item.productId,
|
|
2964
3054
|
variantId: item.variantId,
|
|
2965
|
-
quantity: item.quantity
|
|
3055
|
+
quantity: item.quantity,
|
|
3056
|
+
metadata: item.metadata
|
|
2966
3057
|
});
|
|
2967
3058
|
return updated;
|
|
2968
3059
|
} else {
|
|
@@ -2970,7 +3061,8 @@ var BrainerceClient = class {
|
|
|
2970
3061
|
const updated = await this.addToCart(cart.id, {
|
|
2971
3062
|
productId: item.productId,
|
|
2972
3063
|
variantId: item.variantId,
|
|
2973
|
-
quantity: item.quantity
|
|
3064
|
+
quantity: item.quantity,
|
|
3065
|
+
metadata: item.metadata
|
|
2974
3066
|
});
|
|
2975
3067
|
this.updateSessionCartItemCount(updated.items?.length ?? 0);
|
|
2976
3068
|
return updated;
|
|
@@ -2983,20 +3075,28 @@ var BrainerceClient = class {
|
|
|
2983
3075
|
* - **Guest with session**: Returns server-side session cart
|
|
2984
3076
|
* - **Guest without session**: Returns empty cart (no server call, cart created lazily on add)
|
|
2985
3077
|
*
|
|
3078
|
+
* @param options - Optional. Use `include` to fetch recommendations, upgrades, and bundles
|
|
3079
|
+
* in a single request instead of separate calls.
|
|
3080
|
+
*
|
|
2986
3081
|
* @example
|
|
2987
3082
|
* ```typescript
|
|
2988
3083
|
* const cart = await client.smartGetCart();
|
|
2989
3084
|
* console.log('Items:', cart.items.length);
|
|
3085
|
+
*
|
|
3086
|
+
* // With includes — single request for cart + extras
|
|
3087
|
+
* const enriched = await client.smartGetCart({
|
|
3088
|
+
* include: ['recommendations', 'upgrades', 'bundles'],
|
|
3089
|
+
* });
|
|
2990
3090
|
* ```
|
|
2991
3091
|
*/
|
|
2992
|
-
async smartGetCart() {
|
|
3092
|
+
async smartGetCart(options) {
|
|
2993
3093
|
if (this.isCustomerLoggedIn()) {
|
|
2994
|
-
return this.getOrCreateCustomerCart();
|
|
3094
|
+
return this.getOrCreateCustomerCart(options);
|
|
2995
3095
|
} else {
|
|
2996
3096
|
if (!this.sessionToken) {
|
|
2997
3097
|
return this.emptyCart();
|
|
2998
3098
|
}
|
|
2999
|
-
return this.getOrCreateSessionCart();
|
|
3099
|
+
return this.getOrCreateSessionCart(options);
|
|
3000
3100
|
}
|
|
3001
3101
|
}
|
|
3002
3102
|
/**
|
|
@@ -5673,9 +5773,35 @@ var BrainerceClient = class {
|
|
|
5673
5773
|
);
|
|
5674
5774
|
}
|
|
5675
5775
|
/**
|
|
5676
|
-
* Upload a file
|
|
5677
|
-
*
|
|
5678
|
-
*
|
|
5776
|
+
* Upload a buyer-submitted file (engraving photo, custom image, etc.) for a
|
|
5777
|
+
* product customization field of type `IMAGE` or `GALLERY`. The returned `url`
|
|
5778
|
+
* is what you pass back in the add-to-cart `metadata` payload.
|
|
5779
|
+
*
|
|
5780
|
+
* Available in storefront and vibe-coded modes — no customer login required.
|
|
5781
|
+
*
|
|
5782
|
+
* Server rules:
|
|
5783
|
+
* - `image/*` MIME only. Other types → HTTP 400.
|
|
5784
|
+
* - Max 5 MB per file.
|
|
5785
|
+
* - Throttled to 10 uploads / minute per IP → HTTP 429.
|
|
5786
|
+
* - Retention: at least 7 days. If the cart never becomes an order, the file
|
|
5787
|
+
* is reclaimed automatically. Once the order exists, the file is kept for
|
|
5788
|
+
* order-history purposes.
|
|
5789
|
+
*
|
|
5790
|
+
* @example
|
|
5791
|
+
* ```ts
|
|
5792
|
+
* // On a product page with IMAGE/GALLERY customization fields:
|
|
5793
|
+
* const { url } = await client.uploadCustomizationFile(fileInput.files[0]);
|
|
5794
|
+
*
|
|
5795
|
+
* // Then include the URL in the add-to-cart metadata:
|
|
5796
|
+
* await client.addToCart(cart.id, {
|
|
5797
|
+
* productId: product.id,
|
|
5798
|
+
* quantity: 1,
|
|
5799
|
+
* metadata: {
|
|
5800
|
+
* engraving_text: 'Happy Birthday!',
|
|
5801
|
+
* upload_photo: url,
|
|
5802
|
+
* },
|
|
5803
|
+
* });
|
|
5804
|
+
* ```
|
|
5679
5805
|
*/
|
|
5680
5806
|
async uploadCustomizationFile(file) {
|
|
5681
5807
|
const formData = new FormData();
|
|
@@ -5890,7 +6016,9 @@ var BrainerceClient = class {
|
|
|
5890
6016
|
return this.adminRequest("PUT", "/api/v1/email/settings", data);
|
|
5891
6017
|
}
|
|
5892
6018
|
/**
|
|
5893
|
-
* Get all email templates for the store
|
|
6019
|
+
* Get all email templates for the store, grouped by (eventType, language).
|
|
6020
|
+
* Response includes the store's primary language and supported languages so
|
|
6021
|
+
* the caller can render a locale selector.
|
|
5894
6022
|
* Requires Admin mode (apiKey)
|
|
5895
6023
|
*/
|
|
5896
6024
|
async getEmailTemplates() {
|
|
@@ -6195,6 +6323,19 @@ function getProductPriceInfo(product) {
|
|
|
6195
6323
|
if (!product) {
|
|
6196
6324
|
return { price: 0, originalPrice: 0, isOnSale: false, discountAmount: 0, discountPercent: 0 };
|
|
6197
6325
|
}
|
|
6326
|
+
if (product.discount) {
|
|
6327
|
+
const ruleOriginal = parseFloat(product.discount.originalPrice) || 0;
|
|
6328
|
+
const ruleDiscounted = parseFloat(product.discount.discountedPrice) || 0;
|
|
6329
|
+
const ruleAmount = Math.max(0, ruleOriginal - ruleDiscounted);
|
|
6330
|
+
const rulePercent = ruleOriginal > 0 ? Math.round(ruleAmount / ruleOriginal * 100) : 0;
|
|
6331
|
+
return {
|
|
6332
|
+
price: ruleDiscounted,
|
|
6333
|
+
originalPrice: ruleOriginal,
|
|
6334
|
+
isOnSale: ruleDiscounted < ruleOriginal,
|
|
6335
|
+
discountAmount: ruleAmount,
|
|
6336
|
+
discountPercent: rulePercent
|
|
6337
|
+
};
|
|
6338
|
+
}
|
|
6198
6339
|
const basePrice = parseFloat(product.basePrice) || 0;
|
|
6199
6340
|
const salePrice = product.salePrice ? parseFloat(product.salePrice) : null;
|
|
6200
6341
|
const isOnSale = salePrice !== null && salePrice < basePrice;
|