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.mjs
CHANGED
|
@@ -181,6 +181,41 @@ var BrainerceClient = class {
|
|
|
181
181
|
this.onAuthError = options.onAuthError;
|
|
182
182
|
this.hydrateSessionCart();
|
|
183
183
|
}
|
|
184
|
+
// -------------------- Locale --------------------
|
|
185
|
+
/**
|
|
186
|
+
* Set the active locale for content translation.
|
|
187
|
+
* When set, all content endpoints (products, categories, brands) will return
|
|
188
|
+
* translated content for this locale, falling back to the store's default language.
|
|
189
|
+
*
|
|
190
|
+
* @param locale - Locale code (e.g., "he", "es", "fr") or undefined to clear
|
|
191
|
+
*/
|
|
192
|
+
setLocale(locale) {
|
|
193
|
+
this.locale = locale;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get the currently active locale.
|
|
197
|
+
*/
|
|
198
|
+
getLocale() {
|
|
199
|
+
return this.locale;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get the supported locales for this store.
|
|
203
|
+
* Fetches store info and returns the i18n config.
|
|
204
|
+
* Returns `[storeLanguage]` if multi-language is not enabled.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```typescript
|
|
208
|
+
* const locales = await client.getSupportedLocales();
|
|
209
|
+
* // ["en", "he", "es"]
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
async getSupportedLocales() {
|
|
213
|
+
const info = await this.getStoreInfo();
|
|
214
|
+
if (info.i18n?.enabled && info.i18n.supportedLocales.length > 0) {
|
|
215
|
+
return info.i18n.supportedLocales;
|
|
216
|
+
}
|
|
217
|
+
return [info.language];
|
|
218
|
+
}
|
|
184
219
|
withGuards(result, type) {
|
|
185
220
|
if (!isDevGuardsEnabled()) return result;
|
|
186
221
|
if (result && typeof result.then === "function") {
|
|
@@ -290,6 +325,9 @@ var BrainerceClient = class {
|
|
|
290
325
|
if (this.origin) {
|
|
291
326
|
headers["Origin"] = this.origin;
|
|
292
327
|
}
|
|
328
|
+
if (this.locale) {
|
|
329
|
+
headers["Accept-Language"] = this.locale;
|
|
330
|
+
}
|
|
293
331
|
const response = await fetch(url.toString(), {
|
|
294
332
|
method,
|
|
295
333
|
headers,
|
|
@@ -325,7 +363,7 @@ var BrainerceClient = class {
|
|
|
325
363
|
/**
|
|
326
364
|
* Make a request to the Vibe-Coded API (public, uses connectionId)
|
|
327
365
|
*/
|
|
328
|
-
async vibeCodedRequest(method, path, body, queryParams) {
|
|
366
|
+
async vibeCodedRequest(method, path, body, queryParams, headerOverrides) {
|
|
329
367
|
if (!this.connectionId) {
|
|
330
368
|
throw new BrainerceError("connectionId is required for vibe-coded requests", 400);
|
|
331
369
|
}
|
|
@@ -348,6 +386,12 @@ var BrainerceClient = class {
|
|
|
348
386
|
if (this.origin) {
|
|
349
387
|
headers["Origin"] = this.origin;
|
|
350
388
|
}
|
|
389
|
+
if (this.locale) {
|
|
390
|
+
headers["Accept-Language"] = this.locale;
|
|
391
|
+
}
|
|
392
|
+
if (headerOverrides) {
|
|
393
|
+
Object.assign(headers, headerOverrides);
|
|
394
|
+
}
|
|
351
395
|
if (this.proxyMode && method !== "GET") {
|
|
352
396
|
headers["X-Requested-With"] = "brainerce";
|
|
353
397
|
}
|
|
@@ -396,7 +440,7 @@ var BrainerceClient = class {
|
|
|
396
440
|
/**
|
|
397
441
|
* Make a request to the Storefront API (public, uses storeId)
|
|
398
442
|
*/
|
|
399
|
-
async storefrontRequest(method, path, body, queryParams) {
|
|
443
|
+
async storefrontRequest(method, path, body, queryParams, headerOverrides) {
|
|
400
444
|
if (!this.storeId) {
|
|
401
445
|
throw new BrainerceError("storeId is required for storefront requests", 400);
|
|
402
446
|
}
|
|
@@ -419,6 +463,12 @@ var BrainerceClient = class {
|
|
|
419
463
|
if (this.origin) {
|
|
420
464
|
headers["Origin"] = this.origin;
|
|
421
465
|
}
|
|
466
|
+
if (this.locale) {
|
|
467
|
+
headers["Accept-Language"] = this.locale;
|
|
468
|
+
}
|
|
469
|
+
if (headerOverrides) {
|
|
470
|
+
Object.assign(headers, headerOverrides);
|
|
471
|
+
}
|
|
422
472
|
if (this.customerToken) {
|
|
423
473
|
headers["Authorization"] = `Bearer ${this.customerToken}`;
|
|
424
474
|
}
|
|
@@ -550,12 +600,25 @@ var BrainerceClient = class {
|
|
|
550
600
|
* Get a single product by ID
|
|
551
601
|
* Works in vibe-coded, storefront (public), and admin mode
|
|
552
602
|
*/
|
|
553
|
-
async getProduct(productId) {
|
|
603
|
+
async getProduct(productId, options) {
|
|
604
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
554
605
|
if (this.isVibeCodedMode()) {
|
|
555
|
-
return this.vibeCodedRequest(
|
|
606
|
+
return this.vibeCodedRequest(
|
|
607
|
+
"GET",
|
|
608
|
+
`/products/${productId}`,
|
|
609
|
+
void 0,
|
|
610
|
+
void 0,
|
|
611
|
+
headerOverrides
|
|
612
|
+
);
|
|
556
613
|
}
|
|
557
614
|
if (this.storeId && !this.apiKey) {
|
|
558
|
-
return this.storefrontRequest(
|
|
615
|
+
return this.storefrontRequest(
|
|
616
|
+
"GET",
|
|
617
|
+
`/products/${productId}`,
|
|
618
|
+
void 0,
|
|
619
|
+
void 0,
|
|
620
|
+
headerOverrides
|
|
621
|
+
);
|
|
559
622
|
}
|
|
560
623
|
return this.adminRequest("GET", `/api/v1/products/${productId}`);
|
|
561
624
|
}
|
|
@@ -569,12 +632,25 @@ var BrainerceClient = class {
|
|
|
569
632
|
* const product = await client.getProductBySlug('awesome-product-name');
|
|
570
633
|
* ```
|
|
571
634
|
*/
|
|
572
|
-
async getProductBySlug(slug) {
|
|
635
|
+
async getProductBySlug(slug, options) {
|
|
636
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
573
637
|
if (this.isVibeCodedMode()) {
|
|
574
|
-
return this.vibeCodedRequest(
|
|
638
|
+
return this.vibeCodedRequest(
|
|
639
|
+
"GET",
|
|
640
|
+
`/products/slug/${slug}`,
|
|
641
|
+
void 0,
|
|
642
|
+
void 0,
|
|
643
|
+
headerOverrides
|
|
644
|
+
);
|
|
575
645
|
}
|
|
576
646
|
if (this.storeId && !this.apiKey) {
|
|
577
|
-
return this.storefrontRequest(
|
|
647
|
+
return this.storefrontRequest(
|
|
648
|
+
"GET",
|
|
649
|
+
`/products/slug/${slug}`,
|
|
650
|
+
void 0,
|
|
651
|
+
void 0,
|
|
652
|
+
headerOverrides
|
|
653
|
+
);
|
|
578
654
|
}
|
|
579
655
|
return this.adminRequest("GET", `/api/v1/products/by-slug/${slug}`);
|
|
580
656
|
}
|
|
@@ -588,9 +664,10 @@ var BrainerceClient = class {
|
|
|
588
664
|
* // categories is a tree structure with children
|
|
589
665
|
* ```
|
|
590
666
|
*/
|
|
591
|
-
async getCategories() {
|
|
667
|
+
async getCategories(options) {
|
|
668
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
592
669
|
if (this.isVibeCodedMode()) {
|
|
593
|
-
return this.vibeCodedRequest("GET", "/categories");
|
|
670
|
+
return this.vibeCodedRequest("GET", "/categories", void 0, void 0, headerOverrides);
|
|
594
671
|
}
|
|
595
672
|
throw new BrainerceError("getCategories is only available in vibe-coded mode", 400);
|
|
596
673
|
}
|
|
@@ -604,9 +681,10 @@ var BrainerceClient = class {
|
|
|
604
681
|
* // Use brand IDs in getProducts({ brands: ['brand_id'] })
|
|
605
682
|
* ```
|
|
606
683
|
*/
|
|
607
|
-
async getBrands() {
|
|
684
|
+
async getBrands(options) {
|
|
685
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
608
686
|
if (this.isVibeCodedMode()) {
|
|
609
|
-
return this.vibeCodedRequest("GET", "/brands");
|
|
687
|
+
return this.vibeCodedRequest("GET", "/brands", void 0, void 0, headerOverrides);
|
|
610
688
|
}
|
|
611
689
|
throw new BrainerceError("getBrands is only available in vibe-coded mode", 400);
|
|
612
690
|
}
|
|
@@ -620,9 +698,10 @@ var BrainerceClient = class {
|
|
|
620
698
|
* // Use tag IDs in getProducts({ tags: ['tag_id'] })
|
|
621
699
|
* ```
|
|
622
700
|
*/
|
|
623
|
-
async getTags() {
|
|
701
|
+
async getTags(options) {
|
|
702
|
+
const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
|
|
624
703
|
if (this.isVibeCodedMode()) {
|
|
625
|
-
return this.vibeCodedRequest("GET", "/tags");
|
|
704
|
+
return this.vibeCodedRequest("GET", "/tags", void 0, void 0, headerOverrides);
|
|
626
705
|
}
|
|
627
706
|
throw new BrainerceError("getTags is only available in vibe-coded mode", 400);
|
|
628
707
|
}
|
|
@@ -646,6 +725,22 @@ var BrainerceClient = class {
|
|
|
646
725
|
* const suggestions = await client.getSearchSuggestions('dress', 3);
|
|
647
726
|
* ```
|
|
648
727
|
*/
|
|
728
|
+
/**
|
|
729
|
+
* Get locale alternates for a product (for SEO hreflang tags).
|
|
730
|
+
* Returns the slug for each available locale.
|
|
731
|
+
*
|
|
732
|
+
* @example
|
|
733
|
+
* ```typescript
|
|
734
|
+
* const { alternates } = await client.getProductAlternates('product_id');
|
|
735
|
+
* // alternates = [{ locale: "en", slug: "running-shoes" }, { locale: "he", slug: "נעלי-ריצה" }]
|
|
736
|
+
* ```
|
|
737
|
+
*/
|
|
738
|
+
async getProductAlternates(productId) {
|
|
739
|
+
if (this.storeId && !this.apiKey) {
|
|
740
|
+
return this.storefrontRequest("GET", `/products/${productId}/alternates`);
|
|
741
|
+
}
|
|
742
|
+
throw new BrainerceError("getProductAlternates is only available in storefront mode", 400);
|
|
743
|
+
}
|
|
649
744
|
async getSearchSuggestions(query, limit) {
|
|
650
745
|
if (!query || query.trim().length === 0) {
|
|
651
746
|
return { products: [], categories: [] };
|
|
@@ -2312,17 +2407,21 @@ var BrainerceClient = class {
|
|
|
2312
2407
|
* ```
|
|
2313
2408
|
*/
|
|
2314
2409
|
async getProductRecommendations(productId, type) {
|
|
2315
|
-
const
|
|
2410
|
+
const queryParams = type ? { type } : void 0;
|
|
2316
2411
|
if (this.isVibeCodedMode()) {
|
|
2317
2412
|
return this.vibeCodedRequest(
|
|
2318
2413
|
"GET",
|
|
2319
|
-
`/products/${productId}/recommendations
|
|
2414
|
+
`/products/${productId}/recommendations`,
|
|
2415
|
+
void 0,
|
|
2416
|
+
queryParams
|
|
2320
2417
|
);
|
|
2321
2418
|
}
|
|
2322
2419
|
if (this.storeId && !this.apiKey) {
|
|
2323
2420
|
return this.storefrontRequest(
|
|
2324
2421
|
"GET",
|
|
2325
|
-
`/products/${productId}/recommendations
|
|
2422
|
+
`/products/${productId}/recommendations`,
|
|
2423
|
+
void 0,
|
|
2424
|
+
queryParams
|
|
2326
2425
|
);
|
|
2327
2426
|
}
|
|
2328
2427
|
throw new BrainerceError(
|
|
@@ -2346,17 +2445,21 @@ var BrainerceClient = class {
|
|
|
2346
2445
|
* ```
|
|
2347
2446
|
*/
|
|
2348
2447
|
async getCartRecommendations(cartId, limit) {
|
|
2349
|
-
const
|
|
2448
|
+
const queryParams = limit ? { limit } : void 0;
|
|
2350
2449
|
if (this.isVibeCodedMode()) {
|
|
2351
2450
|
return this.vibeCodedRequest(
|
|
2352
2451
|
"GET",
|
|
2353
|
-
`/cart/${cartId}/recommendations
|
|
2452
|
+
`/cart/${cartId}/recommendations`,
|
|
2453
|
+
void 0,
|
|
2454
|
+
queryParams
|
|
2354
2455
|
);
|
|
2355
2456
|
}
|
|
2356
2457
|
if (this.storeId && !this.apiKey) {
|
|
2357
2458
|
return this.storefrontRequest(
|
|
2358
2459
|
"GET",
|
|
2359
|
-
`/cart/${cartId}/recommendations
|
|
2460
|
+
`/cart/${cartId}/recommendations`,
|
|
2461
|
+
void 0,
|
|
2462
|
+
queryParams
|
|
2360
2463
|
);
|
|
2361
2464
|
}
|
|
2362
2465
|
throw new BrainerceError(
|
|
@@ -2432,14 +2535,16 @@ var BrainerceClient = class {
|
|
|
2432
2535
|
*
|
|
2433
2536
|
* @param cartId - Cart ID
|
|
2434
2537
|
* @param bumpConfigId - Order bump config ID
|
|
2538
|
+
* @param variantId - Optional variant ID (required when bump product has variants and no admin-locked variant)
|
|
2435
2539
|
* @returns Updated cart
|
|
2436
2540
|
*/
|
|
2437
|
-
async addOrderBump(cartId, bumpConfigId) {
|
|
2541
|
+
async addOrderBump(cartId, bumpConfigId, variantId) {
|
|
2542
|
+
const body = { bumpConfigId, ...variantId && { variantId } };
|
|
2438
2543
|
if (this.isVibeCodedMode()) {
|
|
2439
|
-
return this.vibeCodedRequest("POST", `/cart/${cartId}/bump`,
|
|
2544
|
+
return this.vibeCodedRequest("POST", `/cart/${cartId}/bump`, body);
|
|
2440
2545
|
}
|
|
2441
2546
|
if (this.storeId && !this.apiKey) {
|
|
2442
|
-
return this.storefrontRequest("POST", `/cart/${cartId}/bump`,
|
|
2547
|
+
return this.storefrontRequest("POST", `/cart/${cartId}/bump`, body);
|
|
2443
2548
|
}
|
|
2444
2549
|
throw new BrainerceError("addOrderBump() requires vibe-coded or storefront mode", 400);
|
|
2445
2550
|
}
|
|
@@ -2464,20 +2569,25 @@ var BrainerceClient = class {
|
|
|
2464
2569
|
*
|
|
2465
2570
|
* @param cartId - Cart ID
|
|
2466
2571
|
* @param bundleOfferId - Bundle offer ID
|
|
2572
|
+
* @param variantId - Optional variant ID (required when bundle product has variants and no admin-locked variant)
|
|
2467
2573
|
* @returns Updated cart
|
|
2468
2574
|
*
|
|
2469
2575
|
* @example
|
|
2470
2576
|
* ```typescript
|
|
2471
2577
|
* const { bundles } = await client.getCartBundles('cart_123');
|
|
2578
|
+
* // Simple product or locked variant:
|
|
2472
2579
|
* const cart = await client.addBundleToCart('cart_123', bundles[0].id);
|
|
2580
|
+
* // Product with variants (customer selects):
|
|
2581
|
+
* const cart = await client.addBundleToCart('cart_123', bundles[0].id, selectedVariantId);
|
|
2473
2582
|
* ```
|
|
2474
2583
|
*/
|
|
2475
|
-
async addBundleToCart(cartId, bundleOfferId) {
|
|
2584
|
+
async addBundleToCart(cartId, bundleOfferId, variantId) {
|
|
2585
|
+
const body = { bundleOfferId, ...variantId && { variantId } };
|
|
2476
2586
|
if (this.isVibeCodedMode()) {
|
|
2477
|
-
return this.vibeCodedRequest("POST", `/cart/${cartId}/bundle`,
|
|
2587
|
+
return this.vibeCodedRequest("POST", `/cart/${cartId}/bundle`, body);
|
|
2478
2588
|
}
|
|
2479
2589
|
if (this.storeId && !this.apiKey) {
|
|
2480
|
-
return this.storefrontRequest("POST", `/cart/${cartId}/bundle`,
|
|
2590
|
+
return this.storefrontRequest("POST", `/cart/${cartId}/bundle`, body);
|
|
2481
2591
|
}
|
|
2482
2592
|
throw new BrainerceError("addBundleToCart() requires vibe-coded or storefront mode", 400);
|
|
2483
2593
|
}
|
|
@@ -3399,6 +3509,67 @@ var BrainerceClient = class {
|
|
|
3399
3509
|
this.clearActiveCheckoutStorage();
|
|
3400
3510
|
return result;
|
|
3401
3511
|
}
|
|
3512
|
+
// -------------------- Checkout Custom Fields --------------------
|
|
3513
|
+
/**
|
|
3514
|
+
* Get applicable custom field definitions for a checkout.
|
|
3515
|
+
* Returns fields filtered by visibility conditions (delivery type, products in cart).
|
|
3516
|
+
* Use these to render dynamic input fields in the checkout flow.
|
|
3517
|
+
*/
|
|
3518
|
+
async getCheckoutCustomFields(checkoutId) {
|
|
3519
|
+
if (this.isVibeCodedMode()) {
|
|
3520
|
+
return this.vibeCodedRequest(
|
|
3521
|
+
"GET",
|
|
3522
|
+
`/checkout/${checkoutId}/custom-fields`
|
|
3523
|
+
);
|
|
3524
|
+
}
|
|
3525
|
+
if (this.storeId && !this.apiKey) {
|
|
3526
|
+
return this.storefrontRequest(
|
|
3527
|
+
"GET",
|
|
3528
|
+
`/checkout/${checkoutId}/custom-fields`
|
|
3529
|
+
);
|
|
3530
|
+
}
|
|
3531
|
+
return this.adminRequest(
|
|
3532
|
+
"GET",
|
|
3533
|
+
`/api/v1/checkouts/${checkoutId}/custom-fields`
|
|
3534
|
+
);
|
|
3535
|
+
}
|
|
3536
|
+
/**
|
|
3537
|
+
* Set checkout custom field values and recalculate surcharges.
|
|
3538
|
+
* The checkout total is automatically updated to include surcharges.
|
|
3539
|
+
*
|
|
3540
|
+
* @example
|
|
3541
|
+
* ```typescript
|
|
3542
|
+
* const checkout = await client.setCheckoutCustomFields(checkoutId, {
|
|
3543
|
+
* gift_wrapping: 'premium', // SELECT field
|
|
3544
|
+
* floor_number: 5, // NUMBER field
|
|
3545
|
+
* installation: true, // BOOLEAN field
|
|
3546
|
+
* });
|
|
3547
|
+
* // checkout.surchargeAmount reflects the new surcharges
|
|
3548
|
+
* // checkout.total is recalculated
|
|
3549
|
+
* ```
|
|
3550
|
+
*/
|
|
3551
|
+
async setCheckoutCustomFields(checkoutId, fields) {
|
|
3552
|
+
const data = { fields };
|
|
3553
|
+
if (this.isVibeCodedMode()) {
|
|
3554
|
+
return this.vibeCodedRequest(
|
|
3555
|
+
"PATCH",
|
|
3556
|
+
`/checkout/${checkoutId}/custom-fields`,
|
|
3557
|
+
data
|
|
3558
|
+
);
|
|
3559
|
+
}
|
|
3560
|
+
if (this.storeId && !this.apiKey) {
|
|
3561
|
+
return this.storefrontRequest(
|
|
3562
|
+
"PATCH",
|
|
3563
|
+
`/checkout/${checkoutId}/custom-fields`,
|
|
3564
|
+
data
|
|
3565
|
+
);
|
|
3566
|
+
}
|
|
3567
|
+
return this.adminRequest(
|
|
3568
|
+
"PATCH",
|
|
3569
|
+
`/api/v1/checkouts/${checkoutId}/custom-fields`,
|
|
3570
|
+
data
|
|
3571
|
+
);
|
|
3572
|
+
}
|
|
3402
3573
|
/**
|
|
3403
3574
|
* Delete a checkout session. Releases inventory reservations and removes
|
|
3404
3575
|
* payment records not yet linked to an order.
|
|
@@ -5442,6 +5613,53 @@ var BrainerceClient = class {
|
|
|
5442
5613
|
`/api/v1/products/${productId}/metafields/${definitionId}`
|
|
5443
5614
|
);
|
|
5444
5615
|
}
|
|
5616
|
+
// -------------------- Product Customization Fields (Admin) --------------------
|
|
5617
|
+
/**
|
|
5618
|
+
* Get customization fields assigned to a product.
|
|
5619
|
+
* Requires Admin mode (apiKey).
|
|
5620
|
+
*/
|
|
5621
|
+
async getProductCustomizationFields(productId) {
|
|
5622
|
+
return this.adminRequest(
|
|
5623
|
+
"GET",
|
|
5624
|
+
`/api/v1/metafield-definitions/products/${productId}/customization-fields`
|
|
5625
|
+
);
|
|
5626
|
+
}
|
|
5627
|
+
/**
|
|
5628
|
+
* Set customization fields for a product (replaces all existing assignments).
|
|
5629
|
+
* Only definitions marked as `isCustomerInput: true` can be assigned.
|
|
5630
|
+
* Requires Admin mode (apiKey).
|
|
5631
|
+
*/
|
|
5632
|
+
async setProductCustomizationFields(productId, definitionIds) {
|
|
5633
|
+
return this.adminRequest(
|
|
5634
|
+
"PATCH",
|
|
5635
|
+
`/api/v1/metafield-definitions/products/${productId}/customization-fields`,
|
|
5636
|
+
{ definitionIds }
|
|
5637
|
+
);
|
|
5638
|
+
}
|
|
5639
|
+
/**
|
|
5640
|
+
* Upload a file for product customization (e.g., customer logo for printing).
|
|
5641
|
+
* Available in storefront and vibe-coded modes.
|
|
5642
|
+
* Returns the uploaded file URL and key.
|
|
5643
|
+
*/
|
|
5644
|
+
async uploadCustomizationFile(file) {
|
|
5645
|
+
const formData = new FormData();
|
|
5646
|
+
formData.append("file", file);
|
|
5647
|
+
if (this.isVibeCodedMode()) {
|
|
5648
|
+
return this.vibeCodedRequest(
|
|
5649
|
+
"POST",
|
|
5650
|
+
"/customization-upload",
|
|
5651
|
+
formData
|
|
5652
|
+
);
|
|
5653
|
+
}
|
|
5654
|
+
if (this.storeId && !this.apiKey) {
|
|
5655
|
+
return this.storefrontRequest(
|
|
5656
|
+
"POST",
|
|
5657
|
+
"/customization-upload",
|
|
5658
|
+
formData
|
|
5659
|
+
);
|
|
5660
|
+
}
|
|
5661
|
+
throw new Error("uploadCustomizationFile requires storefront or vibe-coded mode");
|
|
5662
|
+
}
|
|
5445
5663
|
// -------------------- Team Management (Admin) - DEPRECATED --------------------
|
|
5446
5664
|
// These account-level methods are deprecated. Use Store Team Management methods instead.
|
|
5447
5665
|
/**
|
|
@@ -5636,7 +5854,9 @@ var BrainerceClient = class {
|
|
|
5636
5854
|
return this.adminRequest("PUT", "/api/v1/email/settings", data);
|
|
5637
5855
|
}
|
|
5638
5856
|
/**
|
|
5639
|
-
* Get all email templates for the store
|
|
5857
|
+
* Get all email templates for the store, grouped by (eventType, language).
|
|
5858
|
+
* Response includes the store's primary language and supported languages so
|
|
5859
|
+
* the caller can render a locale selector.
|
|
5640
5860
|
* Requires Admin mode (apiKey)
|
|
5641
5861
|
*/
|
|
5642
5862
|
async getEmailTemplates() {
|
|
@@ -5941,6 +6161,19 @@ function getProductPriceInfo(product) {
|
|
|
5941
6161
|
if (!product) {
|
|
5942
6162
|
return { price: 0, originalPrice: 0, isOnSale: false, discountAmount: 0, discountPercent: 0 };
|
|
5943
6163
|
}
|
|
6164
|
+
if (product.discount) {
|
|
6165
|
+
const ruleOriginal = parseFloat(product.discount.originalPrice) || 0;
|
|
6166
|
+
const ruleDiscounted = parseFloat(product.discount.discountedPrice) || 0;
|
|
6167
|
+
const ruleAmount = Math.max(0, ruleOriginal - ruleDiscounted);
|
|
6168
|
+
const rulePercent = ruleOriginal > 0 ? Math.round(ruleAmount / ruleOriginal * 100) : 0;
|
|
6169
|
+
return {
|
|
6170
|
+
price: ruleDiscounted,
|
|
6171
|
+
originalPrice: ruleOriginal,
|
|
6172
|
+
isOnSale: ruleDiscounted < ruleOriginal,
|
|
6173
|
+
discountAmount: ruleAmount,
|
|
6174
|
+
discountPercent: rulePercent
|
|
6175
|
+
};
|
|
6176
|
+
}
|
|
5944
6177
|
const basePrice = parseFloat(product.basePrice) || 0;
|
|
5945
6178
|
const salePrice = product.salePrice ? parseFloat(product.salePrice) : null;
|
|
5946
6179
|
const isOnSale = salePrice !== null && salePrice < basePrice;
|
|
@@ -6005,14 +6238,15 @@ function getVariantOptions(variant) {
|
|
|
6005
6238
|
if (!variant?.attributes) return [];
|
|
6006
6239
|
const internalKeys = /* @__PURE__ */ new Set([
|
|
6007
6240
|
"id",
|
|
6008
|
-
"
|
|
6009
|
-
"
|
|
6010
|
-
"
|
|
6011
|
-
"
|
|
6012
|
-
"metaVariantId",
|
|
6013
|
-
"externalId"
|
|
6241
|
+
"externalId",
|
|
6242
|
+
"externalVariantId",
|
|
6243
|
+
"externalInventoryItemId",
|
|
6244
|
+
"platformVariantId"
|
|
6014
6245
|
]);
|
|
6015
|
-
|
|
6246
|
+
const isPlatformKey = (key) => /^(shopify|woocommerce|tiktok|meta)[A-Z_]/.test(key) || key.includes("VariantId") || key.includes("InventoryItemId");
|
|
6247
|
+
return Object.entries(variant.attributes).filter(
|
|
6248
|
+
([key, value]) => typeof value === "string" && !internalKeys.has(key) && !isPlatformKey(key)
|
|
6249
|
+
).map(([name, value]) => ({ name, value }));
|
|
6016
6250
|
}
|
|
6017
6251
|
function getProductSwatches(product) {
|
|
6018
6252
|
if (!product?.productAttributeOptions) return [];
|
|
@@ -6062,6 +6296,9 @@ function getProductMetafieldValue(product, key) {
|
|
|
6062
6296
|
function getProductMetafieldsByType(product, type) {
|
|
6063
6297
|
return product.metafields?.filter((m) => m.type === type) || [];
|
|
6064
6298
|
}
|
|
6299
|
+
function getProductCustomizationFields(product) {
|
|
6300
|
+
return product.customizationFields ?? [];
|
|
6301
|
+
}
|
|
6065
6302
|
function isCouponApplicableToProduct(coupon, productId) {
|
|
6066
6303
|
const getIds = (refs) => refs?.map((ref) => ref.id) ?? [];
|
|
6067
6304
|
const applicableProductIds = getIds(coupon.applicableProducts);
|
|
@@ -6082,6 +6319,7 @@ export {
|
|
|
6082
6319
|
getCartTotals,
|
|
6083
6320
|
getDescriptionContent,
|
|
6084
6321
|
formatPrice as getPriceDisplay,
|
|
6322
|
+
getProductCustomizationFields,
|
|
6085
6323
|
getProductMetafield,
|
|
6086
6324
|
getProductMetafieldValue,
|
|
6087
6325
|
getProductMetafieldsByType,
|
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.17.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
|
+
}
|