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.mjs
CHANGED
|
@@ -325,6 +325,9 @@ var BrainerceClient = class {
|
|
|
325
325
|
if (this.origin) {
|
|
326
326
|
headers["Origin"] = this.origin;
|
|
327
327
|
}
|
|
328
|
+
if (this.locale) {
|
|
329
|
+
headers["Accept-Language"] = this.locale;
|
|
330
|
+
}
|
|
328
331
|
const response = await fetch(url.toString(), {
|
|
329
332
|
method,
|
|
330
333
|
headers,
|
|
@@ -360,7 +363,7 @@ var BrainerceClient = class {
|
|
|
360
363
|
/**
|
|
361
364
|
* Make a request to the Vibe-Coded API (public, uses connectionId)
|
|
362
365
|
*/
|
|
363
|
-
async vibeCodedRequest(method, path, body, queryParams) {
|
|
366
|
+
async vibeCodedRequest(method, path, body, queryParams, headerOverrides) {
|
|
364
367
|
if (!this.connectionId) {
|
|
365
368
|
throw new BrainerceError("connectionId is required for vibe-coded requests", 400);
|
|
366
369
|
}
|
|
@@ -383,6 +386,12 @@ var BrainerceClient = class {
|
|
|
383
386
|
if (this.origin) {
|
|
384
387
|
headers["Origin"] = this.origin;
|
|
385
388
|
}
|
|
389
|
+
if (this.locale) {
|
|
390
|
+
headers["Accept-Language"] = this.locale;
|
|
391
|
+
}
|
|
392
|
+
if (headerOverrides) {
|
|
393
|
+
Object.assign(headers, headerOverrides);
|
|
394
|
+
}
|
|
386
395
|
if (this.proxyMode && method !== "GET") {
|
|
387
396
|
headers["X-Requested-With"] = "brainerce";
|
|
388
397
|
}
|
|
@@ -431,7 +440,7 @@ var BrainerceClient = class {
|
|
|
431
440
|
/**
|
|
432
441
|
* Make a request to the Storefront API (public, uses storeId)
|
|
433
442
|
*/
|
|
434
|
-
async storefrontRequest(method, path, body, queryParams) {
|
|
443
|
+
async storefrontRequest(method, path, body, queryParams, headerOverrides) {
|
|
435
444
|
if (!this.storeId) {
|
|
436
445
|
throw new BrainerceError("storeId is required for storefront requests", 400);
|
|
437
446
|
}
|
|
@@ -454,6 +463,12 @@ var BrainerceClient = class {
|
|
|
454
463
|
if (this.origin) {
|
|
455
464
|
headers["Origin"] = this.origin;
|
|
456
465
|
}
|
|
466
|
+
if (this.locale) {
|
|
467
|
+
headers["Accept-Language"] = this.locale;
|
|
468
|
+
}
|
|
469
|
+
if (headerOverrides) {
|
|
470
|
+
Object.assign(headers, headerOverrides);
|
|
471
|
+
}
|
|
457
472
|
if (this.customerToken) {
|
|
458
473
|
headers["Authorization"] = `Bearer ${this.customerToken}`;
|
|
459
474
|
}
|
|
@@ -555,7 +570,6 @@ var BrainerceClient = class {
|
|
|
555
570
|
maxPrice: params?.maxPrice,
|
|
556
571
|
sortBy: params?.sortBy,
|
|
557
572
|
sortOrder: params?.sortOrder,
|
|
558
|
-
locale: params?.locale || this.locale,
|
|
559
573
|
// Admin-only params
|
|
560
574
|
type: params?.type
|
|
561
575
|
};
|
|
@@ -587,13 +601,14 @@ var BrainerceClient = class {
|
|
|
587
601
|
* Works in vibe-coded, storefront (public), and admin mode
|
|
588
602
|
*/
|
|
589
603
|
async getProduct(productId, options) {
|
|
590
|
-
const
|
|
604
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
591
605
|
if (this.isVibeCodedMode()) {
|
|
592
606
|
return this.vibeCodedRequest(
|
|
593
607
|
"GET",
|
|
594
608
|
`/products/${productId}`,
|
|
595
609
|
void 0,
|
|
596
|
-
|
|
610
|
+
void 0,
|
|
611
|
+
headerOverrides
|
|
597
612
|
);
|
|
598
613
|
}
|
|
599
614
|
if (this.storeId && !this.apiKey) {
|
|
@@ -601,7 +616,8 @@ var BrainerceClient = class {
|
|
|
601
616
|
"GET",
|
|
602
617
|
`/products/${productId}`,
|
|
603
618
|
void 0,
|
|
604
|
-
|
|
619
|
+
void 0,
|
|
620
|
+
headerOverrides
|
|
605
621
|
);
|
|
606
622
|
}
|
|
607
623
|
return this.adminRequest("GET", `/api/v1/products/${productId}`);
|
|
@@ -617,13 +633,14 @@ var BrainerceClient = class {
|
|
|
617
633
|
* ```
|
|
618
634
|
*/
|
|
619
635
|
async getProductBySlug(slug, options) {
|
|
620
|
-
const
|
|
636
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
621
637
|
if (this.isVibeCodedMode()) {
|
|
622
638
|
return this.vibeCodedRequest(
|
|
623
639
|
"GET",
|
|
624
640
|
`/products/slug/${slug}`,
|
|
625
641
|
void 0,
|
|
626
|
-
|
|
642
|
+
void 0,
|
|
643
|
+
headerOverrides
|
|
627
644
|
);
|
|
628
645
|
}
|
|
629
646
|
if (this.storeId && !this.apiKey) {
|
|
@@ -631,7 +648,8 @@ var BrainerceClient = class {
|
|
|
631
648
|
"GET",
|
|
632
649
|
`/products/slug/${slug}`,
|
|
633
650
|
void 0,
|
|
634
|
-
|
|
651
|
+
void 0,
|
|
652
|
+
headerOverrides
|
|
635
653
|
);
|
|
636
654
|
}
|
|
637
655
|
return this.adminRequest("GET", `/api/v1/products/by-slug/${slug}`);
|
|
@@ -647,9 +665,9 @@ var BrainerceClient = class {
|
|
|
647
665
|
* ```
|
|
648
666
|
*/
|
|
649
667
|
async getCategories(options) {
|
|
650
|
-
const
|
|
668
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
651
669
|
if (this.isVibeCodedMode()) {
|
|
652
|
-
return this.vibeCodedRequest("GET", "/categories", void 0,
|
|
670
|
+
return this.vibeCodedRequest("GET", "/categories", void 0, void 0, headerOverrides);
|
|
653
671
|
}
|
|
654
672
|
throw new BrainerceError("getCategories is only available in vibe-coded mode", 400);
|
|
655
673
|
}
|
|
@@ -664,9 +682,9 @@ var BrainerceClient = class {
|
|
|
664
682
|
* ```
|
|
665
683
|
*/
|
|
666
684
|
async getBrands(options) {
|
|
667
|
-
const
|
|
685
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
668
686
|
if (this.isVibeCodedMode()) {
|
|
669
|
-
return this.vibeCodedRequest("GET", "/brands", void 0,
|
|
687
|
+
return this.vibeCodedRequest("GET", "/brands", void 0, void 0, headerOverrides);
|
|
670
688
|
}
|
|
671
689
|
throw new BrainerceError("getBrands is only available in vibe-coded mode", 400);
|
|
672
690
|
}
|
|
@@ -680,11 +698,10 @@ var BrainerceClient = class {
|
|
|
680
698
|
* // Use tag IDs in getProducts({ tags: ['tag_id'] })
|
|
681
699
|
* ```
|
|
682
700
|
*/
|
|
683
|
-
async getTags() {
|
|
701
|
+
async getTags(options) {
|
|
702
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
684
703
|
if (this.isVibeCodedMode()) {
|
|
685
|
-
return this.vibeCodedRequest("GET", "/tags", void 0,
|
|
686
|
-
locale: this.locale
|
|
687
|
-
});
|
|
704
|
+
return this.vibeCodedRequest("GET", "/tags", void 0, void 0, headerOverrides);
|
|
688
705
|
}
|
|
689
706
|
throw new BrainerceError("getTags is only available in vibe-coded mode", 400);
|
|
690
707
|
}
|
|
@@ -728,7 +745,7 @@ var BrainerceClient = class {
|
|
|
728
745
|
if (!query || query.trim().length === 0) {
|
|
729
746
|
return { products: [], categories: [] };
|
|
730
747
|
}
|
|
731
|
-
const queryParams = { q: query, limit
|
|
748
|
+
const queryParams = { q: query, limit };
|
|
732
749
|
if (this.isVibeCodedMode()) {
|
|
733
750
|
return this.vibeCodedRequest(
|
|
734
751
|
"GET",
|
|
@@ -2034,30 +2051,82 @@ var BrainerceClient = class {
|
|
|
2034
2051
|
}
|
|
2035
2052
|
/**
|
|
2036
2053
|
* Get a cart by ID
|
|
2054
|
+
*
|
|
2055
|
+
* @param cartId - The cart ID
|
|
2056
|
+
* @param options - Optional settings. Use `include` to fetch related data in a single request.
|
|
2057
|
+
*
|
|
2058
|
+
* @example
|
|
2059
|
+
* ```typescript
|
|
2060
|
+
* // Basic cart fetch
|
|
2061
|
+
* const cart = await client.getCart('cart_123');
|
|
2062
|
+
*
|
|
2063
|
+
* // Fetch cart with recommendations, upgrades, and bundles in one call
|
|
2064
|
+
* const enriched = await client.getCart('cart_123', {
|
|
2065
|
+
* include: ['recommendations', 'upgrades', 'bundles'],
|
|
2066
|
+
* });
|
|
2067
|
+
* console.log(enriched.recommendations); // { recommendations: [...] }
|
|
2068
|
+
* console.log(enriched.upgrades); // { upgrades: { ... } }
|
|
2069
|
+
* console.log(enriched.bundles); // { bundles: [...] }
|
|
2070
|
+
* ```
|
|
2037
2071
|
*/
|
|
2038
|
-
async getCart(cartId) {
|
|
2072
|
+
async getCart(cartId, options) {
|
|
2039
2073
|
if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
|
|
2040
2074
|
console.warn('getCart("__local__") is deprecated. Use smartGetCart() instead.');
|
|
2041
2075
|
return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
|
|
2042
2076
|
}
|
|
2077
|
+
const queryParams = options?.include?.length ? { include: options.include.join(",") } : void 0;
|
|
2043
2078
|
if (this.isVibeCodedMode()) {
|
|
2044
|
-
return this.withGuards(
|
|
2079
|
+
return this.withGuards(
|
|
2080
|
+
this.vibeCodedRequest("GET", `/cart/${cartId}`, void 0, queryParams),
|
|
2081
|
+
"cart"
|
|
2082
|
+
);
|
|
2045
2083
|
}
|
|
2046
2084
|
if (this.storeId && !this.apiKey) {
|
|
2047
|
-
return this.withGuards(
|
|
2085
|
+
return this.withGuards(
|
|
2086
|
+
this.storefrontRequest("GET", `/cart/${cartId}`, void 0, queryParams),
|
|
2087
|
+
"cart"
|
|
2088
|
+
);
|
|
2048
2089
|
}
|
|
2049
|
-
return this.withGuards(
|
|
2090
|
+
return this.withGuards(
|
|
2091
|
+
this.adminRequest("GET", `/api/v1/cart/${cartId}`, void 0, queryParams),
|
|
2092
|
+
"cart"
|
|
2093
|
+
);
|
|
2050
2094
|
}
|
|
2051
2095
|
/**
|
|
2052
|
-
* Add an item to the cart
|
|
2096
|
+
* Add an item to the cart.
|
|
2097
|
+
*
|
|
2098
|
+
* If the product has `customizationFields` (merchant-defined buyer input
|
|
2099
|
+
* like engraving text, uploaded photos, select options), pass the buyer's
|
|
2100
|
+
* values in `metadata`. Keys must match each field's `key`. For `IMAGE` /
|
|
2101
|
+
* `GALLERY` types, upload the file first via `uploadCustomizationFile()`
|
|
2102
|
+
* and pass the returned URL. The server validates every value against its
|
|
2103
|
+
* `MetafieldDefinition` and rejects the request with HTTP 400 if anything
|
|
2104
|
+
* fails (type mismatch, required missing, not in `enumValues`, etc.).
|
|
2105
|
+
*
|
|
2106
|
+
* Values are snapshotted onto the order line at checkout — later edits to
|
|
2107
|
+
* the field definition do not retroactively change existing orders.
|
|
2053
2108
|
*
|
|
2054
2109
|
* @example
|
|
2055
2110
|
* ```typescript
|
|
2111
|
+
* // Product with no customization fields
|
|
2056
2112
|
* const cart = await client.addToCart('cart_123', {
|
|
2057
2113
|
* productId: 'prod_abc',
|
|
2058
2114
|
* quantity: 2,
|
|
2059
2115
|
* notes: 'Gift wrap please',
|
|
2060
2116
|
* });
|
|
2117
|
+
*
|
|
2118
|
+
* // Product WITH customization fields (engraving + photo + select + multi)
|
|
2119
|
+
* const { url: photoUrl } = await client.uploadCustomizationFile(file);
|
|
2120
|
+
* const cart = await client.addToCart('cart_123', {
|
|
2121
|
+
* productId: 'prod_mug',
|
|
2122
|
+
* quantity: 1,
|
|
2123
|
+
* metadata: {
|
|
2124
|
+
* engraving_text: 'Happy Birthday!', // TEXT
|
|
2125
|
+
* frame_color: 'Gold', // SELECT (must be in enumValues)
|
|
2126
|
+
* upload_photo: photoUrl, // IMAGE
|
|
2127
|
+
* addons: ['Gift wrap'], // MULTI_SELECT (always array)
|
|
2128
|
+
* },
|
|
2129
|
+
* });
|
|
2061
2130
|
* ```
|
|
2062
2131
|
*/
|
|
2063
2132
|
async addToCart(cartId, item) {
|
|
@@ -2390,17 +2459,21 @@ var BrainerceClient = class {
|
|
|
2390
2459
|
* ```
|
|
2391
2460
|
*/
|
|
2392
2461
|
async getProductRecommendations(productId, type) {
|
|
2393
|
-
const
|
|
2462
|
+
const queryParams = type ? { type } : void 0;
|
|
2394
2463
|
if (this.isVibeCodedMode()) {
|
|
2395
2464
|
return this.vibeCodedRequest(
|
|
2396
2465
|
"GET",
|
|
2397
|
-
`/products/${productId}/recommendations
|
|
2466
|
+
`/products/${productId}/recommendations`,
|
|
2467
|
+
void 0,
|
|
2468
|
+
queryParams
|
|
2398
2469
|
);
|
|
2399
2470
|
}
|
|
2400
2471
|
if (this.storeId && !this.apiKey) {
|
|
2401
2472
|
return this.storefrontRequest(
|
|
2402
2473
|
"GET",
|
|
2403
|
-
`/products/${productId}/recommendations
|
|
2474
|
+
`/products/${productId}/recommendations`,
|
|
2475
|
+
void 0,
|
|
2476
|
+
queryParams
|
|
2404
2477
|
);
|
|
2405
2478
|
}
|
|
2406
2479
|
throw new BrainerceError(
|
|
@@ -2424,17 +2497,21 @@ var BrainerceClient = class {
|
|
|
2424
2497
|
* ```
|
|
2425
2498
|
*/
|
|
2426
2499
|
async getCartRecommendations(cartId, limit) {
|
|
2427
|
-
const
|
|
2500
|
+
const queryParams = limit ? { limit } : void 0;
|
|
2428
2501
|
if (this.isVibeCodedMode()) {
|
|
2429
2502
|
return this.vibeCodedRequest(
|
|
2430
2503
|
"GET",
|
|
2431
|
-
`/cart/${cartId}/recommendations
|
|
2504
|
+
`/cart/${cartId}/recommendations`,
|
|
2505
|
+
void 0,
|
|
2506
|
+
queryParams
|
|
2432
2507
|
);
|
|
2433
2508
|
}
|
|
2434
2509
|
if (this.storeId && !this.apiKey) {
|
|
2435
2510
|
return this.storefrontRequest(
|
|
2436
2511
|
"GET",
|
|
2437
|
-
`/cart/${cartId}/recommendations
|
|
2512
|
+
`/cart/${cartId}/recommendations`,
|
|
2513
|
+
void 0,
|
|
2514
|
+
queryParams
|
|
2438
2515
|
);
|
|
2439
2516
|
}
|
|
2440
2517
|
throw new BrainerceError(
|
|
@@ -2697,11 +2774,21 @@ var BrainerceClient = class {
|
|
|
2697
2774
|
* Uses promise dedup lock to prevent race conditions on parallel calls.
|
|
2698
2775
|
* @internal
|
|
2699
2776
|
*/
|
|
2700
|
-
async getOrCreateSessionCart() {
|
|
2701
|
-
if (this._sessionCartPromise)
|
|
2777
|
+
async getOrCreateSessionCart(options) {
|
|
2778
|
+
if (this._sessionCartPromise) {
|
|
2779
|
+
const base = await this._sessionCartPromise;
|
|
2780
|
+
if (options?.include?.length && base.id) {
|
|
2781
|
+
return this.getCart(base.id, options);
|
|
2782
|
+
}
|
|
2783
|
+
return base;
|
|
2784
|
+
}
|
|
2702
2785
|
this._sessionCartPromise = this._getOrCreateSessionCartImpl();
|
|
2703
2786
|
try {
|
|
2704
|
-
|
|
2787
|
+
const base = await this._sessionCartPromise;
|
|
2788
|
+
if (options?.include?.length && base.id) {
|
|
2789
|
+
return this.getCart(base.id, options);
|
|
2790
|
+
}
|
|
2791
|
+
return base;
|
|
2705
2792
|
} finally {
|
|
2706
2793
|
this._sessionCartPromise = null;
|
|
2707
2794
|
}
|
|
@@ -2834,10 +2921,10 @@ var BrainerceClient = class {
|
|
|
2834
2921
|
* Caches the cart ID for subsequent calls
|
|
2835
2922
|
* @internal
|
|
2836
2923
|
*/
|
|
2837
|
-
async getOrCreateCustomerCart() {
|
|
2924
|
+
async getOrCreateCustomerCart(options) {
|
|
2838
2925
|
if (this.customerCartId) {
|
|
2839
2926
|
try {
|
|
2840
|
-
const existingCart = await this.getCart(this.customerCartId);
|
|
2927
|
+
const existingCart = await this.getCart(this.customerCartId, options);
|
|
2841
2928
|
if (existingCart.status === "ACTIVE") {
|
|
2842
2929
|
return existingCart;
|
|
2843
2930
|
}
|
|
@@ -2850,6 +2937,9 @@ var BrainerceClient = class {
|
|
|
2850
2937
|
const cart2 = await this.fetchCustomerCart();
|
|
2851
2938
|
if (cart2.status === "ACTIVE") {
|
|
2852
2939
|
this.customerCartId = cart2.id;
|
|
2940
|
+
if (options?.include?.length) {
|
|
2941
|
+
return this.getCart(cart2.id, options);
|
|
2942
|
+
}
|
|
2853
2943
|
return cart2;
|
|
2854
2944
|
}
|
|
2855
2945
|
} catch {
|
|
@@ -2901,7 +2991,8 @@ var BrainerceClient = class {
|
|
|
2901
2991
|
const updated = await this.addToCart(cart.id, {
|
|
2902
2992
|
productId: item.productId,
|
|
2903
2993
|
variantId: item.variantId,
|
|
2904
|
-
quantity: item.quantity
|
|
2994
|
+
quantity: item.quantity,
|
|
2995
|
+
metadata: item.metadata
|
|
2905
2996
|
});
|
|
2906
2997
|
return updated;
|
|
2907
2998
|
} else {
|
|
@@ -2909,7 +3000,8 @@ var BrainerceClient = class {
|
|
|
2909
3000
|
const updated = await this.addToCart(cart.id, {
|
|
2910
3001
|
productId: item.productId,
|
|
2911
3002
|
variantId: item.variantId,
|
|
2912
|
-
quantity: item.quantity
|
|
3003
|
+
quantity: item.quantity,
|
|
3004
|
+
metadata: item.metadata
|
|
2913
3005
|
});
|
|
2914
3006
|
this.updateSessionCartItemCount(updated.items?.length ?? 0);
|
|
2915
3007
|
return updated;
|
|
@@ -2922,20 +3014,28 @@ var BrainerceClient = class {
|
|
|
2922
3014
|
* - **Guest with session**: Returns server-side session cart
|
|
2923
3015
|
* - **Guest without session**: Returns empty cart (no server call, cart created lazily on add)
|
|
2924
3016
|
*
|
|
3017
|
+
* @param options - Optional. Use `include` to fetch recommendations, upgrades, and bundles
|
|
3018
|
+
* in a single request instead of separate calls.
|
|
3019
|
+
*
|
|
2925
3020
|
* @example
|
|
2926
3021
|
* ```typescript
|
|
2927
3022
|
* const cart = await client.smartGetCart();
|
|
2928
3023
|
* console.log('Items:', cart.items.length);
|
|
3024
|
+
*
|
|
3025
|
+
* // With includes — single request for cart + extras
|
|
3026
|
+
* const enriched = await client.smartGetCart({
|
|
3027
|
+
* include: ['recommendations', 'upgrades', 'bundles'],
|
|
3028
|
+
* });
|
|
2929
3029
|
* ```
|
|
2930
3030
|
*/
|
|
2931
|
-
async smartGetCart() {
|
|
3031
|
+
async smartGetCart(options) {
|
|
2932
3032
|
if (this.isCustomerLoggedIn()) {
|
|
2933
|
-
return this.getOrCreateCustomerCart();
|
|
3033
|
+
return this.getOrCreateCustomerCart(options);
|
|
2934
3034
|
} else {
|
|
2935
3035
|
if (!this.sessionToken) {
|
|
2936
3036
|
return this.emptyCart();
|
|
2937
3037
|
}
|
|
2938
|
-
return this.getOrCreateSessionCart();
|
|
3038
|
+
return this.getOrCreateSessionCart(options);
|
|
2939
3039
|
}
|
|
2940
3040
|
}
|
|
2941
3041
|
/**
|
|
@@ -5612,9 +5712,35 @@ var BrainerceClient = class {
|
|
|
5612
5712
|
);
|
|
5613
5713
|
}
|
|
5614
5714
|
/**
|
|
5615
|
-
* Upload a file
|
|
5616
|
-
*
|
|
5617
|
-
*
|
|
5715
|
+
* Upload a buyer-submitted file (engraving photo, custom image, etc.) for a
|
|
5716
|
+
* product customization field of type `IMAGE` or `GALLERY`. The returned `url`
|
|
5717
|
+
* is what you pass back in the add-to-cart `metadata` payload.
|
|
5718
|
+
*
|
|
5719
|
+
* Available in storefront and vibe-coded modes — no customer login required.
|
|
5720
|
+
*
|
|
5721
|
+
* Server rules:
|
|
5722
|
+
* - `image/*` MIME only. Other types → HTTP 400.
|
|
5723
|
+
* - Max 5 MB per file.
|
|
5724
|
+
* - Throttled to 10 uploads / minute per IP → HTTP 429.
|
|
5725
|
+
* - Retention: at least 7 days. If the cart never becomes an order, the file
|
|
5726
|
+
* is reclaimed automatically. Once the order exists, the file is kept for
|
|
5727
|
+
* order-history purposes.
|
|
5728
|
+
*
|
|
5729
|
+
* @example
|
|
5730
|
+
* ```ts
|
|
5731
|
+
* // On a product page with IMAGE/GALLERY customization fields:
|
|
5732
|
+
* const { url } = await client.uploadCustomizationFile(fileInput.files[0]);
|
|
5733
|
+
*
|
|
5734
|
+
* // Then include the URL in the add-to-cart metadata:
|
|
5735
|
+
* await client.addToCart(cart.id, {
|
|
5736
|
+
* productId: product.id,
|
|
5737
|
+
* quantity: 1,
|
|
5738
|
+
* metadata: {
|
|
5739
|
+
* engraving_text: 'Happy Birthday!',
|
|
5740
|
+
* upload_photo: url,
|
|
5741
|
+
* },
|
|
5742
|
+
* });
|
|
5743
|
+
* ```
|
|
5618
5744
|
*/
|
|
5619
5745
|
async uploadCustomizationFile(file) {
|
|
5620
5746
|
const formData = new FormData();
|
|
@@ -5829,7 +5955,9 @@ var BrainerceClient = class {
|
|
|
5829
5955
|
return this.adminRequest("PUT", "/api/v1/email/settings", data);
|
|
5830
5956
|
}
|
|
5831
5957
|
/**
|
|
5832
|
-
* Get all email templates for the store
|
|
5958
|
+
* Get all email templates for the store, grouped by (eventType, language).
|
|
5959
|
+
* Response includes the store's primary language and supported languages so
|
|
5960
|
+
* the caller can render a locale selector.
|
|
5833
5961
|
* Requires Admin mode (apiKey)
|
|
5834
5962
|
*/
|
|
5835
5963
|
async getEmailTemplates() {
|
|
@@ -6134,6 +6262,19 @@ function getProductPriceInfo(product) {
|
|
|
6134
6262
|
if (!product) {
|
|
6135
6263
|
return { price: 0, originalPrice: 0, isOnSale: false, discountAmount: 0, discountPercent: 0 };
|
|
6136
6264
|
}
|
|
6265
|
+
if (product.discount) {
|
|
6266
|
+
const ruleOriginal = parseFloat(product.discount.originalPrice) || 0;
|
|
6267
|
+
const ruleDiscounted = parseFloat(product.discount.discountedPrice) || 0;
|
|
6268
|
+
const ruleAmount = Math.max(0, ruleOriginal - ruleDiscounted);
|
|
6269
|
+
const rulePercent = ruleOriginal > 0 ? Math.round(ruleAmount / ruleOriginal * 100) : 0;
|
|
6270
|
+
return {
|
|
6271
|
+
price: ruleDiscounted,
|
|
6272
|
+
originalPrice: ruleOriginal,
|
|
6273
|
+
isOnSale: ruleDiscounted < ruleOriginal,
|
|
6274
|
+
discountAmount: ruleAmount,
|
|
6275
|
+
discountPercent: rulePercent
|
|
6276
|
+
};
|
|
6277
|
+
}
|
|
6137
6278
|
const basePrice = parseFloat(product.basePrice) || 0;
|
|
6138
6279
|
const salePrice = product.salePrice ? parseFloat(product.salePrice) : null;
|
|
6139
6280
|
const isOnSale = salePrice !== null && salePrice < basePrice;
|
package/package.json
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "brainerce",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Official SDK for building e-commerce storefronts with Brainerce Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"require": "./dist/index.js",
|
|
12
|
-
"import": "./dist/index.mjs"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"dist",
|
|
17
|
-
"README.md"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
21
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
22
|
-
"lint": "eslint \"src/**/*.ts\"",
|
|
23
|
-
"test": "vitest run",
|
|
24
|
-
"test:watch": "vitest",
|
|
25
|
-
"prepublishOnly": "pnpm build"
|
|
26
|
-
},
|
|
27
|
-
"keywords": [
|
|
28
|
-
"brainerce",
|
|
29
|
-
"e-commerce",
|
|
30
|
-
"ecommerce",
|
|
31
|
-
"sdk",
|
|
32
|
-
"vibe-coding",
|
|
33
|
-
"vibe-coded",
|
|
34
|
-
"ai-commerce",
|
|
35
|
-
"storefront",
|
|
36
|
-
"headless-commerce",
|
|
37
|
-
"multi-platform",
|
|
38
|
-
"shopify",
|
|
39
|
-
"tiktok",
|
|
40
|
-
"cursor",
|
|
41
|
-
"lovable",
|
|
42
|
-
"v0",
|
|
43
|
-
"cart",
|
|
44
|
-
"checkout",
|
|
45
|
-
"products",
|
|
46
|
-
"sync"
|
|
47
|
-
],
|
|
48
|
-
"author": "Brainerce",
|
|
49
|
-
"license": "MIT",
|
|
50
|
-
"repository": {
|
|
51
|
-
"type": "git",
|
|
52
|
-
"url": "https://github.com/brainerce/brainerce.git",
|
|
53
|
-
"directory": "packages/sdk"
|
|
54
|
-
},
|
|
55
|
-
"homepage": "https://brainerce.com",
|
|
56
|
-
"bugs": {
|
|
57
|
-
"url": "https://github.com/brainerce/brainerce/issues"
|
|
58
|
-
},
|
|
59
|
-
"devDependencies": {
|
|
60
|
-
"@types/node": "^25.0.3",
|
|
61
|
-
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
62
|
-
"@typescript-eslint/parser": "^8.50.1",
|
|
63
|
-
"eslint": "^9.39.2",
|
|
64
|
-
"tsup": "^8.0.0",
|
|
65
|
-
"typescript": "^5.3.0",
|
|
66
|
-
"vitest": "^1.0.0"
|
|
67
|
-
},
|
|
68
|
-
"peerDependencies": {
|
|
69
|
-
"typescript": ">=4.7.0"
|
|
70
|
-
},
|
|
71
|
-
"peerDependenciesMeta": {
|
|
72
|
-
"typescript": {
|
|
73
|
-
"optional": true
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "brainerce",
|
|
3
|
+
"version": "1.18.0",
|
|
4
|
+
"description": "Official SDK for building e-commerce storefronts with Brainerce Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"import": "./dist/index.mjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
21
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
22
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"prepublishOnly": "pnpm build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"brainerce",
|
|
29
|
+
"e-commerce",
|
|
30
|
+
"ecommerce",
|
|
31
|
+
"sdk",
|
|
32
|
+
"vibe-coding",
|
|
33
|
+
"vibe-coded",
|
|
34
|
+
"ai-commerce",
|
|
35
|
+
"storefront",
|
|
36
|
+
"headless-commerce",
|
|
37
|
+
"multi-platform",
|
|
38
|
+
"shopify",
|
|
39
|
+
"tiktok",
|
|
40
|
+
"cursor",
|
|
41
|
+
"lovable",
|
|
42
|
+
"v0",
|
|
43
|
+
"cart",
|
|
44
|
+
"checkout",
|
|
45
|
+
"products",
|
|
46
|
+
"sync"
|
|
47
|
+
],
|
|
48
|
+
"author": "Brainerce",
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "https://github.com/brainerce/brainerce.git",
|
|
53
|
+
"directory": "packages/sdk"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://brainerce.com",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/brainerce/brainerce/issues"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@types/node": "^25.0.3",
|
|
61
|
+
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
62
|
+
"@typescript-eslint/parser": "^8.50.1",
|
|
63
|
+
"eslint": "^9.39.2",
|
|
64
|
+
"tsup": "^8.0.0",
|
|
65
|
+
"typescript": "^5.3.0",
|
|
66
|
+
"vitest": "^1.0.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"typescript": ">=4.7.0"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"typescript": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|