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/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("GET", `/products/${productId}`);
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("GET", `/products/${productId}`);
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("GET", `/products/slug/${slug}`);
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("GET", `/products/slug/${slug}`);
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 params = type ? `?type=${type}` : "";
2410
+ const queryParams = type ? { type } : void 0;
2316
2411
  if (this.isVibeCodedMode()) {
2317
2412
  return this.vibeCodedRequest(
2318
2413
  "GET",
2319
- `/products/${productId}/recommendations${params}`
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${params}`
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 params = limit ? `?limit=${limit}` : "";
2448
+ const queryParams = limit ? { limit } : void 0;
2350
2449
  if (this.isVibeCodedMode()) {
2351
2450
  return this.vibeCodedRequest(
2352
2451
  "GET",
2353
- `/cart/${cartId}/recommendations${params}`
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${params}`
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`, { bumpConfigId });
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`, { bumpConfigId });
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`, { bundleOfferId });
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`, { bundleOfferId });
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
- "shopifyVariantId",
6009
- "shopify_variant_id",
6010
- "shopifyInventoryItemId",
6011
- "woocommerceVariantId",
6012
- "metaVariantId",
6013
- "externalId"
6241
+ "externalId",
6242
+ "externalVariantId",
6243
+ "externalInventoryItemId",
6244
+ "platformVariantId"
6014
6245
  ]);
6015
- return Object.entries(variant.attributes).filter(([key, value]) => typeof value === "string" && !internalKeys.has(key)).map(([name, value]) => ({ name, value }));
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.15.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
- }
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
+ }