brainerce 1.28.1 → 1.31.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.d.ts CHANGED
@@ -2736,6 +2736,37 @@ interface VariantInventoryResponse {
2736
2736
  canPurchase: boolean;
2737
2737
  lastInventorySyncAt?: string | null;
2738
2738
  }
2739
+ /**
2740
+ * A media-library asset returned by the admin media endpoints
2741
+ * (`/v1/media/*`). The CDN `url` is what you store in `images[].url` on a
2742
+ * product. Requires an admin API key with `media:read` / `media:write`.
2743
+ */
2744
+ interface MediaAsset {
2745
+ id: string;
2746
+ url: string;
2747
+ key: string;
2748
+ thumbnailUrl: string | null;
2749
+ mimeType: string;
2750
+ width: number | null;
2751
+ height: number | null;
2752
+ size: number;
2753
+ /** Display name / title in the media library. */
2754
+ name: string;
2755
+ /** Accessibility alt text. */
2756
+ alt: string | null;
2757
+ createdAt: string;
2758
+ }
2759
+ /** Query params for `listMedia`. */
2760
+ interface ListMediaParams {
2761
+ page?: number;
2762
+ limit?: number;
2763
+ search?: string;
2764
+ }
2765
+ /** Body for `updateMediaAsset` — default metadata. */
2766
+ interface UpdateMediaAssetInput {
2767
+ alt?: string;
2768
+ name?: string;
2769
+ }
2739
2770
  type RefundType = 'full' | 'partial';
2740
2771
  interface RefundLineItem {
2741
2772
  lineItemId: string;
@@ -3807,6 +3838,35 @@ interface PublicRegionPaymentProvider {
3807
3838
  interface PublicRegionDetail extends PublicRegion {
3808
3839
  paymentProviders: PublicRegionPaymentProvider[];
3809
3840
  }
3841
+ /**
3842
+ * Server-side region resolution for a buyer country (storefront seam).
3843
+ * `matched=true` → the country was explicitly listed by a region. `false` →
3844
+ * fell back to the default region (or `region=null` when no default exists).
3845
+ */
3846
+ interface AutoRegionResponse {
3847
+ region: PublicRegion | null;
3848
+ matched: boolean;
3849
+ /** Upper-cased ISO-3166-1 alpha-2. Empty string when caller omitted `country`. */
3850
+ country: string;
3851
+ }
3852
+ /**
3853
+ * Non-binding tax preview for PDP / PLP / cart. The authoritative calculation
3854
+ * still runs at checkout against the full shipping address (state / postal /
3855
+ * per-class). Render with an "Estimate" affordance.
3856
+ */
3857
+ interface TaxEstimateResponse {
3858
+ appliesTax: boolean;
3859
+ /** Percent — e.g. 18 for 18%. `null` when no matching rule. */
3860
+ rate: number | null;
3861
+ rateName: string | null;
3862
+ /** Tax portion of `subtotal` at the store's `pricesIncludeTax` mode. */
3863
+ estimatedTax: number;
3864
+ pricesIncludeTax: boolean;
3865
+ /** Store currency — the cart / order currency, unchanged by FX display overlay. */
3866
+ currency: string;
3867
+ /** Disclaimer copy — always present to surface the "preview, not binding" nature. */
3868
+ note: string;
3869
+ }
3810
3870
  interface CreateRegionDto {
3811
3871
  name: string;
3812
3872
  /** ISO 4217 */
@@ -5553,6 +5613,50 @@ declare class BrainerceClient {
5553
5613
  * ```
5554
5614
  */
5555
5615
  updateVariantInventory(productId: string, variantId: string, data: UpdateVariantInventoryDto): Promise<VariantInventoryResponse>;
5616
+ /**
5617
+ * Upload a file, or ingest a remote image URL, into the store's media
5618
+ * library. Requires an admin API key with the `media:write` scope. Returns
5619
+ * the created asset — store `asset.url` in `images[].url` on a product.
5620
+ *
5621
+ * @example
5622
+ * ```typescript
5623
+ * // Upload a File/Blob:
5624
+ * const asset = await client.uploadMedia(fileInput.files[0]);
5625
+ * // …or ingest by URL (fetched server-side via the SSRF-safe downloader):
5626
+ * const asset = await client.uploadMedia({ sourceUrl: 'https://example.com/photo.jpg' });
5627
+ * await client.updateProduct('prod_123', {
5628
+ * images: [{ url: asset.url, position: 0, isMain: true }],
5629
+ * });
5630
+ * ```
5631
+ */
5632
+ uploadMedia(input: File | Blob | {
5633
+ sourceUrl: string;
5634
+ }): Promise<MediaAsset>;
5635
+ /**
5636
+ * List media-library assets (paginated). Requires `media:read`.
5637
+ *
5638
+ * @example
5639
+ * ```typescript
5640
+ * const { data, meta } = await client.listMedia({ page: 1, limit: 50, search: 'hero' });
5641
+ * ```
5642
+ */
5643
+ listMedia(params?: ListMediaParams): Promise<PaginatedResponse<MediaAsset>>;
5644
+ /**
5645
+ * Get a single media asset by ID. Requires `media:read`.
5646
+ */
5647
+ getMedia(id: string): Promise<MediaAsset>;
5648
+ /**
5649
+ * Update an asset's default metadata (`alt` / `name`). Requires `media:write`.
5650
+ */
5651
+ updateMediaAsset(id: string, data: UpdateMediaAssetInput): Promise<MediaAsset>;
5652
+ /**
5653
+ * Delete a media asset — soft-deletes it and removes its key from every
5654
+ * product/variant/category/brand/store/modifier that referenced it.
5655
+ * Requires `media:write`.
5656
+ */
5657
+ deleteMedia(id: string): Promise<{
5658
+ success: boolean;
5659
+ }>;
5556
5660
  /**
5557
5661
  * Get a list of orders with pagination
5558
5662
  */
@@ -8616,6 +8720,33 @@ declare class BrainerceClient {
8616
8720
  * `countries` includes `country`, else the default region, else null.
8617
8721
  */
8618
8722
  detectRegion(country: string, regions: Array<Region | PublicRegion>): Region | PublicRegion | null;
8723
+ /**
8724
+ * Server-side region resolution in one round trip (storefront seam). Pair
8725
+ * with the country your edge runtime extracts — Cloudflare `CF-IPCountry`,
8726
+ * Vercel `request.geo?.country`, Fastly `client-geo-country`, etc.
8727
+ *
8728
+ * Brainerce does NOT derive the country from the request IP server-side
8729
+ * because the storefront server is what reaches the backend (not the end-
8730
+ * customer). The storefront must extract + forward the country.
8731
+ *
8732
+ * Returns `{ region, matched, country }` — `matched=true` means the country
8733
+ * was explicitly listed by a region; `false` means we fell back to the
8734
+ * default region (or `region=null` if no default exists either).
8735
+ */
8736
+ getAutoRegion(country?: string): Promise<AutoRegionResponse>;
8737
+ /**
8738
+ * Non-binding tax preview for PDP / PLP / cart. Pass the buyer's country
8739
+ * (from your edge runtime — same source as `getAutoRegion`) and the current
8740
+ * items subtotal in the store currency. The authoritative tax still runs
8741
+ * at checkout — render with an "Estimate" affordance.
8742
+ *
8743
+ * Returns `appliesTax=false` when tax is disabled, the country is missing,
8744
+ * or no active rate covers it.
8745
+ */
8746
+ estimateTax(params: {
8747
+ country?: string;
8748
+ subtotal: number;
8749
+ }): Promise<TaxEstimateResponse>;
8619
8750
  /**
8620
8751
  * List the store's tax classes (public, no apiKey — storeId mode). Storefront-
8621
8752
  * safe fields only (id/name/slug/description/isDefault) for transparency UIs
package/dist/index.js CHANGED
@@ -1404,6 +1404,70 @@ var BrainerceClient = class {
1404
1404
  data
1405
1405
  );
1406
1406
  }
1407
+ // -------------------- Media Library (Admin) --------------------
1408
+ /**
1409
+ * Upload a file, or ingest a remote image URL, into the store's media
1410
+ * library. Requires an admin API key with the `media:write` scope. Returns
1411
+ * the created asset — store `asset.url` in `images[].url` on a product.
1412
+ *
1413
+ * @example
1414
+ * ```typescript
1415
+ * // Upload a File/Blob:
1416
+ * const asset = await client.uploadMedia(fileInput.files[0]);
1417
+ * // …or ingest by URL (fetched server-side via the SSRF-safe downloader):
1418
+ * const asset = await client.uploadMedia({ sourceUrl: 'https://example.com/photo.jpg' });
1419
+ * await client.updateProduct('prod_123', {
1420
+ * images: [{ url: asset.url, position: 0, isMain: true }],
1421
+ * });
1422
+ * ```
1423
+ */
1424
+ async uploadMedia(input) {
1425
+ const formData = new FormData();
1426
+ if (typeof input === "object" && "sourceUrl" in input) {
1427
+ formData.append("sourceUrl", input.sourceUrl);
1428
+ } else {
1429
+ formData.append("file", input);
1430
+ }
1431
+ return this.adminRequest("POST", "/api/v1/media", formData);
1432
+ }
1433
+ /**
1434
+ * List media-library assets (paginated). Requires `media:read`.
1435
+ *
1436
+ * @example
1437
+ * ```typescript
1438
+ * const { data, meta } = await client.listMedia({ page: 1, limit: 50, search: 'hero' });
1439
+ * ```
1440
+ */
1441
+ async listMedia(params) {
1442
+ return this.adminRequest("GET", "/api/v1/media", void 0, {
1443
+ page: params?.page,
1444
+ limit: params?.limit,
1445
+ search: params?.search
1446
+ });
1447
+ }
1448
+ /**
1449
+ * Get a single media asset by ID. Requires `media:read`.
1450
+ */
1451
+ async getMedia(id) {
1452
+ return this.adminRequest("GET", `/api/v1/media/${encodePathSegment(id)}`);
1453
+ }
1454
+ /**
1455
+ * Update an asset's default metadata (`alt` / `name`). Requires `media:write`.
1456
+ */
1457
+ async updateMediaAsset(id, data) {
1458
+ return this.adminRequest("PATCH", `/api/v1/media/${encodePathSegment(id)}`, data);
1459
+ }
1460
+ /**
1461
+ * Delete a media asset — soft-deletes it and removes its key from every
1462
+ * product/variant/category/brand/store/modifier that referenced it.
1463
+ * Requires `media:write`.
1464
+ */
1465
+ async deleteMedia(id) {
1466
+ return this.adminRequest(
1467
+ "DELETE",
1468
+ `/api/v1/media/${encodePathSegment(id)}`
1469
+ );
1470
+ }
1407
1471
  // -------------------- Orders --------------------
1408
1472
  /**
1409
1473
  * Get a list of orders with pagination
@@ -7054,6 +7118,44 @@ var BrainerceClient = class {
7054
7118
  const code = country.toUpperCase();
7055
7119
  return regions.find((r) => r.countries.includes(code)) ?? regions.find((r) => r.isDefault) ?? null;
7056
7120
  }
7121
+ /**
7122
+ * Server-side region resolution in one round trip (storefront seam). Pair
7123
+ * with the country your edge runtime extracts — Cloudflare `CF-IPCountry`,
7124
+ * Vercel `request.geo?.country`, Fastly `client-geo-country`, etc.
7125
+ *
7126
+ * Brainerce does NOT derive the country from the request IP server-side
7127
+ * because the storefront server is what reaches the backend (not the end-
7128
+ * customer). The storefront must extract + forward the country.
7129
+ *
7130
+ * Returns `{ region, matched, country }` — `matched=true` means the country
7131
+ * was explicitly listed by a region; `false` means we fell back to the
7132
+ * default region (or `region=null` if no default exists either).
7133
+ */
7134
+ async getAutoRegion(country) {
7135
+ return this.storefrontRequest(
7136
+ "GET",
7137
+ "/regions/auto",
7138
+ void 0,
7139
+ country ? { country } : void 0
7140
+ );
7141
+ }
7142
+ /**
7143
+ * Non-binding tax preview for PDP / PLP / cart. Pass the buyer's country
7144
+ * (from your edge runtime — same source as `getAutoRegion`) and the current
7145
+ * items subtotal in the store currency. The authoritative tax still runs
7146
+ * at checkout — render with an "Estimate" affordance.
7147
+ *
7148
+ * Returns `appliesTax=false` when tax is disabled, the country is missing,
7149
+ * or no active rate covers it.
7150
+ */
7151
+ async estimateTax(params) {
7152
+ return this.storefrontRequest(
7153
+ "GET",
7154
+ "/tax/estimate",
7155
+ void 0,
7156
+ params.country ? { country: params.country, subtotal: params.subtotal } : { subtotal: params.subtotal }
7157
+ );
7158
+ }
7057
7159
  // -------------------- Tax Classes (Storefront mode, public — no apiKey) --------------------
7058
7160
  /**
7059
7161
  * List the store's tax classes (public, no apiKey — storeId mode). Storefront-
package/dist/index.mjs CHANGED
@@ -1334,6 +1334,70 @@ var BrainerceClient = class {
1334
1334
  data
1335
1335
  );
1336
1336
  }
1337
+ // -------------------- Media Library (Admin) --------------------
1338
+ /**
1339
+ * Upload a file, or ingest a remote image URL, into the store's media
1340
+ * library. Requires an admin API key with the `media:write` scope. Returns
1341
+ * the created asset — store `asset.url` in `images[].url` on a product.
1342
+ *
1343
+ * @example
1344
+ * ```typescript
1345
+ * // Upload a File/Blob:
1346
+ * const asset = await client.uploadMedia(fileInput.files[0]);
1347
+ * // …or ingest by URL (fetched server-side via the SSRF-safe downloader):
1348
+ * const asset = await client.uploadMedia({ sourceUrl: 'https://example.com/photo.jpg' });
1349
+ * await client.updateProduct('prod_123', {
1350
+ * images: [{ url: asset.url, position: 0, isMain: true }],
1351
+ * });
1352
+ * ```
1353
+ */
1354
+ async uploadMedia(input) {
1355
+ const formData = new FormData();
1356
+ if (typeof input === "object" && "sourceUrl" in input) {
1357
+ formData.append("sourceUrl", input.sourceUrl);
1358
+ } else {
1359
+ formData.append("file", input);
1360
+ }
1361
+ return this.adminRequest("POST", "/api/v1/media", formData);
1362
+ }
1363
+ /**
1364
+ * List media-library assets (paginated). Requires `media:read`.
1365
+ *
1366
+ * @example
1367
+ * ```typescript
1368
+ * const { data, meta } = await client.listMedia({ page: 1, limit: 50, search: 'hero' });
1369
+ * ```
1370
+ */
1371
+ async listMedia(params) {
1372
+ return this.adminRequest("GET", "/api/v1/media", void 0, {
1373
+ page: params?.page,
1374
+ limit: params?.limit,
1375
+ search: params?.search
1376
+ });
1377
+ }
1378
+ /**
1379
+ * Get a single media asset by ID. Requires `media:read`.
1380
+ */
1381
+ async getMedia(id) {
1382
+ return this.adminRequest("GET", `/api/v1/media/${encodePathSegment(id)}`);
1383
+ }
1384
+ /**
1385
+ * Update an asset's default metadata (`alt` / `name`). Requires `media:write`.
1386
+ */
1387
+ async updateMediaAsset(id, data) {
1388
+ return this.adminRequest("PATCH", `/api/v1/media/${encodePathSegment(id)}`, data);
1389
+ }
1390
+ /**
1391
+ * Delete a media asset — soft-deletes it and removes its key from every
1392
+ * product/variant/category/brand/store/modifier that referenced it.
1393
+ * Requires `media:write`.
1394
+ */
1395
+ async deleteMedia(id) {
1396
+ return this.adminRequest(
1397
+ "DELETE",
1398
+ `/api/v1/media/${encodePathSegment(id)}`
1399
+ );
1400
+ }
1337
1401
  // -------------------- Orders --------------------
1338
1402
  /**
1339
1403
  * Get a list of orders with pagination
@@ -6984,6 +7048,44 @@ var BrainerceClient = class {
6984
7048
  const code = country.toUpperCase();
6985
7049
  return regions.find((r) => r.countries.includes(code)) ?? regions.find((r) => r.isDefault) ?? null;
6986
7050
  }
7051
+ /**
7052
+ * Server-side region resolution in one round trip (storefront seam). Pair
7053
+ * with the country your edge runtime extracts — Cloudflare `CF-IPCountry`,
7054
+ * Vercel `request.geo?.country`, Fastly `client-geo-country`, etc.
7055
+ *
7056
+ * Brainerce does NOT derive the country from the request IP server-side
7057
+ * because the storefront server is what reaches the backend (not the end-
7058
+ * customer). The storefront must extract + forward the country.
7059
+ *
7060
+ * Returns `{ region, matched, country }` — `matched=true` means the country
7061
+ * was explicitly listed by a region; `false` means we fell back to the
7062
+ * default region (or `region=null` if no default exists either).
7063
+ */
7064
+ async getAutoRegion(country) {
7065
+ return this.storefrontRequest(
7066
+ "GET",
7067
+ "/regions/auto",
7068
+ void 0,
7069
+ country ? { country } : void 0
7070
+ );
7071
+ }
7072
+ /**
7073
+ * Non-binding tax preview for PDP / PLP / cart. Pass the buyer's country
7074
+ * (from your edge runtime — same source as `getAutoRegion`) and the current
7075
+ * items subtotal in the store currency. The authoritative tax still runs
7076
+ * at checkout — render with an "Estimate" affordance.
7077
+ *
7078
+ * Returns `appliesTax=false` when tax is disabled, the country is missing,
7079
+ * or no active rate covers it.
7080
+ */
7081
+ async estimateTax(params) {
7082
+ return this.storefrontRequest(
7083
+ "GET",
7084
+ "/tax/estimate",
7085
+ void 0,
7086
+ params.country ? { country: params.country, subtotal: params.subtotal } : { subtotal: params.subtotal }
7087
+ );
7088
+ }
6987
7089
  // -------------------- Tax Classes (Storefront mode, public — no apiKey) --------------------
6988
7090
  /**
6989
7091
  * List the store's tax classes (public, no apiKey — storeId mode). Storefront-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainerce",
3
- "version": "1.28.1",
3
+ "version": "1.31.0",
4
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
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -10,6 +10,11 @@
10
10
  "types": "./dist/index.d.ts",
11
11
  "require": "./dist/index.js",
12
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"
13
18
  }
14
19
  },
15
20
  "files": [
@@ -17,7 +22,7 @@
17
22
  "README.md"
18
23
  ],
19
24
  "scripts": {
20
- "build": "tsup src/index.ts --format cjs,esm --dts",
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",
21
26
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
22
27
  "lint": "eslint \"src/**/*.ts\"",
23
28
  "test": "vitest run",