brainerce 2.0.2 → 2.1.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
@@ -115,7 +115,7 @@ function isDevGuardsEnabled() {
115
115
  }
116
116
 
117
117
  // src/version.ts
118
- var SDK_VERSION = "2.0.1";
118
+ var SDK_VERSION = "2.0.3";
119
119
 
120
120
  // src/client.ts
121
121
  var DEFAULT_BASE_URL = "https://api.brainerce.com";
@@ -1132,6 +1132,45 @@ var _BrainerceClient = class _BrainerceClient {
1132
1132
  getStoreDirection(locale) {
1133
1133
  return getDirectionForLocale(locale ?? this.locale);
1134
1134
  }
1135
+ /**
1136
+ * Get what the merchant actually configured on this sales channel: store
1137
+ * identity and multi-language setup, the channel's own settings (low-stock
1138
+ * warning and threshold, reservation strategy and timeout, birthday and
1139
+ * email-verification requirements, granted scopes) and which optional
1140
+ * features are switched on (payment providers, social login, coupons,
1141
+ * discount rules, shipping zones, downloadables, content, loyalty).
1142
+ *
1143
+ * Read this instead of hardcoding. A storefront with a hardcoded low-stock
1144
+ * threshold shows the wrong badge on every store whose merchant chose a
1145
+ * different one, and a storefront that renders a feature nobody enabled
1146
+ * ships a control that silently does nothing.
1147
+ *
1148
+ * Only available in vibe-coded mode (`salesChannelId`). The payload belongs
1149
+ * to one sales channel: `storeId` mode has no channel to read it from, and
1150
+ * an `apiKey` addresses the store rather than any single channel.
1151
+ *
1152
+ * Call it once for the whole app and share the result. It is per channel,
1153
+ * not per product, so fetching it on every page is wasted work.
1154
+ *
1155
+ * @example
1156
+ * ```typescript
1157
+ * const caps = await client.getStoreCapabilities();
1158
+ *
1159
+ * // Low stock: honour the switch before the number.
1160
+ * const threshold = caps.connection.lowStockWarning
1161
+ * ? caps.connection.lowStockThreshold
1162
+ * : 0;
1163
+ *
1164
+ * if (caps.features.hasCoupons) renderCouponInput();
1165
+ * if (caps.store.i18n?.enabled) renderLocaleSwitcher(caps.store.i18n.supportedLocales);
1166
+ * ```
1167
+ */
1168
+ async getStoreCapabilities() {
1169
+ if (this.isVibeCodedMode()) {
1170
+ return this.vibeCodedRequest("GET", "/capabilities");
1171
+ }
1172
+ throw new BrainerceError("getStoreCapabilities is only available in vibe-coded mode", 400);
1173
+ }
1135
1174
  // -------------------- Analytics --------------------
1136
1175
  /**
1137
1176
  * Send a storefront analytics beacon (pageview or engagement).
@@ -2959,14 +2998,20 @@ var _BrainerceClient = class _BrainerceClient {
2959
2998
  });
2960
2999
  }
2961
3000
  /**
2962
- * Get platform capabilities for coupon features.
2963
- * Use this to understand what features each platform supports.
3001
+ * Get platform capabilities for coupon features, keyed by platform.
3002
+ *
3003
+ * ⛔ **Returns an empty object today.** Platform coupon capabilities moved
3004
+ * into the standalone connector apps and are not re-exposed here yet, so the
3005
+ * endpoint answers `{}` for every store. Treat a missing key as "unknown",
3006
+ * never as "the platform lacks the feature", and do not index into a platform
3007
+ * key without checking it exists first — there are none to find.
2964
3008
  *
2965
3009
  * @example
2966
3010
  * ```typescript
2967
3011
  * const capabilities = await client.getCouponPlatformCapabilities();
2968
- * if (!capabilities.SHOPIFY.supportsProductExclusions) {
2969
- * console.log('Shopify does not support product exclusions');
3012
+ * const meta = capabilities['GOOGLE'];
3013
+ * if (meta && !meta.supportsProducts) {
3014
+ * console.log('This platform cannot target individual products');
2970
3015
  * }
2971
3016
  * ```
2972
3017
  */
@@ -3092,7 +3137,7 @@ var _BrainerceClient = class _BrainerceClient {
3092
3137
  );
3093
3138
  }
3094
3139
  console.warn(
3095
- `BrainerceClient.${methodName}: passing \`storeId\` is deprecated \u2014 it is now derived from the SDK config. Remove the leading argument; this overload will be removed in SDK 2.0.`
3140
+ `BrainerceClient.${methodName}: passing \`storeId\` is deprecated \u2014 it is now derived from the SDK config. Remove the leading argument; this overload will be removed in a future major version.`
3096
3141
  );
3097
3142
  }
3098
3143
  /**
@@ -5587,6 +5632,164 @@ var _BrainerceClient = class _BrainerceClient {
5587
5632
  "checkout"
5588
5633
  );
5589
5634
  }
5635
+ /**
5636
+ * Apply a gift card to a checkout.
5637
+ *
5638
+ * Merchants issue cards from the dashboard, so live codes exist and this field
5639
+ * is worth building. There is still no way for a shopper to BUY a gift card —
5640
+ * no product type, no purchase flow — so every card in circulation was issued
5641
+ * by hand.
5642
+ *
5643
+ * Redemption is deliberately NOT gated on the store's gift-card switch: a
5644
+ * store that turned the feature off still owes every card already in a
5645
+ * customer's hand, so the field keeps working. Build it unconditionally.
5646
+ *
5647
+ * A gift card is a **means of payment, not a discount**. The order total does
5648
+ * not change and tax stays calculated on the full value; what changes is
5649
+ * `providerAmountDue`, the amount the payment provider will be charged.
5650
+ *
5651
+ * Render it as its own line — "Gift card −₪54.50" beside the total — and NOT
5652
+ * by adding it to `discountAmount`. A shopper who sees stored value folded
5653
+ * into a discount is being shown the wrong thing, and so is their receipt.
5654
+ *
5655
+ * Only as much of the card as the order still owes is applied, so a card
5656
+ * larger than the basket leaves a balance on it for next time, and a smaller
5657
+ * one leaves an amount for the provider to charge.
5658
+ *
5659
+ * @example
5660
+ * const { amountApplied, providerAmountDue, tenderId } =
5661
+ * await client.applyGiftCard('checkout_123', 'A1B2-C3D4-E5F6-G7H8-J9K0');
5662
+ * // total is unchanged; charge the provider providerAmountDue
5663
+ */
5664
+ async applyGiftCard(checkoutId, code) {
5665
+ if (this.isVibeCodedMode()) {
5666
+ return this.vibeCodedRequest(
5667
+ "POST",
5668
+ `/checkout/${encodePathSegment(checkoutId)}/gift-card`,
5669
+ { code }
5670
+ );
5671
+ }
5672
+ if (this.storeId && !this.apiKey) {
5673
+ return this.storefrontRequest(
5674
+ "POST",
5675
+ `/checkout/${encodePathSegment(checkoutId)}/gift-card`,
5676
+ { code }
5677
+ );
5678
+ }
5679
+ return this.adminRequest(
5680
+ "POST",
5681
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/gift-card`,
5682
+ { code }
5683
+ );
5684
+ }
5685
+ /**
5686
+ * Remove a previously applied gift card from a checkout.
5687
+ *
5688
+ * Takes the `tenderId` returned by {@link applyGiftCard}, not the code — a
5689
+ * checkout can carry more than one card, and the code is never echoed back.
5690
+ *
5691
+ * The held value goes straight back to the card. Nothing was ever debited
5692
+ * while it was applied, so removing costs the shopper nothing.
5693
+ */
5694
+ async removeGiftCard(checkoutId, tenderId) {
5695
+ const path = `/checkout/${encodePathSegment(checkoutId)}/gift-card/${encodePathSegment(tenderId)}`;
5696
+ if (this.isVibeCodedMode()) {
5697
+ return this.vibeCodedRequest("DELETE", path);
5698
+ }
5699
+ if (this.storeId && !this.apiKey) {
5700
+ return this.storefrontRequest("DELETE", path);
5701
+ }
5702
+ return this.adminRequest("DELETE", `/api/v1${path}`);
5703
+ }
5704
+ /**
5705
+ * Check what is left on a gift card.
5706
+ *
5707
+ * Rate limited, and deliberately uninformative: a code that does not exist,
5708
+ * one that has been disabled and one that has expired all return the SAME
5709
+ * response — `{ balance: '0.00', usable: false }` — and take the same time to
5710
+ * do it. Do not build UI that tries to tell those apart, because the API will
5711
+ * not tell you, by design: a gift-card code is bearer value, and an endpoint
5712
+ * that confirmed which codes were real would be a free way to find them.
5713
+ *
5714
+ * Show "we cannot use this code" and let the shopper re-enter it.
5715
+ */
5716
+ async checkGiftCardBalance(code) {
5717
+ if (this.isVibeCodedMode()) {
5718
+ return this.vibeCodedRequest("POST", "/gift-cards/balance", { code });
5719
+ }
5720
+ if (this.storeId && !this.apiKey) {
5721
+ return this.storefrontRequest("POST", "/gift-cards/balance", { code });
5722
+ }
5723
+ return this.adminRequest("POST", "/api/v1/gift-cards/balance", { code });
5724
+ }
5725
+ // ==========================================================================
5726
+ // Donations
5727
+ // ==========================================================================
5728
+ /**
5729
+ * Start a donation.
5730
+ *
5731
+ * A donation does not go through the cart. There is no line item, no
5732
+ * quantity, no shipping and no order — a donor names an amount and pays it,
5733
+ * which is a different shape of transaction from a purchase. Do not model a
5734
+ * donation as a product; if you already have, the amount is the giveaway:
5735
+ * you cannot let a donor type one.
5736
+ *
5737
+ * ⛔ A successful return is NOT a completed gift. You get back a PENDING
5738
+ * donation and a provider intent to complete, exactly as with a checkout.
5739
+ * The gift is only real once the provider's webhook confirms it, which is
5740
+ * when the donation reads back as `PAID`. Show a thank-you that reflects
5741
+ * that, and never send a receipt off the back of this call.
5742
+ *
5743
+ * Requires donations to be switched on for the store; a store that has not
5744
+ * turned them on is rejected rather than silently accepting money.
5745
+ *
5746
+ * ```ts
5747
+ * const donation = await brainerce.createDonation({
5748
+ * amount: 180,
5749
+ * feeCoverAmount: 6.3, // offered as a checkbox; most donors accept
5750
+ * donorEmail: 'sarah@example.com',
5751
+ * donorName: 'Sarah Cohen',
5752
+ * tributeType: 'IN_MEMORY',
5753
+ * tributeName: 'Avraham Cohen',
5754
+ * returnPath: '/thank-you',
5755
+ * });
5756
+ * // → complete donation.payment with your provider, then poll getDonation()
5757
+ * ```
5758
+ */
5759
+ async createDonation(input) {
5760
+ if (this.isVibeCodedMode()) {
5761
+ return this.vibeCodedRequest("POST", "/donations", input);
5762
+ }
5763
+ if (this.storeId && !this.apiKey) {
5764
+ return this.storefrontRequest("POST", "/donations", input);
5765
+ }
5766
+ throw new Error(
5767
+ "createDonation is a storefront call. Initialise the SDK with a salesChannelId or storeId \u2014 an admin apiKey cannot start a donation."
5768
+ );
5769
+ }
5770
+ /**
5771
+ * Read a donation back — for a thank-you page, and to see whether it is paid.
5772
+ *
5773
+ * Rate limited to 5 requests a minute, because an id that either resolves or
5774
+ * 404s is a way to enumerate them. Poll it a handful of times after the donor
5775
+ * returns from the provider; do not put it behind a 1-second interval.
5776
+ *
5777
+ * The payload is narrow on purpose: no failure reason, and `donorName` comes
5778
+ * back `null` whenever the gift was marked anonymous — so you can render this
5779
+ * straight onto a public page without leaking anything.
5780
+ */
5781
+ async getDonation(donationId) {
5782
+ const path = `/donations/${encodePathSegment(donationId)}`;
5783
+ if (this.isVibeCodedMode()) {
5784
+ return this.vibeCodedRequest("GET", path);
5785
+ }
5786
+ if (this.storeId && !this.apiKey) {
5787
+ return this.storefrontRequest("GET", path);
5788
+ }
5789
+ throw new Error(
5790
+ "getDonation is a storefront call. Initialise the SDK with a salesChannelId or storeId."
5791
+ );
5792
+ }
5590
5793
  /**
5591
5794
  * Set customer information on checkout
5592
5795
  *
@@ -7938,119 +8141,6 @@ var _BrainerceClient = class _BrainerceClient {
7938
8141
  }
7939
8142
  return this.storefrontRequest("GET", "/customers/me/cart");
7940
8143
  }
7941
- // -------------------- Custom API Integrations --------------------
7942
- // These methods require Admin mode (apiKey)
7943
- /**
7944
- * Get all Custom API integrations for a store
7945
- * Requires Admin mode (apiKey)
7946
- *
7947
- * @example
7948
- * ```typescript
7949
- * const integrations = await client.getCustomApiIntegrations();
7950
- * integrations.forEach(api => {
7951
- * console.log(`${api.name}: ${api.status}`);
7952
- * });
7953
- * ```
7954
- */
7955
- async getCustomApiIntegrations() {
7956
- return this.adminRequest("GET", "/api/v1/custom-api");
7957
- }
7958
- /**
7959
- * Get a single Custom API integration by ID
7960
- * Requires Admin mode (apiKey)
7961
- *
7962
- * @example
7963
- * ```typescript
7964
- * const api = await client.getCustomApiIntegration('api_123');
7965
- * console.log(`API: ${api.name}, URL: ${api.baseUrl}`);
7966
- * ```
7967
- */
7968
- async getCustomApiIntegration(integrationId) {
7969
- return this.adminRequest(
7970
- "GET",
7971
- `/api/v1/custom-api/${encodePathSegment(integrationId)}`
7972
- );
7973
- }
7974
- /**
7975
- * Create a new Custom API integration
7976
- * Requires Admin mode (apiKey)
7977
- *
7978
- * @example
7979
- * ```typescript
7980
- * const api = await client.createCustomApiIntegration({
7981
- * name: 'My External API',
7982
- * baseUrl: 'https://api.example.com',
7983
- * authType: 'api_key',
7984
- * credentials: {
7985
- * apiKey: 'sk_123...',
7986
- * headerName: 'X-API-Key',
7987
- * },
7988
- * syncDirection: 'bidirectional',
7989
- * syncConfig: {
7990
- * products: true,
7991
- * orders: true,
7992
- * inventory: true,
7993
- * },
7994
- * });
7995
- * ```
7996
- */
7997
- async createCustomApiIntegration(data) {
7998
- return this.adminRequest("POST", "/api/v1/custom-api", data);
7999
- }
8000
- /**
8001
- * Update a Custom API integration
8002
- * Requires Admin mode (apiKey)
8003
- *
8004
- * @example
8005
- * ```typescript
8006
- * const api = await client.updateCustomApiIntegration('api_123', {
8007
- * enabled: false,
8008
- * syncConfig: { products: true, orders: false, inventory: true },
8009
- * });
8010
- * ```
8011
- */
8012
- async updateCustomApiIntegration(integrationId, data) {
8013
- return this.adminRequest(
8014
- "PATCH",
8015
- `/api/v1/custom-api/${encodePathSegment(integrationId)}`,
8016
- data
8017
- );
8018
- }
8019
- /**
8020
- * Delete a Custom API integration
8021
- * Requires Admin mode (apiKey)
8022
- *
8023
- * @example
8024
- * ```typescript
8025
- * await client.deleteCustomApiIntegration('api_123');
8026
- * ```
8027
- */
8028
- async deleteCustomApiIntegration(integrationId) {
8029
- await this.adminRequest(
8030
- "DELETE",
8031
- `/api/v1/custom-api/${encodePathSegment(integrationId)}`
8032
- );
8033
- }
8034
- /**
8035
- * Test connection to a Custom API
8036
- * Requires Admin mode (apiKey)
8037
- *
8038
- * @example
8039
- * ```typescript
8040
- * const result = await client.testCustomApiConnection('api_123');
8041
- * if (result.success) {
8042
- * console.log(`Connection OK, latency: ${result.latency}ms`);
8043
- * } else {
8044
- * console.error(`Connection failed: ${result.error}`);
8045
- * }
8046
- * ```
8047
- */
8048
- async testCustomApiConnection(integrationId) {
8049
- return this.adminRequest(
8050
- "POST",
8051
- `/api/v1/custom-api/${encodePathSegment(integrationId)}/test`
8052
- );
8053
- }
8054
8144
  // -------------------- Inventory Reservations --------------------
8055
8145
  // These methods are only available in vibe-coded mode when reservation strategy
8056
8146
  // is set to ON_CART or ON_CHECKOUT
@@ -8690,12 +8780,18 @@ var _BrainerceClient = class _BrainerceClient {
8690
8780
  * ```typescript
8691
8781
  * const rate = await client.createZoneShippingRate('zone_123', {
8692
8782
  * name: 'Standard Shipping',
8693
- * type: 'flat',
8694
- * price: 5.99,
8695
- * minOrderValue: 0,
8696
- * estimatedDays: '3-5',
8783
+ * type: 'FLAT_RATE',
8784
+ * rateConfig: { amount: 5.99 },
8785
+ * minDeliveryDays: 3,
8786
+ * maxDeliveryDays: 5,
8697
8787
  * });
8698
8788
  * ```
8789
+ *
8790
+ * The price lives in `rateConfig`, whose shape follows `type` — `FLAT_RATE`
8791
+ * takes `{ amount }`, `WEIGHT_BASED` and `PRICE_BASED` take tier arrays, and
8792
+ * `FREE` and `LOCAL_PICKUP` take none. Unknown top-level properties are
8793
+ * rejected outright rather than ignored, so a stray `price` or
8794
+ * `estimatedDays` fails the whole call with 400.
8699
8795
  */
8700
8796
  async createZoneShippingRate(zoneId, data) {
8701
8797
  return this.adminRequest(
@@ -8896,6 +8992,10 @@ var _BrainerceClient = class _BrainerceClient {
8896
8992
  *
8897
8993
  * Returns `appliesTax=false` when tax is disabled, the country is missing,
8898
8994
  * or no active rate covers it.
8995
+ *
8996
+ * The preview has no province, so it only sees country-level rates: a
8997
+ * Canadian estimate shows the federal GST alone and the provincial PST/QST
8998
+ * joins it at checkout. Render `note` so the buyer is not surprised.
8899
8999
  */
8900
9000
  async estimateTax(params) {
8901
9001
  const query = params.country ? { country: params.country, subtotal: params.subtotal } : { subtotal: params.subtotal };
@@ -8966,10 +9066,46 @@ var _BrainerceClient = class _BrainerceClient {
8966
9066
  /**
8967
9067
  * Get all tax rates for the store
8968
9068
  * Requires Admin mode (apiKey)
9069
+ *
9070
+ * A jurisdiction can need more than one rate. Canada is the common case: a
9071
+ * country-level `GST` row plus a province-level `PST`/`QST` row, both with
9072
+ * `stackable: true`, which the checkout charges together. Provinces on HST
9073
+ * carry a single combined row with `stackable: false`.
8969
9074
  */
8970
9075
  async getTaxRates() {
8971
9076
  return this.adminRequest("GET", "/api/v1/tax/rates");
8972
9077
  }
9078
+ /**
9079
+ * List the country tax presets available to apply.
9080
+ * Requires Admin mode (apiKey)
9081
+ */
9082
+ async getTaxPresets() {
9083
+ return this.adminRequest("GET", "/api/v1/tax/presets");
9084
+ }
9085
+ /**
9086
+ * Apply a country's whole tax table in one call, instead of creating a rate
9087
+ * per province by hand. Requires Admin mode (apiKey).
9088
+ *
9089
+ * `CA` writes ten rates: federal GST 5% country-wide, one combined HST row
9090
+ * each for ON/NB/NL/NS/PE, and PST/RST/QST for BC/SK/MB/QC charged on top of
9091
+ * the GST. Alberta and the territories need no row — the GST covers them.
9092
+ *
9093
+ * Throws 409 when the store already has rates for that country; delete those
9094
+ * first if you meant to replace them. Rates land in the Standard tax class.
9095
+ *
9096
+ * Brainerce does not register the store for GST/HST and does not file returns.
9097
+ *
9098
+ * @example
9099
+ * ```typescript
9100
+ * const { created } = await client.applyTaxPreset('CA'); // created === 10
9101
+ * ```
9102
+ */
9103
+ async applyTaxPreset(presetKey) {
9104
+ return this.adminRequest(
9105
+ "POST",
9106
+ `/api/v1/tax/presets/${encodePathSegment(presetKey)}/apply`
9107
+ );
9108
+ }
8973
9109
  /**
8974
9110
  * Get a single tax rate by ID
8975
9111
  * Requires Admin mode (apiKey)
@@ -10397,9 +10533,7 @@ function validateDateAvailabilityConfig(config, fieldType, surface = "checkout")
10397
10533
  (k) => config[k] !== void 0
10398
10534
  );
10399
10535
  if (relativeKeys.length > 0) {
10400
- errors.push(
10401
- `${relativeKeys.join("/")} only apply to checkout fields, not ${surface} fields`
10402
- );
10536
+ errors.push(`${relativeKeys.join("/")} only apply to checkout fields, not ${surface} fields`);
10403
10537
  }
10404
10538
  }
10405
10539
  if (config.blockedWeekdays) {
@@ -10422,7 +10556,9 @@ function validateDateAvailabilityConfig(config, fieldType, surface = "checkout")
10422
10556
  const windowsByWeekday = /* @__PURE__ */ new Map();
10423
10557
  for (const w of config.businessHours) {
10424
10558
  if (!Number.isInteger(w.weekday) || w.weekday < 0 || w.weekday > 6) {
10425
- errors.push(`businessHours.weekday must be an integer 0-6, got ${JSON.stringify(w.weekday)}`);
10559
+ errors.push(
10560
+ `businessHours.weekday must be an integer 0-6, got ${JSON.stringify(w.weekday)}`
10561
+ );
10426
10562
  continue;
10427
10563
  }
10428
10564
  const openValid = TIME_RE.test(w.open);
@@ -10534,7 +10670,8 @@ function addCalendarDays(dateYYYYMMDD, days) {
10534
10670
  function parseDateFieldValue(raw, fieldType, timezone) {
10535
10671
  const str = raw instanceof Date ? Number.isNaN(raw.getTime()) ? "" : raw.toISOString() : typeof raw === "string" ? raw.trim() : "";
10536
10672
  const expected = fieldType === "DATE" ? "expected a calendar date in YYYY-MM-DD format" : "expected an ISO-8601 date/time such as 2026-08-13T13:00:00+03:00";
10537
- if (!str) return { status: "invalid", reason: `"${String(raw)}" is not a valid date \u2014 ${expected}` };
10673
+ if (!str)
10674
+ return { status: "invalid", reason: `"${String(raw)}" is not a valid date \u2014 ${expected}` };
10538
10675
  const dateOnly = DATE_ONLY_RE.exec(str);
10539
10676
  const dateTime = dateOnly ? null : DATE_TIME_RE.exec(str);
10540
10677
  const match = dateOnly ?? dateTime;
@@ -10623,7 +10760,14 @@ function timezoneOffsetMs(utcMillis, timezone) {
10623
10760
  }
10624
10761
  const get = (type) => Number(parts.find((p) => p.type === type)?.value ?? "0");
10625
10762
  const hour = get("hour") === 24 ? 0 : get("hour");
10626
- const asIfUtc = Date.UTC(get("year"), get("month") - 1, get("day"), hour, get("minute"), get("second"));
10763
+ const asIfUtc = Date.UTC(
10764
+ get("year"),
10765
+ get("month") - 1,
10766
+ get("day"),
10767
+ hour,
10768
+ get("minute"),
10769
+ get("second")
10770
+ );
10627
10771
  return asIfUtc - Math.floor(utcMillis / 1e3) * 1e3;
10628
10772
  }
10629
10773
  function isCalendarDateAllowed(dateYYYYMMDD, config, clock) {
package/package.json CHANGED
@@ -1,84 +1,84 @@
1
- {
2
- "name": "brainerce",
3
- "version": "2.0.2",
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
- "./bot": {
15
- "types": "./dist/bot/index.d.ts",
16
- "require": "./dist/bot/index.js",
17
- "import": "./dist/bot/index.mjs"
18
- }
19
- },
20
- "files": [
21
- "dist",
22
- "README.md"
23
- ],
24
- "scripts": {
25
- "build": "tsup src/index.ts --format cjs,esm --dts && tsup src/bot/index.ts --format cjs,esm --dts --out-dir dist/bot && tsup src/bot/bootstrap.ts --format iife --minify --out-dir dist/bot",
26
- "type-check": "tsc --noEmit",
27
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
28
- "lint": "eslint \"src/**/*.ts\"",
29
- "test": "vitest run",
30
- "test:watch": "vitest",
31
- "release": "pnpm build && node ../../scripts/publish-workspace-package.js .",
32
- "prepublishOnly": "pnpm build"
33
- },
34
- "keywords": [
35
- "brainerce",
36
- "e-commerce",
37
- "ecommerce",
38
- "sdk",
39
- "vibe-coding",
40
- "vibe-coded",
41
- "ai-commerce",
42
- "storefront",
43
- "headless-commerce",
44
- "multi-platform",
45
- "shopify",
46
- "tiktok",
47
- "cursor",
48
- "lovable",
49
- "v0",
50
- "cart",
51
- "checkout",
52
- "products",
53
- "sync"
54
- ],
55
- "author": "Brainerce",
56
- "license": "MIT",
57
- "repository": {
58
- "type": "git",
59
- "url": "https://github.com/brainerce/brainerce.git",
60
- "directory": "packages/sdk"
61
- },
62
- "homepage": "https://brainerce.com",
63
- "bugs": {
64
- "url": "https://github.com/brainerce/brainerce/issues"
65
- },
66
- "devDependencies": {
67
- "@brainerce/types": "workspace:*",
68
- "@types/node": "^25.0.3",
69
- "@typescript-eslint/eslint-plugin": "^8.50.1",
70
- "@typescript-eslint/parser": "^8.50.1",
71
- "eslint": "^9.39.2",
72
- "tsup": "^8.0.0",
73
- "typescript": "^5.3.0",
74
- "vitest": "^1.0.0"
75
- },
76
- "peerDependencies": {
77
- "typescript": ">=4.7.0"
78
- },
79
- "peerDependenciesMeta": {
80
- "typescript": {
81
- "optional": true
82
- }
83
- }
84
- }
1
+ {
2
+ "name": "brainerce",
3
+ "version": "2.1.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
+ "./bot": {
15
+ "types": "./dist/bot/index.d.ts",
16
+ "require": "./dist/bot/index.js",
17
+ "import": "./dist/bot/index.mjs"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup src/index.ts --format cjs,esm --dts && tsup src/bot/index.ts --format cjs,esm --dts --out-dir dist/bot && tsup src/bot/bootstrap.ts --format iife --minify --out-dir dist/bot",
26
+ "type-check": "tsc --noEmit",
27
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
28
+ "lint": "eslint \"src/**/*.ts\"",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
31
+ "release": "pnpm build && node ../../scripts/publish-workspace-package.js .",
32
+ "prepublishOnly": "pnpm build"
33
+ },
34
+ "keywords": [
35
+ "brainerce",
36
+ "e-commerce",
37
+ "ecommerce",
38
+ "sdk",
39
+ "vibe-coding",
40
+ "vibe-coded",
41
+ "ai-commerce",
42
+ "storefront",
43
+ "headless-commerce",
44
+ "multi-platform",
45
+ "shopify",
46
+ "tiktok",
47
+ "cursor",
48
+ "lovable",
49
+ "v0",
50
+ "cart",
51
+ "checkout",
52
+ "products",
53
+ "sync"
54
+ ],
55
+ "author": "Brainerce",
56
+ "license": "MIT",
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "https://github.com/brainerce/brainerce.git",
60
+ "directory": "packages/sdk"
61
+ },
62
+ "homepage": "https://brainerce.com",
63
+ "bugs": {
64
+ "url": "https://github.com/brainerce/brainerce/issues"
65
+ },
66
+ "devDependencies": {
67
+ "@brainerce/types": "workspace:*",
68
+ "@types/node": "^25.0.3",
69
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
70
+ "@typescript-eslint/parser": "^8.50.1",
71
+ "eslint": "^9.39.2",
72
+ "tsup": "^8.0.0",
73
+ "typescript": "^5.3.0",
74
+ "vitest": "^1.0.0"
75
+ },
76
+ "peerDependencies": {
77
+ "typescript": ">=4.7.0"
78
+ },
79
+ "peerDependenciesMeta": {
80
+ "typescript": {
81
+ "optional": true
82
+ }
83
+ }
84
+ }