brainerce 1.27.1 → 1.28.1

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.js CHANGED
@@ -37,7 +37,10 @@ __export(index_exports, {
37
37
  createWebhookHandler: () => createWebhookHandler,
38
38
  deriveSeoDescription: () => deriveSeoDescription,
39
39
  enableDevGuards: () => enableDevGuards,
40
+ formatMoney: () => formatMoney,
40
41
  formatPrice: () => formatPrice,
42
+ formatProductPrice: () => formatProductPrice,
43
+ formatVariantPrice: () => formatVariantPrice,
41
44
  getCartItemImage: () => getCartItemImage,
42
45
  getCartItemName: () => getCartItemName,
43
46
  getCartTotals: () => getCartTotals,
@@ -202,6 +205,26 @@ function encodePathSegment(value) {
202
205
  }
203
206
  return encodeURIComponent(normalized);
204
207
  }
208
+ var MAX_RETRY_AFTER_MS = 6e4;
209
+ function parseRetryAfterMs(response) {
210
+ const header = response.headers.get("retry-after");
211
+ if (!header) return null;
212
+ const trimmed = header.trim();
213
+ if (!trimmed) return null;
214
+ if (/^\d+$/.test(trimmed)) {
215
+ const seconds = parseInt(trimmed, 10);
216
+ if (!Number.isFinite(seconds) || seconds < 0) return null;
217
+ return Math.min(seconds * 1e3, MAX_RETRY_AFTER_MS);
218
+ }
219
+ const target = Date.parse(trimmed);
220
+ if (Number.isNaN(target)) return null;
221
+ const deltaMs = target - Date.now();
222
+ if (deltaMs <= 0) return 0;
223
+ return Math.min(deltaMs, MAX_RETRY_AFTER_MS);
224
+ }
225
+ function sleep(ms) {
226
+ return new Promise((resolve) => setTimeout(resolve, ms));
227
+ }
205
228
  var BrainerceClient = class {
206
229
  constructor(options) {
207
230
  this.customerToken = null;
@@ -635,7 +658,7 @@ var BrainerceClient = class {
635
658
  /**
636
659
  * Make a request to the Admin API (requires apiKey)
637
660
  */
638
- async adminRequest(method, path, body, queryParams) {
661
+ async adminRequest(method, path, body, queryParams, responseType = "json") {
639
662
  if (!this.apiKey) {
640
663
  throw new BrainerceError(
641
664
  "This operation requires an API key. Initialize with apiKey instead of storeId.",
@@ -650,52 +673,64 @@ var BrainerceClient = class {
650
673
  }
651
674
  });
652
675
  }
653
- const controller = new AbortController();
654
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
655
- try {
656
- const headers = {
657
- Authorization: `Bearer ${this.apiKey}`,
658
- "Content-Type": "application/json",
659
- "X-SDK-Version": SDK_VERSION,
660
- "ngrok-skip-browser-warning": "true"
661
- };
662
- if (this.origin) {
663
- headers["Origin"] = this.origin;
664
- }
665
- if (this.locale) {
666
- headers["Accept-Language"] = this.locale;
667
- }
668
- const response = await fetch(url.toString(), {
669
- method,
670
- headers,
671
- body: body ? JSON.stringify(body) : void 0,
672
- signal: controller.signal
673
- });
674
- clearTimeout(timeoutId);
675
- if (!response.ok) {
676
- const errorData = await response.json().catch(() => ({}));
677
- throw new BrainerceError(
678
- errorData.message || `Request failed with status ${response.status}`,
679
- response.status,
680
- errorData
681
- );
682
- }
683
- const text = await response.text();
684
- if (!text) return {};
685
- return JSON.parse(text);
686
- } catch (error) {
687
- clearTimeout(timeoutId);
688
- if (error instanceof BrainerceError) {
689
- throw error;
690
- }
691
- if (error instanceof Error) {
692
- if (error.name === "AbortError") {
693
- throw new BrainerceError("Request timeout", 408);
676
+ const headers = {
677
+ Authorization: `Bearer ${this.apiKey}`,
678
+ "Content-Type": "application/json",
679
+ "X-SDK-Version": SDK_VERSION,
680
+ "ngrok-skip-browser-warning": "true"
681
+ };
682
+ if (this.origin) {
683
+ headers["Origin"] = this.origin;
684
+ }
685
+ if (this.locale) {
686
+ headers["Accept-Language"] = this.locale;
687
+ }
688
+ for (let attempt = 0; attempt < 2; attempt++) {
689
+ const controller = new AbortController();
690
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
691
+ try {
692
+ const response = await fetch(url.toString(), {
693
+ method,
694
+ headers,
695
+ body: body ? JSON.stringify(body) : void 0,
696
+ signal: controller.signal
697
+ });
698
+ clearTimeout(timeoutId);
699
+ if (response.status === 429 && attempt === 0) {
700
+ const retryAfterMs = parseRetryAfterMs(response);
701
+ if (retryAfterMs !== null) {
702
+ await response.text().catch(() => void 0);
703
+ await sleep(retryAfterMs);
704
+ continue;
705
+ }
694
706
  }
695
- throw new BrainerceError(error.message, 0);
707
+ if (!response.ok) {
708
+ const errorData = await response.json().catch(() => ({}));
709
+ throw new BrainerceError(
710
+ errorData.message || `Request failed with status ${response.status}`,
711
+ response.status,
712
+ errorData
713
+ );
714
+ }
715
+ const text = await response.text();
716
+ if (responseType === "text") return text;
717
+ if (!text) return {};
718
+ return JSON.parse(text);
719
+ } catch (error) {
720
+ clearTimeout(timeoutId);
721
+ if (error instanceof BrainerceError) {
722
+ throw error;
723
+ }
724
+ if (error instanceof Error) {
725
+ if (error.name === "AbortError") {
726
+ throw new BrainerceError("Request timeout", 408);
727
+ }
728
+ throw new BrainerceError(error.message, 0);
729
+ }
730
+ throw new BrainerceError("Unknown error occurred", 0);
696
731
  }
697
- throw new BrainerceError("Unknown error occurred", 0);
698
732
  }
733
+ throw new BrainerceError("Rate limited (max retries exceeded)", 429);
699
734
  }
700
735
  /**
701
736
  * Make a request to the Vibe-Coded API (public, uses connectionId)
@@ -704,7 +739,7 @@ var BrainerceClient = class {
704
739
  if (!this.connectionId) {
705
740
  throw new BrainerceError("connectionId is required for vibe-coded requests", 400);
706
741
  }
707
- const url = new URL(`${this.baseUrl}/api/vc/${this.connectionId}${path}`);
742
+ const url = new URL(`${this.baseUrl}/api/vc/${encodePathSegment(this.connectionId)}${path}`);
708
743
  if (queryParams) {
709
744
  Object.entries(queryParams).forEach(([key, value]) => {
710
745
  if (value !== void 0) {
@@ -712,70 +747,81 @@ var BrainerceClient = class {
712
747
  }
713
748
  });
714
749
  }
715
- const controller = new AbortController();
716
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
717
- try {
718
- const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
719
- const headers = {
720
- "X-SDK-Version": SDK_VERSION,
721
- "ngrok-skip-browser-warning": "true"
722
- };
723
- if (!isFormData) {
724
- headers["Content-Type"] = "application/json";
725
- }
726
- if (this.origin) {
727
- headers["Origin"] = this.origin;
728
- }
729
- if (this.locale) {
730
- headers["Accept-Language"] = this.locale;
731
- }
732
- if (headerOverrides) {
733
- Object.assign(headers, headerOverrides);
734
- }
735
- if (this.proxyMode && method !== "GET") {
736
- headers["X-Requested-With"] = "brainerce";
737
- }
738
- if (this.customerToken) {
739
- headers["Authorization"] = `Bearer ${this.customerToken}`;
740
- }
741
- const response = await fetch(url.toString(), {
742
- method,
743
- headers,
744
- body: body ? isFormData ? body : JSON.stringify(body) : void 0,
745
- signal: controller.signal
746
- });
747
- clearTimeout(timeoutId);
748
- if (!response.ok) {
749
- const errorData = await response.json().catch(() => ({}));
750
- if (response.status === 401 && this.onAuthError) {
751
- this.onAuthError({
752
- message: errorData.message || "Unauthorized",
753
- statusCode: 401,
754
- path
755
- });
750
+ const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
751
+ const headers = {
752
+ "X-SDK-Version": SDK_VERSION,
753
+ "ngrok-skip-browser-warning": "true"
754
+ };
755
+ if (!isFormData) {
756
+ headers["Content-Type"] = "application/json";
757
+ }
758
+ if (this.origin) {
759
+ headers["Origin"] = this.origin;
760
+ }
761
+ if (this.locale) {
762
+ headers["Accept-Language"] = this.locale;
763
+ }
764
+ if (headerOverrides) {
765
+ Object.assign(headers, headerOverrides);
766
+ }
767
+ if (this.proxyMode && method !== "GET") {
768
+ headers["X-Requested-With"] = "brainerce";
769
+ }
770
+ if (this.customerToken) {
771
+ headers["Authorization"] = `Bearer ${this.customerToken}`;
772
+ }
773
+ for (let attempt = 0; attempt < 2; attempt++) {
774
+ const controller = new AbortController();
775
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
776
+ try {
777
+ const response = await fetch(url.toString(), {
778
+ method,
779
+ headers,
780
+ body: body ? isFormData ? body : JSON.stringify(body) : void 0,
781
+ signal: controller.signal
782
+ });
783
+ clearTimeout(timeoutId);
784
+ if (response.status === 429 && attempt === 0) {
785
+ const retryAfterMs = parseRetryAfterMs(response);
786
+ if (retryAfterMs !== null) {
787
+ await response.text().catch(() => void 0);
788
+ await sleep(retryAfterMs);
789
+ continue;
790
+ }
756
791
  }
757
- throw new BrainerceError(
758
- errorData.message || `Request failed with status ${response.status}`,
759
- response.status,
760
- errorData
761
- );
762
- }
763
- const text = await response.text();
764
- if (!text) return {};
765
- return JSON.parse(text);
766
- } catch (error) {
767
- clearTimeout(timeoutId);
768
- if (error instanceof BrainerceError) {
769
- throw error;
770
- }
771
- if (error instanceof Error) {
772
- if (error.name === "AbortError") {
773
- throw new BrainerceError("Request timeout", 408);
792
+ if (!response.ok) {
793
+ const errorData = await response.json().catch(() => ({}));
794
+ if (response.status === 401 && this.onAuthError) {
795
+ this.onAuthError({
796
+ message: errorData.message || "Unauthorized",
797
+ statusCode: 401,
798
+ path
799
+ });
800
+ }
801
+ throw new BrainerceError(
802
+ errorData.message || `Request failed with status ${response.status}`,
803
+ response.status,
804
+ errorData
805
+ );
774
806
  }
775
- throw new BrainerceError(error.message, 0);
807
+ const text = await response.text();
808
+ if (!text) return {};
809
+ return JSON.parse(text);
810
+ } catch (error) {
811
+ clearTimeout(timeoutId);
812
+ if (error instanceof BrainerceError) {
813
+ throw error;
814
+ }
815
+ if (error instanceof Error) {
816
+ if (error.name === "AbortError") {
817
+ throw new BrainerceError("Request timeout", 408);
818
+ }
819
+ throw new BrainerceError(error.message, 0);
820
+ }
821
+ throw new BrainerceError("Unknown error occurred", 0);
776
822
  }
777
- throw new BrainerceError("Unknown error occurred", 0);
778
823
  }
824
+ throw new BrainerceError("Rate limited (max retries exceeded)", 429);
779
825
  }
780
826
  /**
781
827
  * Make a request to the Storefront API (public, uses storeId)
@@ -784,7 +830,7 @@ var BrainerceClient = class {
784
830
  if (!this.storeId) {
785
831
  throw new BrainerceError("storeId is required for storefront requests", 400);
786
832
  }
787
- const url = new URL(`${this.baseUrl}/stores/${this.storeId}${path}`);
833
+ const url = new URL(`${this.baseUrl}/stores/${encodePathSegment(this.storeId)}${path}`);
788
834
  if (queryParams) {
789
835
  Object.entries(queryParams).forEach(([key, value]) => {
790
836
  if (value !== void 0) {
@@ -792,67 +838,78 @@ var BrainerceClient = class {
792
838
  }
793
839
  });
794
840
  }
795
- const controller = new AbortController();
796
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
797
- try {
798
- const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
799
- const headers = {
800
- "X-SDK-Version": SDK_VERSION,
801
- "ngrok-skip-browser-warning": "true"
802
- };
803
- if (!isFormData) {
804
- headers["Content-Type"] = "application/json";
805
- }
806
- if (this.origin) {
807
- headers["Origin"] = this.origin;
808
- }
809
- if (this.locale) {
810
- headers["Accept-Language"] = this.locale;
811
- }
812
- if (headerOverrides) {
813
- Object.assign(headers, headerOverrides);
814
- }
815
- if (this.customerToken) {
816
- headers["Authorization"] = `Bearer ${this.customerToken}`;
817
- }
818
- const response = await fetch(url.toString(), {
819
- method,
820
- headers,
821
- body: body ? isFormData ? body : JSON.stringify(body) : void 0,
822
- signal: controller.signal
823
- });
824
- clearTimeout(timeoutId);
825
- if (!response.ok) {
826
- const errorData = await response.json().catch(() => ({}));
827
- if (response.status === 401 && this.onAuthError) {
828
- this.onAuthError({
829
- message: errorData.message || "Unauthorized",
830
- statusCode: 401,
831
- path
832
- });
841
+ const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
842
+ const headers = {
843
+ "X-SDK-Version": SDK_VERSION,
844
+ "ngrok-skip-browser-warning": "true"
845
+ };
846
+ if (!isFormData) {
847
+ headers["Content-Type"] = "application/json";
848
+ }
849
+ if (this.origin) {
850
+ headers["Origin"] = this.origin;
851
+ }
852
+ if (this.locale) {
853
+ headers["Accept-Language"] = this.locale;
854
+ }
855
+ if (headerOverrides) {
856
+ Object.assign(headers, headerOverrides);
857
+ }
858
+ if (this.customerToken) {
859
+ headers["Authorization"] = `Bearer ${this.customerToken}`;
860
+ }
861
+ for (let attempt = 0; attempt < 2; attempt++) {
862
+ const controller = new AbortController();
863
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
864
+ try {
865
+ const response = await fetch(url.toString(), {
866
+ method,
867
+ headers,
868
+ body: body ? isFormData ? body : JSON.stringify(body) : void 0,
869
+ signal: controller.signal
870
+ });
871
+ clearTimeout(timeoutId);
872
+ if (response.status === 429 && attempt === 0) {
873
+ const retryAfterMs = parseRetryAfterMs(response);
874
+ if (retryAfterMs !== null) {
875
+ await response.text().catch(() => void 0);
876
+ await sleep(retryAfterMs);
877
+ continue;
878
+ }
833
879
  }
834
- throw new BrainerceError(
835
- errorData.message || `Request failed with status ${response.status}`,
836
- response.status,
837
- errorData
838
- );
839
- }
840
- const text = await response.text();
841
- if (!text) return {};
842
- return JSON.parse(text);
843
- } catch (error) {
844
- clearTimeout(timeoutId);
845
- if (error instanceof BrainerceError) {
846
- throw error;
847
- }
848
- if (error instanceof Error) {
849
- if (error.name === "AbortError") {
850
- throw new BrainerceError("Request timeout", 408);
880
+ if (!response.ok) {
881
+ const errorData = await response.json().catch(() => ({}));
882
+ if (response.status === 401 && this.onAuthError) {
883
+ this.onAuthError({
884
+ message: errorData.message || "Unauthorized",
885
+ statusCode: 401,
886
+ path
887
+ });
888
+ }
889
+ throw new BrainerceError(
890
+ errorData.message || `Request failed with status ${response.status}`,
891
+ response.status,
892
+ errorData
893
+ );
851
894
  }
852
- throw new BrainerceError(error.message, 0);
895
+ const text = await response.text();
896
+ if (!text) return {};
897
+ return JSON.parse(text);
898
+ } catch (error) {
899
+ clearTimeout(timeoutId);
900
+ if (error instanceof BrainerceError) {
901
+ throw error;
902
+ }
903
+ if (error instanceof Error) {
904
+ if (error.name === "AbortError") {
905
+ throw new BrainerceError("Request timeout", 408);
906
+ }
907
+ throw new BrainerceError(error.message, 0);
908
+ }
909
+ throw new BrainerceError("Unknown error occurred", 0);
853
910
  }
854
- throw new BrainerceError("Unknown error occurred", 0);
855
911
  }
912
+ throw new BrainerceError("Rate limited (max retries exceeded)", 429);
856
913
  }
857
914
  /**
858
915
  * Smart request - uses storefront or admin API based on client mode
@@ -942,6 +999,7 @@ var BrainerceClient = class {
942
999
  // Admin-only params
943
1000
  type: params?.type
944
1001
  };
1002
+ const queryParamsWithRegion = params?.regionId ? { ...queryParams, regionId: params.regionId } : queryParams;
945
1003
  if (this.isVibeCodedMode()) {
946
1004
  return this.vibeCodedRequest(
947
1005
  "GET",
@@ -955,14 +1013,14 @@ var BrainerceClient = class {
955
1013
  "GET",
956
1014
  "/products",
957
1015
  void 0,
958
- queryParams
1016
+ queryParamsWithRegion
959
1017
  );
960
1018
  }
961
1019
  return this.adminRequest(
962
1020
  "GET",
963
1021
  "/api/v1/products",
964
1022
  void 0,
965
- queryParams
1023
+ queryParamsWithRegion
966
1024
  );
967
1025
  }
968
1026
  /**
@@ -971,10 +1029,11 @@ var BrainerceClient = class {
971
1029
  */
972
1030
  async getProduct(productId, options) {
973
1031
  const headerOverrides = options?.locale ? { "Accept-Language": options.locale } : void 0;
1032
+ const queryParams = options?.regionId ? { regionId: options.regionId } : void 0;
974
1033
  if (this.isVibeCodedMode()) {
975
1034
  return this.vibeCodedRequest(
976
1035
  "GET",
977
- `/products/${productId}`,
1036
+ `/products/${encodePathSegment(productId)}`,
978
1037
  void 0,
979
1038
  void 0,
980
1039
  headerOverrides
@@ -983,13 +1042,18 @@ var BrainerceClient = class {
983
1042
  if (this.storeId && !this.apiKey) {
984
1043
  return this.storefrontRequest(
985
1044
  "GET",
986
- `/products/${productId}`,
987
- void 0,
1045
+ `/products/${encodePathSegment(productId)}`,
988
1046
  void 0,
1047
+ queryParams,
989
1048
  headerOverrides
990
1049
  );
991
1050
  }
992
- return this.adminRequest("GET", `/api/v1/products/${productId}`);
1051
+ return this.adminRequest(
1052
+ "GET",
1053
+ `/api/v1/products/${encodePathSegment(productId)}`,
1054
+ void 0,
1055
+ queryParams
1056
+ );
993
1057
  }
994
1058
  /**
995
1059
  * Get a single product by slug
@@ -1107,7 +1171,7 @@ var BrainerceClient = class {
1107
1171
  */
1108
1172
  async getProductAlternates(productId) {
1109
1173
  if (this.storeId && !this.apiKey) {
1110
- return this.storefrontRequest("GET", `/products/${productId}/alternates`);
1174
+ return this.storefrontRequest("GET", `/products/${encodePathSegment(productId)}/alternates`);
1111
1175
  }
1112
1176
  throw new BrainerceError("getProductAlternates is only available in storefront mode", 400);
1113
1177
  }
@@ -1149,7 +1213,7 @@ var BrainerceClient = class {
1149
1213
  * Update an existing product
1150
1214
  */
1151
1215
  async updateProduct(productId, data) {
1152
- return this.request("PATCH", `/api/v1/products/${productId}`, data);
1216
+ return this.request("PATCH", `/api/v1/products/${encodePathSegment(productId)}`, data);
1153
1217
  }
1154
1218
  /**
1155
1219
  * Delete a product
@@ -1177,7 +1241,7 @@ var BrainerceClient = class {
1177
1241
  const queryParams = options?.platforms?.length ? { platforms: options.platforms.join(",") } : void 0;
1178
1242
  return this.request(
1179
1243
  "DELETE",
1180
- `/api/v1/products/${productId}`,
1244
+ `/api/v1/products/${encodePathSegment(productId)}`,
1181
1245
  void 0,
1182
1246
  queryParams
1183
1247
  );
@@ -1192,7 +1256,10 @@ var BrainerceClient = class {
1192
1256
  * ```
1193
1257
  */
1194
1258
  async convertToVariable(productId) {
1195
- return this.request("PATCH", `/api/v1/products/${productId}/convert-to-variable`);
1259
+ return this.request(
1260
+ "PATCH",
1261
+ `/api/v1/products/${encodePathSegment(productId)}/convert-to-variable`
1262
+ );
1196
1263
  }
1197
1264
  /**
1198
1265
  * Convert a VARIABLE product to SIMPLE product
@@ -1205,7 +1272,10 @@ var BrainerceClient = class {
1205
1272
  * ```
1206
1273
  */
1207
1274
  async convertToSimple(productId) {
1208
- return this.request("PATCH", `/api/v1/products/${productId}/convert-to-simple`);
1275
+ return this.request(
1276
+ "PATCH",
1277
+ `/api/v1/products/${encodePathSegment(productId)}/convert-to-simple`
1278
+ );
1209
1279
  }
1210
1280
  /**
1211
1281
  * Publish a product to specific platforms
@@ -1217,9 +1287,13 @@ var BrainerceClient = class {
1217
1287
  * ```
1218
1288
  */
1219
1289
  async publishProduct(productId, platforms) {
1220
- return this.request("POST", `/api/v1/products/${productId}/publish`, {
1221
- platforms
1222
- });
1290
+ return this.request(
1291
+ "POST",
1292
+ `/api/v1/products/${encodePathSegment(productId)}/publish`,
1293
+ {
1294
+ platforms
1295
+ }
1296
+ );
1223
1297
  }
1224
1298
  // -------------------- Variants --------------------
1225
1299
  /**
@@ -1237,7 +1311,11 @@ var BrainerceClient = class {
1237
1311
  * ```
1238
1312
  */
1239
1313
  async createVariant(productId, data) {
1240
- return this.request("POST", `/api/v1/products/${productId}/variants`, data);
1314
+ return this.request(
1315
+ "POST",
1316
+ `/api/v1/products/${encodePathSegment(productId)}/variants`,
1317
+ data
1318
+ );
1241
1319
  }
1242
1320
  /**
1243
1321
  * Bulk save variants (create, update, delete in one operation)
@@ -1257,7 +1335,7 @@ var BrainerceClient = class {
1257
1335
  async bulkSaveVariants(productId, data) {
1258
1336
  return this.request(
1259
1337
  "POST",
1260
- `/api/v1/products/${productId}/variants/bulk`,
1338
+ `/api/v1/products/${encodePathSegment(productId)}/variants/bulk`,
1261
1339
  data
1262
1340
  );
1263
1341
  }
@@ -1275,7 +1353,7 @@ var BrainerceClient = class {
1275
1353
  async updateVariant(productId, variantId, data) {
1276
1354
  return this.request(
1277
1355
  "PATCH",
1278
- `/api/v1/products/${productId}/variants/${variantId}`,
1356
+ `/api/v1/products/${encodePathSegment(productId)}/variants/${encodePathSegment(variantId)}`,
1279
1357
  data
1280
1358
  );
1281
1359
  }
@@ -1288,7 +1366,10 @@ var BrainerceClient = class {
1288
1366
  * ```
1289
1367
  */
1290
1368
  async deleteVariant(productId, variantId) {
1291
- await this.request("DELETE", `/api/v1/products/${productId}/variants/${variantId}`);
1369
+ await this.request(
1370
+ "DELETE",
1371
+ `/api/v1/products/${encodePathSegment(productId)}/variants/${encodePathSegment(variantId)}`
1372
+ );
1292
1373
  }
1293
1374
  /**
1294
1375
  * Get inventory for a specific variant
@@ -1302,7 +1383,7 @@ var BrainerceClient = class {
1302
1383
  async getVariantInventory(productId, variantId) {
1303
1384
  return this.request(
1304
1385
  "GET",
1305
- `/api/v1/products/${productId}/variants/${variantId}/inventory`
1386
+ `/api/v1/products/${encodePathSegment(productId)}/variants/${encodePathSegment(variantId)}/inventory`
1306
1387
  );
1307
1388
  }
1308
1389
  /**
@@ -1319,7 +1400,7 @@ var BrainerceClient = class {
1319
1400
  async updateVariantInventory(productId, variantId, data) {
1320
1401
  return this.request(
1321
1402
  "PATCH",
1322
- `/api/v1/products/${productId}/variants/${variantId}/inventory`,
1403
+ `/api/v1/products/${encodePathSegment(productId)}/variants/${encodePathSegment(variantId)}/inventory`,
1323
1404
  data
1324
1405
  );
1325
1406
  }
@@ -1343,7 +1424,10 @@ var BrainerceClient = class {
1343
1424
  * Get a single order by ID
1344
1425
  */
1345
1426
  async getOrder(orderId) {
1346
- return this.withGuards(this.request("GET", `/api/v1/orders/${orderId}`), "order");
1427
+ return this.withGuards(
1428
+ this.request("GET", `/api/v1/orders/${encodePathSegment(orderId)}`),
1429
+ "order"
1430
+ );
1347
1431
  }
1348
1432
  /**
1349
1433
  * Create a new order
@@ -1356,7 +1440,7 @@ var BrainerceClient = class {
1356
1440
  * Update an order (e.g., change status)
1357
1441
  */
1358
1442
  async updateOrder(orderId, data) {
1359
- return this.request("PATCH", `/api/v1/orders/${orderId}`, data);
1443
+ return this.request("PATCH", `/api/v1/orders/${encodePathSegment(orderId)}`, data);
1360
1444
  }
1361
1445
  /**
1362
1446
  * Update order status
@@ -1367,7 +1451,9 @@ var BrainerceClient = class {
1367
1451
  * ```
1368
1452
  */
1369
1453
  async updateOrderStatus(orderId, status) {
1370
- return this.request("PATCH", `/api/v1/orders/${orderId}/status`, { status });
1454
+ return this.request("PATCH", `/api/v1/orders/${encodePathSegment(orderId)}/status`, {
1455
+ status
1456
+ });
1371
1457
  }
1372
1458
  /**
1373
1459
  * Update order payment method
@@ -1379,9 +1465,13 @@ var BrainerceClient = class {
1379
1465
  * ```
1380
1466
  */
1381
1467
  async updatePaymentMethod(orderId, paymentMethod) {
1382
- return this.request("PATCH", `/api/v1/orders/${orderId}/payment-method`, {
1383
- paymentMethod
1384
- });
1468
+ return this.request(
1469
+ "PATCH",
1470
+ `/api/v1/orders/${encodePathSegment(orderId)}/payment-method`,
1471
+ {
1472
+ paymentMethod
1473
+ }
1474
+ );
1385
1475
  }
1386
1476
  /**
1387
1477
  * Update order notes
@@ -1392,7 +1482,9 @@ var BrainerceClient = class {
1392
1482
  * ```
1393
1483
  */
1394
1484
  async updateOrderNotes(orderId, notes) {
1395
- return this.request("PATCH", `/api/v1/orders/${orderId}/notes`, { notes });
1485
+ return this.request("PATCH", `/api/v1/orders/${encodePathSegment(orderId)}/notes`, {
1486
+ notes
1487
+ });
1396
1488
  }
1397
1489
  /**
1398
1490
  * Get refunds for an order
@@ -1405,7 +1497,7 @@ var BrainerceClient = class {
1405
1497
  * ```
1406
1498
  */
1407
1499
  async getOrderRefunds(orderId) {
1408
- return this.request("GET", `/api/v1/orders/${orderId}/refunds`);
1500
+ return this.request("GET", `/api/v1/orders/${encodePathSegment(orderId)}/refunds`);
1409
1501
  }
1410
1502
  /**
1411
1503
  * Create a refund for an order
@@ -1432,7 +1524,11 @@ var BrainerceClient = class {
1432
1524
  * ```
1433
1525
  */
1434
1526
  async createRefund(orderId, data) {
1435
- return this.request("POST", `/api/v1/orders/${orderId}/refunds`, data);
1527
+ return this.request(
1528
+ "POST",
1529
+ `/api/v1/orders/${encodePathSegment(orderId)}/refunds`,
1530
+ data
1531
+ );
1436
1532
  }
1437
1533
  /**
1438
1534
  * Update order shipping address
@@ -1452,7 +1548,11 @@ var BrainerceClient = class {
1452
1548
  * ```
1453
1549
  */
1454
1550
  async updateOrderShipping(orderId, data) {
1455
- return this.request("PATCH", `/api/v1/orders/${orderId}/shipping`, data);
1551
+ return this.request(
1552
+ "PATCH",
1553
+ `/api/v1/orders/${encodePathSegment(orderId)}/shipping`,
1554
+ data
1555
+ );
1456
1556
  }
1457
1557
  /**
1458
1558
  * Cancel an order
@@ -1465,7 +1565,7 @@ var BrainerceClient = class {
1465
1565
  * ```
1466
1566
  */
1467
1567
  async cancelOrder(orderId) {
1468
- return this.request("POST", `/api/v1/orders/${orderId}/cancel`);
1568
+ return this.request("POST", `/api/v1/orders/${encodePathSegment(orderId)}/cancel`);
1469
1569
  }
1470
1570
  /**
1471
1571
  * Fulfill an order (mark as shipped)
@@ -1481,7 +1581,11 @@ var BrainerceClient = class {
1481
1581
  * ```
1482
1582
  */
1483
1583
  async fulfillOrder(orderId, data) {
1484
- return this.request("POST", `/api/v1/orders/${orderId}/fulfill`, data || {});
1584
+ return this.request(
1585
+ "POST",
1586
+ `/api/v1/orders/${encodePathSegment(orderId)}/fulfill`,
1587
+ data || {}
1588
+ );
1485
1589
  }
1486
1590
  /**
1487
1591
  * Sync draft orders from connected platforms
@@ -1506,7 +1610,11 @@ var BrainerceClient = class {
1506
1610
  * ```
1507
1611
  */
1508
1612
  async completeDraftOrder(orderId, data) {
1509
- return this.request("POST", `/api/v1/orders/${orderId}/complete-draft`, data || {});
1613
+ return this.request(
1614
+ "POST",
1615
+ `/api/v1/orders/${encodePathSegment(orderId)}/complete-draft`,
1616
+ data || {}
1617
+ );
1510
1618
  }
1511
1619
  /**
1512
1620
  * Send invoice for a draft order
@@ -1523,7 +1631,7 @@ var BrainerceClient = class {
1523
1631
  async sendDraftInvoice(orderId, data) {
1524
1632
  return this.request(
1525
1633
  "POST",
1526
- `/api/v1/orders/${orderId}/send-invoice`,
1634
+ `/api/v1/orders/${encodePathSegment(orderId)}/send-invoice`,
1527
1635
  data || {}
1528
1636
  );
1529
1637
  }
@@ -1536,7 +1644,7 @@ var BrainerceClient = class {
1536
1644
  * ```
1537
1645
  */
1538
1646
  async deleteDraftOrder(orderId) {
1539
- await this.request("DELETE", `/api/v1/orders/${orderId}/draft`);
1647
+ await this.request("DELETE", `/api/v1/orders/${encodePathSegment(orderId)}/draft`);
1540
1648
  }
1541
1649
  /**
1542
1650
  * Update a draft order
@@ -1559,7 +1667,7 @@ var BrainerceClient = class {
1559
1667
  * ```
1560
1668
  */
1561
1669
  async updateDraftOrder(orderId, data) {
1562
- return this.request("PATCH", `/api/v1/orders/${orderId}/draft`, data);
1670
+ return this.request("PATCH", `/api/v1/orders/${encodePathSegment(orderId)}/draft`, data);
1563
1671
  }
1564
1672
  // -------------------- Inventory --------------------
1565
1673
  /**
@@ -1567,13 +1675,17 @@ var BrainerceClient = class {
1567
1675
  * This will sync inventory to all connected platforms
1568
1676
  */
1569
1677
  async updateInventory(productId, data) {
1570
- await this.request("PUT", `/api/v1/products/${productId}/inventory`, data);
1678
+ await this.request(
1679
+ "PUT",
1680
+ `/api/v1/products/${encodePathSegment(productId)}/inventory`,
1681
+ data
1682
+ );
1571
1683
  }
1572
1684
  /**
1573
1685
  * Get current inventory for a product
1574
1686
  */
1575
1687
  async getInventory(productId) {
1576
- return this.request("GET", `/api/v1/inventory/${productId}`);
1688
+ return this.request("GET", `/api/v1/inventory/${encodePathSegment(productId)}`);
1577
1689
  }
1578
1690
  /**
1579
1691
  * Edit inventory manually with reason for audit trail
@@ -1734,7 +1846,7 @@ var BrainerceClient = class {
1734
1846
  * Get the status of a sync job
1735
1847
  */
1736
1848
  async getSyncStatus(jobId) {
1737
- return this.request("GET", `/api/v1/sync/${jobId}`);
1849
+ return this.request("GET", `/api/v1/sync/${encodePathSegment(jobId)}`);
1738
1850
  }
1739
1851
  // -------------------- Coupons --------------------
1740
1852
  /**
@@ -1756,7 +1868,7 @@ var BrainerceClient = class {
1756
1868
  * Get a single coupon by ID
1757
1869
  */
1758
1870
  async getCoupon(couponId) {
1759
- return this.request("GET", `/api/v1/coupons/${couponId}`);
1871
+ return this.request("GET", `/api/v1/coupons/${encodePathSegment(couponId)}`);
1760
1872
  }
1761
1873
  /**
1762
1874
  * Create a new coupon.
@@ -1786,20 +1898,20 @@ var BrainerceClient = class {
1786
1898
  * Update an existing coupon
1787
1899
  */
1788
1900
  async updateCoupon(couponId, data) {
1789
- return this.request("PATCH", `/api/v1/coupons/${couponId}`, data);
1901
+ return this.request("PATCH", `/api/v1/coupons/${encodePathSegment(couponId)}`, data);
1790
1902
  }
1791
1903
  /**
1792
1904
  * Delete a coupon
1793
1905
  */
1794
1906
  async deleteCoupon(couponId) {
1795
- await this.request("DELETE", `/api/v1/coupons/${couponId}`);
1907
+ await this.request("DELETE", `/api/v1/coupons/${encodePathSegment(couponId)}`);
1796
1908
  }
1797
1909
  /**
1798
1910
  * Sync a coupon to all connected platforms.
1799
1911
  * Returns a sync job that can be tracked with getSyncStatus().
1800
1912
  */
1801
1913
  async syncCoupon(couponId) {
1802
- return this.request("POST", `/api/v1/coupons/${couponId}/sync`);
1914
+ return this.request("POST", `/api/v1/coupons/${encodePathSegment(couponId)}/sync`);
1803
1915
  }
1804
1916
  /**
1805
1917
  * Publish a coupon to specific platforms.
@@ -1812,7 +1924,9 @@ var BrainerceClient = class {
1812
1924
  * ```
1813
1925
  */
1814
1926
  async publishCoupon(couponId, platforms) {
1815
- return this.request("POST", `/api/v1/coupons/${couponId}/publish`, { platforms });
1927
+ return this.request("POST", `/api/v1/coupons/${encodePathSegment(couponId)}/publish`, {
1928
+ platforms
1929
+ });
1816
1930
  }
1817
1931
  /**
1818
1932
  * Get platform capabilities for coupon features.
@@ -1853,13 +1967,17 @@ var BrainerceClient = class {
1853
1967
  * Get a customer by ID
1854
1968
  */
1855
1969
  async getCustomer(customerId) {
1856
- return this.request("GET", `/api/v1/customers/${customerId}`);
1970
+ return this.request("GET", `/api/v1/customers/${encodePathSegment(customerId)}`);
1857
1971
  }
1858
1972
  /**
1859
1973
  * Update a customer
1860
1974
  */
1861
1975
  async updateCustomer(customerId, data) {
1862
- return this.request("PATCH", `/api/v1/customers/${customerId}`, data);
1976
+ return this.request(
1977
+ "PATCH",
1978
+ `/api/v1/customers/${encodePathSegment(customerId)}`,
1979
+ data
1980
+ );
1863
1981
  }
1864
1982
  /**
1865
1983
  * Get a customer by email
@@ -1867,56 +1985,84 @@ var BrainerceClient = class {
1867
1985
  async getCustomerByEmail(email) {
1868
1986
  return this.request("GET", "/api/v1/customers/by-email", void 0, { email });
1869
1987
  }
1870
- /**
1871
- * List a customer's saved payment methods (vaulted cards).
1872
- *
1873
- * Returns display-only metadata — last4, brand, expiry, default flag,
1874
- * status. The underlying provider token is encrypted at rest and
1875
- * NEVER returned through this API.
1876
- *
1877
- * Apps mode requires `customers:read` and `payments:read` scopes.
1878
- *
1879
- * @param storeId - The store this customer belongs to
1880
- * @param customerId - The customer's ID
1881
- * @returns Array of saved payment methods
1882
- *
1883
- * @example
1884
- * ```typescript
1885
- * const methods = await client.listSavedPaymentMethods(storeId, customerId);
1886
- * methods.forEach((m) => {
1887
- * console.log(`${m.brand} ending in ${m.last4} (expires ${m.expMonth}/${m.expYear})`);
1888
- * });
1889
- * ```
1890
- */
1891
- async listSavedPaymentMethods(storeId, customerId) {
1988
+ async listSavedPaymentMethods(customerIdOrStoreId, maybeCustomerId) {
1989
+ const customerId = this.resolveSavedPaymentMethodsArgs(
1990
+ "listSavedPaymentMethods",
1991
+ customerIdOrStoreId,
1992
+ maybeCustomerId
1993
+ );
1892
1994
  return this.request(
1893
1995
  "GET",
1894
- `/api/stores/${storeId}/customers/${customerId}/payment-methods`
1996
+ `/api/stores/${this.storeId}/customers/${encodePathSegment(customerId)}/payment-methods`
1997
+ );
1998
+ }
1999
+ async removeSavedPaymentMethod(customerIdOrStoreId, paymentMethodIdOrCustomerId, maybePaymentMethodId) {
2000
+ const { customerId, paymentMethodId } = this.resolveRemovePaymentMethodArgs(
2001
+ customerIdOrStoreId,
2002
+ paymentMethodIdOrCustomerId,
2003
+ maybePaymentMethodId
2004
+ );
2005
+ return this.request(
2006
+ "DELETE",
2007
+ `/api/stores/${this.storeId}/customers/${encodePathSegment(customerId)}/payment-methods/${encodePathSegment(paymentMethodId)}`
1895
2008
  );
1896
2009
  }
1897
2010
  /**
1898
- * Remove a customer's saved payment method.
1899
- *
1900
- * Hard-deletes the row. The provider may still hold the underlying
1901
- * token internally — we don't issue a delete-at-provider call because
1902
- * not every provider supports it. From the platform's perspective the
1903
- * token is gone; subsequent charges will fail.
1904
- *
1905
- * Apps mode requires `customers:write` scope.
1906
- *
1907
- * @param storeId - The store this customer belongs to
1908
- * @param customerId - The customer's ID
1909
- * @param paymentMethodId - The saved payment method ID to remove
2011
+ * Internal helper: normalize legacy `(storeId, customerId)` callers to the
2012
+ * new `(customerId)` signature for `listSavedPaymentMethods`.
1910
2013
  *
1911
- * @example
1912
- * ```typescript
1913
- * await client.removeSavedPaymentMethod(storeId, customerId, methodId);
1914
- * ```
2014
+ * Throws if the SDK instance has no `storeId` (these endpoints are
2015
+ * storefront-scoped) and warns when the deprecated overload is detected.
1915
2016
  */
1916
- async removeSavedPaymentMethod(storeId, customerId, paymentMethodId) {
1917
- return this.request(
1918
- "DELETE",
1919
- `/api/stores/${storeId}/customers/${customerId}/payment-methods/${paymentMethodId}`
2017
+ resolveSavedPaymentMethodsArgs(methodName, customerIdOrStoreId, maybeCustomerId) {
2018
+ if (!this.storeId) {
2019
+ throw new BrainerceError(
2020
+ `${methodName}: this method requires a storeId on the SDK instance. Pass \`storeId\` when constructing \`new BrainerceClient({ storeId })\`.`,
2021
+ 400
2022
+ );
2023
+ }
2024
+ if (maybeCustomerId !== void 0) {
2025
+ this.warnDeprecatedStoreIdArg(methodName, customerIdOrStoreId);
2026
+ return maybeCustomerId;
2027
+ }
2028
+ return customerIdOrStoreId;
2029
+ }
2030
+ /**
2031
+ * Internal helper: normalize legacy `(storeId, customerId, paymentMethodId)`
2032
+ * callers to the new `(customerId, paymentMethodId)` signature.
2033
+ */
2034
+ resolveRemovePaymentMethodArgs(customerIdOrStoreId, paymentMethodIdOrCustomerId, maybePaymentMethodId) {
2035
+ if (!this.storeId) {
2036
+ throw new BrainerceError(
2037
+ "removeSavedPaymentMethod: this method requires a storeId on the SDK instance. Pass `storeId` when constructing `new BrainerceClient({ storeId })`.",
2038
+ 400
2039
+ );
2040
+ }
2041
+ if (maybePaymentMethodId !== void 0) {
2042
+ this.warnDeprecatedStoreIdArg("removeSavedPaymentMethod", customerIdOrStoreId);
2043
+ return {
2044
+ customerId: paymentMethodIdOrCustomerId,
2045
+ paymentMethodId: maybePaymentMethodId
2046
+ };
2047
+ }
2048
+ return {
2049
+ customerId: customerIdOrStoreId,
2050
+ paymentMethodId: paymentMethodIdOrCustomerId
2051
+ };
2052
+ }
2053
+ /**
2054
+ * One-shot deprecation warning per (method, mismatch?) — verifies the
2055
+ * caller-supplied storeId matches the SDK config and warns regardless.
2056
+ */
2057
+ warnDeprecatedStoreIdArg(methodName, suppliedStoreId) {
2058
+ if (suppliedStoreId !== this.storeId) {
2059
+ throw new BrainerceError(
2060
+ `${methodName}: supplied storeId "${suppliedStoreId}" does not match the SDK instance storeId "${this.storeId}". Construct a new client per store.`,
2061
+ 400
2062
+ );
2063
+ }
2064
+ console.warn(
2065
+ `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.`
1920
2066
  );
1921
2067
  }
1922
2068
  /**
@@ -1975,12 +2121,33 @@ var BrainerceClient = class {
1975
2121
  * Request a password reset email for a customer
1976
2122
  * Works in vibe-coded, storefront, and admin mode
1977
2123
  *
2124
+ * The `resetUrl` MUST be supplied explicitly in non-browser (SSR / Node)
2125
+ * contexts — auto-deriving it from `window.location.origin` is impossible
2126
+ * there and historically resulted in `undefined` being sent to the backend,
2127
+ * which then bounced the email to a broken link. In browser contexts the
2128
+ * origin is still used as a fallback but the SDK logs a one-time warning
2129
+ * recommending an explicit value so server-rendered + proxied dashboards
2130
+ * don't silently rely on the wrong host.
2131
+ *
1978
2132
  * @param email - Customer email address
1979
2133
  * @param options - Optional settings
1980
- * @param options.resetUrl - Override the auto-detected reset URL (e.g. for BFF proxy callback)
2134
+ * @param options.resetUrl - Reset URL the email links should point to.
2135
+ * Required outside the browser; recommended inside it.
1981
2136
  */
1982
2137
  async forgotPassword(email, options) {
1983
- const resetUrl = options?.resetUrl ?? (typeof window !== "undefined" ? `${window.location.origin}/reset-password` : void 0);
2138
+ let resetUrl = options?.resetUrl;
2139
+ if (!resetUrl) {
2140
+ if (typeof window === "undefined") {
2141
+ throw new BrainerceError(
2142
+ 'forgotPassword: `resetUrl` is required outside the browser. Pass `{ resetUrl: "https://your-site.example/reset-password" }` so the email links to the right host.',
2143
+ 400
2144
+ );
2145
+ }
2146
+ console.warn(
2147
+ "BrainerceClient.forgotPassword: deriving `resetUrl` from `window.location.origin` \u2014 pass `{ resetUrl }` explicitly to avoid wrong-host links behind proxies or in SSR."
2148
+ );
2149
+ resetUrl = `${window.location.origin}/reset-password`;
2150
+ }
1984
2151
  if (this.isVibeCodedMode()) {
1985
2152
  return this.vibeCodedRequest("POST", "/customers/forgot-password", {
1986
2153
  email,
@@ -2163,12 +2330,14 @@ var BrainerceClient = class {
2163
2330
  * // Redirect user to Google
2164
2331
  * window.location.href = authorizationUrl;
2165
2332
  *
2166
- * // On /auth/callback page — the backend handles code exchange and redirects with params:
2333
+ * // On /auth/callback page — exchange the one-time auth_code for the JWT.
2334
+ * // (The backend used to put the JWT directly in the redirect URL; that path
2335
+ * // is deprecated because URL params leak into browser history and logs.)
2167
2336
  * const params = new URLSearchParams(window.location.search);
2168
- * if (params.get('oauth_success') === 'true') {
2169
- * const token = params.get('token');
2170
- * client.setCustomerToken(token);
2171
- * // Also available: customer_id, customer_email, is_new
2337
+ * if (params.get('oauth_success') === 'true' && params.get('auth_code')) {
2338
+ * const result = await client.exchangeOAuthCode(params.get('auth_code')!);
2339
+ * client.setCustomerToken(result.token);
2340
+ * // result.customer, result.isNewCustomer, result.redirectUrl, ...
2172
2341
  * } else if (params.get('oauth_error')) {
2173
2342
  * // Show error
2174
2343
  * }
@@ -2186,7 +2355,7 @@ var BrainerceClient = class {
2186
2355
  params.set("redirectUrl", options.redirectUrl);
2187
2356
  }
2188
2357
  const queryString = params.toString();
2189
- const endpoint = `/oauth/${provider}/authorize${queryString ? `?${queryString}` : ""}`;
2358
+ const endpoint = `/oauth/${encodePathSegment(provider)}/authorize${queryString ? `?${queryString}` : ""}`;
2190
2359
  if (this.isVibeCodedMode()) {
2191
2360
  return this.vibeCodedRequest("GET", endpoint);
2192
2361
  }
@@ -2195,6 +2364,83 @@ var BrainerceClient = class {
2195
2364
  }
2196
2365
  throw new BrainerceError("getOAuthAuthorizeUrl requires vibe-coded or storefront mode", 400);
2197
2366
  }
2367
+ /**
2368
+ * Exchange a one-time `auth_code` (returned in the post-OAuth redirect URL)
2369
+ * for the customer JWT. Use this on the `/auth/callback` storefront page
2370
+ * after reading `auth_code` from `window.location.search`.
2371
+ *
2372
+ * The code is single-use and expires 2 minutes after the OAuth callback
2373
+ * issued it. A second call with the same code returns 400.
2374
+ *
2375
+ * This replaces the legacy flow where the JWT was placed directly in the
2376
+ * redirect URL (`?token=...`). The legacy URL params still ship behind a
2377
+ * server feature flag during the migration window, but they will be
2378
+ * removed in the next major release — migrate now.
2379
+ *
2380
+ * @param authCode - The single-use code from the `?auth_code=` URL param.
2381
+ *
2382
+ * @example
2383
+ * ```typescript
2384
+ * const params = new URLSearchParams(window.location.search);
2385
+ * const code = params.get('auth_code');
2386
+ * if (code) {
2387
+ * const { token, customer, isNewCustomer, redirectUrl } =
2388
+ * await client.exchangeOAuthCode(code);
2389
+ * client.setCustomerToken(token);
2390
+ * }
2391
+ * ```
2392
+ */
2393
+ async exchangeOAuthCode(authCode) {
2394
+ if (!authCode) {
2395
+ throw new BrainerceError("authCode is required", 400);
2396
+ }
2397
+ const url = `${this.baseUrl}/api/oauth/customer/exchange`;
2398
+ const controller = new AbortController();
2399
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2400
+ try {
2401
+ const headers = {
2402
+ "Content-Type": "application/json",
2403
+ "X-SDK-Version": SDK_VERSION,
2404
+ "ngrok-skip-browser-warning": "true"
2405
+ };
2406
+ if (this.origin) {
2407
+ headers["Origin"] = this.origin;
2408
+ }
2409
+ if (this.locale) {
2410
+ headers["Accept-Language"] = this.locale;
2411
+ }
2412
+ const response = await fetch(url, {
2413
+ method: "POST",
2414
+ headers,
2415
+ body: JSON.stringify({ code: authCode }),
2416
+ signal: controller.signal
2417
+ });
2418
+ clearTimeout(timeoutId);
2419
+ if (!response.ok) {
2420
+ const errorData = await response.json().catch(() => ({}));
2421
+ throw new BrainerceError(
2422
+ errorData.message || `Request failed with status ${response.status}`,
2423
+ response.status,
2424
+ errorData
2425
+ );
2426
+ }
2427
+ const text = await response.text();
2428
+ if (!text) return {};
2429
+ return JSON.parse(text);
2430
+ } catch (error) {
2431
+ clearTimeout(timeoutId);
2432
+ if (error instanceof BrainerceError) {
2433
+ throw error;
2434
+ }
2435
+ if (error instanceof Error) {
2436
+ if (error.name === "AbortError") {
2437
+ throw new BrainerceError("Request timeout", 408);
2438
+ }
2439
+ throw new BrainerceError(error.message, 0);
2440
+ }
2441
+ throw new BrainerceError("Unknown error occurred", 0);
2442
+ }
2443
+ }
2198
2444
  /**
2199
2445
  * Handle OAuth callback - exchange code for customer token (server-to-server)
2200
2446
  *
@@ -2215,7 +2461,7 @@ var BrainerceClient = class {
2215
2461
  throw new BrainerceError("provider is required (e.g., 'GOOGLE', 'FACEBOOK', 'GITHUB')", 400);
2216
2462
  }
2217
2463
  const params = new URLSearchParams({ code, state });
2218
- const endpoint = `/oauth/${provider}/callback?${params.toString()}`;
2464
+ const endpoint = `/oauth/${encodePathSegment(provider)}/callback?${params.toString()}`;
2219
2465
  if (this.isVibeCodedMode()) {
2220
2466
  return this.vibeCodedRequest("GET", endpoint);
2221
2467
  }
@@ -2259,7 +2505,7 @@ var BrainerceClient = class {
2259
2505
  params.set("redirectUrl", options.redirectUrl);
2260
2506
  }
2261
2507
  const queryString = params.toString();
2262
- const endpoint = `/oauth/${provider}/link${queryString ? `?${queryString}` : ""}`;
2508
+ const endpoint = `/oauth/${encodePathSegment(provider)}/link${queryString ? `?${queryString}` : ""}`;
2263
2509
  if (this.isVibeCodedMode()) {
2264
2510
  return this.vibeCodedRequest("POST", endpoint);
2265
2511
  }
@@ -2288,10 +2534,16 @@ var BrainerceClient = class {
2288
2534
  throw new BrainerceError("Customer token is required. Call setCustomerToken() first.", 401);
2289
2535
  }
2290
2536
  if (this.isVibeCodedMode()) {
2291
- return this.vibeCodedRequest("DELETE", `/oauth/${provider}/link`);
2537
+ return this.vibeCodedRequest(
2538
+ "DELETE",
2539
+ `/oauth/${encodePathSegment(provider)}/link`
2540
+ );
2292
2541
  }
2293
2542
  if (this.isStorefrontMode()) {
2294
- return this.storefrontRequest("DELETE", `/oauth/${provider}/link`);
2543
+ return this.storefrontRequest(
2544
+ "DELETE",
2545
+ `/oauth/${encodePathSegment(provider)}/link`
2546
+ );
2295
2547
  }
2296
2548
  throw new BrainerceError("unlinkOAuthProvider requires vibe-coded or storefront mode", 400);
2297
2549
  }
@@ -2358,7 +2610,10 @@ var BrainerceClient = class {
2358
2610
  * Get all addresses for a customer
2359
2611
  */
2360
2612
  async getCustomerAddresses(customerId) {
2361
- return this.request("GET", `/api/v1/customers/${customerId}/addresses`);
2613
+ return this.request(
2614
+ "GET",
2615
+ `/api/v1/customers/${encodePathSegment(customerId)}/addresses`
2616
+ );
2362
2617
  }
2363
2618
  /**
2364
2619
  * Add an address to a customer
@@ -2380,7 +2635,7 @@ var BrainerceClient = class {
2380
2635
  async addCustomerAddress(customerId, address) {
2381
2636
  return this.request(
2382
2637
  "POST",
2383
- `/api/v1/customers/${customerId}/addresses`,
2638
+ `/api/v1/customers/${encodePathSegment(customerId)}/addresses`,
2384
2639
  address
2385
2640
  );
2386
2641
  }
@@ -2390,7 +2645,7 @@ var BrainerceClient = class {
2390
2645
  async updateCustomerAddress(customerId, addressId, address) {
2391
2646
  return this.request(
2392
2647
  "PATCH",
2393
- `/api/v1/customers/${customerId}/addresses/${addressId}`,
2648
+ `/api/v1/customers/${encodePathSegment(customerId)}/addresses/${encodePathSegment(addressId)}`,
2394
2649
  address
2395
2650
  );
2396
2651
  }
@@ -2398,7 +2653,10 @@ var BrainerceClient = class {
2398
2653
  * Delete a customer address
2399
2654
  */
2400
2655
  async deleteCustomerAddress(customerId, addressId) {
2401
- await this.request("DELETE", `/api/v1/customers/${customerId}/addresses/${addressId}`);
2656
+ await this.request(
2657
+ "DELETE",
2658
+ `/api/v1/customers/${encodePathSegment(customerId)}/addresses/${encodePathSegment(addressId)}`
2659
+ );
2402
2660
  }
2403
2661
  /**
2404
2662
  * Get orders for a customer
@@ -2412,7 +2670,7 @@ var BrainerceClient = class {
2412
2670
  async getCustomerOrders(customerId, params) {
2413
2671
  return this.request(
2414
2672
  "GET",
2415
- `/api/v1/customers/${customerId}/orders`,
2673
+ `/api/v1/customers/${encodePathSegment(customerId)}/orders`,
2416
2674
  void 0,
2417
2675
  { page: params?.page, limit: params?.limit }
2418
2676
  );
@@ -2484,12 +2742,18 @@ var BrainerceClient = class {
2484
2742
  */
2485
2743
  async getCartBySession(sessionToken) {
2486
2744
  if (this.isVibeCodedMode()) {
2487
- return this.vibeCodedRequest("GET", `/cart/session/${sessionToken}`);
2745
+ return this.vibeCodedRequest("GET", `/cart/session/${encodePathSegment(sessionToken)}`);
2488
2746
  }
2489
2747
  if (this.storeId && !this.apiKey) {
2490
- return this.storefrontRequest("GET", `/cart/session/${sessionToken}`);
2748
+ return this.storefrontRequest(
2749
+ "GET",
2750
+ `/cart/session/${encodePathSegment(sessionToken)}`
2751
+ );
2491
2752
  }
2492
- return this.adminRequest("GET", `/api/v1/cart/session/${sessionToken}`);
2753
+ return this.adminRequest(
2754
+ "GET",
2755
+ `/api/v1/cart/session/${encodePathSegment(sessionToken)}`
2756
+ );
2493
2757
  }
2494
2758
  /**
2495
2759
  * Get a cart by customer ID (for authenticated users)
@@ -2502,9 +2766,9 @@ var BrainerceClient = class {
2502
2766
  */
2503
2767
  async getCartByCustomer(customerId) {
2504
2768
  if (this.storeId && !this.apiKey) {
2505
- return this.storefrontRequest("GET", `/cart/customer/${customerId}`);
2769
+ return this.storefrontRequest("GET", `/cart/customer/${encodePathSegment(customerId)}`);
2506
2770
  }
2507
- return this.adminRequest("GET", `/api/v1/cart/customer/${customerId}`);
2771
+ return this.adminRequest("GET", `/api/v1/cart/customer/${encodePathSegment(customerId)}`);
2508
2772
  }
2509
2773
  /**
2510
2774
  * Get a cart by ID
@@ -2534,18 +2798,33 @@ var BrainerceClient = class {
2534
2798
  const queryParams = options?.include?.length ? { include: options.include.join(",") } : void 0;
2535
2799
  if (this.isVibeCodedMode()) {
2536
2800
  return this.withGuards(
2537
- this.vibeCodedRequest("GET", `/cart/${cartId}`, void 0, queryParams),
2801
+ this.vibeCodedRequest(
2802
+ "GET",
2803
+ `/cart/${encodePathSegment(cartId)}`,
2804
+ void 0,
2805
+ queryParams
2806
+ ),
2538
2807
  "cart"
2539
2808
  );
2540
2809
  }
2541
2810
  if (this.storeId && !this.apiKey) {
2542
2811
  return this.withGuards(
2543
- this.storefrontRequest("GET", `/cart/${cartId}`, void 0, queryParams),
2812
+ this.storefrontRequest(
2813
+ "GET",
2814
+ `/cart/${encodePathSegment(cartId)}`,
2815
+ void 0,
2816
+ queryParams
2817
+ ),
2544
2818
  "cart"
2545
2819
  );
2546
2820
  }
2547
2821
  return this.withGuards(
2548
- this.adminRequest("GET", `/api/v1/cart/${cartId}`, void 0, queryParams),
2822
+ this.adminRequest(
2823
+ "GET",
2824
+ `/api/v1/cart/${encodePathSegment(cartId)}`,
2825
+ void 0,
2826
+ queryParams
2827
+ ),
2549
2828
  "cart"
2550
2829
  );
2551
2830
  }
@@ -2601,18 +2880,18 @@ var BrainerceClient = class {
2601
2880
  }
2602
2881
  if (this.isVibeCodedMode()) {
2603
2882
  return this.withGuards(
2604
- this.vibeCodedRequest("POST", `/cart/${cartId}/items`, item),
2883
+ this.vibeCodedRequest("POST", `/cart/${encodePathSegment(cartId)}/items`, item),
2605
2884
  "cart"
2606
2885
  );
2607
2886
  }
2608
2887
  if (this.storeId && !this.apiKey) {
2609
2888
  return this.withGuards(
2610
- this.storefrontRequest("POST", `/cart/${cartId}/items`, item),
2889
+ this.storefrontRequest("POST", `/cart/${encodePathSegment(cartId)}/items`, item),
2611
2890
  "cart"
2612
2891
  );
2613
2892
  }
2614
2893
  return this.withGuards(
2615
- this.adminRequest("POST", `/api/v1/cart/${cartId}/items`, item),
2894
+ this.adminRequest("POST", `/api/v1/cart/${encodePathSegment(cartId)}/items`, item),
2616
2895
  "cart"
2617
2896
  );
2618
2897
  }
@@ -2639,18 +2918,30 @@ var BrainerceClient = class {
2639
2918
  }
2640
2919
  if (this.isVibeCodedMode()) {
2641
2920
  return this.withGuards(
2642
- this.vibeCodedRequest("PATCH", `/cart/${cartId}/items/${itemId}`, data),
2921
+ this.vibeCodedRequest(
2922
+ "PATCH",
2923
+ `/cart/${encodePathSegment(cartId)}/items/${encodePathSegment(itemId)}`,
2924
+ data
2925
+ ),
2643
2926
  "cart"
2644
2927
  );
2645
2928
  }
2646
2929
  if (this.storeId && !this.apiKey) {
2647
2930
  return this.withGuards(
2648
- this.storefrontRequest("PATCH", `/cart/${cartId}/items/${itemId}`, data),
2931
+ this.storefrontRequest(
2932
+ "PATCH",
2933
+ `/cart/${encodePathSegment(cartId)}/items/${encodePathSegment(itemId)}`,
2934
+ data
2935
+ ),
2649
2936
  "cart"
2650
2937
  );
2651
2938
  }
2652
2939
  return this.withGuards(
2653
- this.adminRequest("PATCH", `/api/v1/cart/${cartId}/items/${itemId}`, data),
2940
+ this.adminRequest(
2941
+ "PATCH",
2942
+ `/api/v1/cart/${encodePathSegment(cartId)}/items/${encodePathSegment(itemId)}`,
2943
+ data
2944
+ ),
2654
2945
  "cart"
2655
2946
  );
2656
2947
  }
@@ -2677,18 +2968,27 @@ var BrainerceClient = class {
2677
2968
  }
2678
2969
  if (this.isVibeCodedMode()) {
2679
2970
  return this.withGuards(
2680
- this.vibeCodedRequest("DELETE", `/cart/${cartId}/items/${itemId}`),
2971
+ this.vibeCodedRequest(
2972
+ "DELETE",
2973
+ `/cart/${encodePathSegment(cartId)}/items/${encodePathSegment(itemId)}`
2974
+ ),
2681
2975
  "cart"
2682
2976
  );
2683
2977
  }
2684
2978
  if (this.storeId && !this.apiKey) {
2685
2979
  return this.withGuards(
2686
- this.storefrontRequest("DELETE", `/cart/${cartId}/items/${itemId}`),
2980
+ this.storefrontRequest(
2981
+ "DELETE",
2982
+ `/cart/${encodePathSegment(cartId)}/items/${encodePathSegment(itemId)}`
2983
+ ),
2687
2984
  "cart"
2688
2985
  );
2689
2986
  }
2690
2987
  return this.withGuards(
2691
- this.adminRequest("DELETE", `/api/v1/cart/${cartId}/items/${itemId}`),
2988
+ this.adminRequest(
2989
+ "DELETE",
2990
+ `/api/v1/cart/${encodePathSegment(cartId)}/items/${encodePathSegment(itemId)}`
2991
+ ),
2692
2992
  "cart"
2693
2993
  );
2694
2994
  }
@@ -2709,13 +3009,16 @@ var BrainerceClient = class {
2709
3009
  return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
2710
3010
  }
2711
3011
  if (this.isVibeCodedMode()) {
2712
- return this.withGuards(this.vibeCodedRequest("DELETE", `/cart/${cartId}`), "cart");
3012
+ return this.withGuards(
3013
+ this.vibeCodedRequest("DELETE", `/cart/${encodePathSegment(cartId)}`),
3014
+ "cart"
3015
+ );
2713
3016
  }
2714
3017
  if (this.storeId && !this.apiKey) {
2715
- await this.storefrontRequest("DELETE", `/cart/${cartId}/items`);
3018
+ await this.storefrontRequest("DELETE", `/cart/${encodePathSegment(cartId)}/items`);
2716
3019
  return this.withGuards({}, "cart");
2717
3020
  }
2718
- await this.adminRequest("DELETE", `/api/v1/cart/${cartId}/items`);
3021
+ await this.adminRequest("DELETE", `/api/v1/cart/${encodePathSegment(cartId)}/items`);
2719
3022
  return this.withGuards({}, "cart");
2720
3023
  }
2721
3024
  /**
@@ -2730,18 +3033,18 @@ var BrainerceClient = class {
2730
3033
  async applyCoupon(cartId, code) {
2731
3034
  if (this.isVibeCodedMode()) {
2732
3035
  return this.withGuards(
2733
- this.vibeCodedRequest("POST", `/cart/${cartId}/coupon`, { code }),
3036
+ this.vibeCodedRequest("POST", `/cart/${encodePathSegment(cartId)}/coupon`, { code }),
2734
3037
  "cart"
2735
3038
  );
2736
3039
  }
2737
3040
  if (this.storeId && !this.apiKey) {
2738
3041
  return this.withGuards(
2739
- this.storefrontRequest("POST", `/cart/${cartId}/coupon`, { code }),
3042
+ this.storefrontRequest("POST", `/cart/${encodePathSegment(cartId)}/coupon`, { code }),
2740
3043
  "cart"
2741
3044
  );
2742
3045
  }
2743
3046
  return this.withGuards(
2744
- this.adminRequest("POST", `/api/v1/cart/${cartId}/coupon`, { code }),
3047
+ this.adminRequest("POST", `/api/v1/cart/${encodePathSegment(cartId)}/coupon`, { code }),
2745
3048
  "cart"
2746
3049
  );
2747
3050
  }
@@ -2756,18 +3059,18 @@ var BrainerceClient = class {
2756
3059
  async removeCoupon(cartId) {
2757
3060
  if (this.isVibeCodedMode()) {
2758
3061
  return this.withGuards(
2759
- this.vibeCodedRequest("DELETE", `/cart/${cartId}/coupon`),
3062
+ this.vibeCodedRequest("DELETE", `/cart/${encodePathSegment(cartId)}/coupon`),
2760
3063
  "cart"
2761
3064
  );
2762
3065
  }
2763
3066
  if (this.storeId && !this.apiKey) {
2764
3067
  return this.withGuards(
2765
- this.storefrontRequest("DELETE", `/cart/${cartId}/coupon`),
3068
+ this.storefrontRequest("DELETE", `/cart/${encodePathSegment(cartId)}/coupon`),
2766
3069
  "cart"
2767
3070
  );
2768
3071
  }
2769
3072
  return this.withGuards(
2770
- this.adminRequest("DELETE", `/api/v1/cart/${cartId}/coupon`),
3073
+ this.adminRequest("DELETE", `/api/v1/cart/${encodePathSegment(cartId)}/coupon`),
2771
3074
  "cart"
2772
3075
  );
2773
3076
  }
@@ -2792,18 +3095,18 @@ var BrainerceClient = class {
2792
3095
  }
2793
3096
  if (this.isVibeCodedMode()) {
2794
3097
  return this.withGuards(
2795
- this.vibeCodedRequest("POST", `/cart/${cartId}/recalculate`),
3098
+ this.vibeCodedRequest("POST", `/cart/${encodePathSegment(cartId)}/recalculate`),
2796
3099
  "cart"
2797
3100
  );
2798
3101
  }
2799
3102
  if (this.storeId && !this.apiKey) {
2800
3103
  return this.withGuards(
2801
- this.storefrontRequest("POST", `/cart/${cartId}/recalculate`),
3104
+ this.storefrontRequest("POST", `/cart/${encodePathSegment(cartId)}/recalculate`),
2802
3105
  "cart"
2803
3106
  );
2804
3107
  }
2805
3108
  return this.withGuards(
2806
- this.adminRequest("POST", `/api/v1/cart/${cartId}/recalculate`),
3109
+ this.adminRequest("POST", `/api/v1/cart/${encodePathSegment(cartId)}/recalculate`),
2807
3110
  "cart"
2808
3111
  );
2809
3112
  }
@@ -2832,18 +3135,24 @@ var BrainerceClient = class {
2832
3135
  }
2833
3136
  if (this.isVibeCodedMode()) {
2834
3137
  return this.withGuards(
2835
- this.vibeCodedRequest("POST", `/cart/${cartId}/refresh-snapshots`),
3138
+ this.vibeCodedRequest("POST", `/cart/${encodePathSegment(cartId)}/refresh-snapshots`),
2836
3139
  "cart"
2837
3140
  );
2838
3141
  }
2839
3142
  if (this.storeId && !this.apiKey) {
2840
3143
  return this.withGuards(
2841
- this.storefrontRequest("POST", `/cart/${cartId}/refresh-snapshots`),
3144
+ this.storefrontRequest(
3145
+ "POST",
3146
+ `/cart/${encodePathSegment(cartId)}/refresh-snapshots`
3147
+ ),
2842
3148
  "cart"
2843
3149
  );
2844
3150
  }
2845
3151
  return this.withGuards(
2846
- this.adminRequest("POST", `/api/v1/cart/${cartId}/refresh-snapshots`),
3152
+ this.adminRequest(
3153
+ "POST",
3154
+ `/api/v1/cart/${encodePathSegment(cartId)}/refresh-snapshots`
3155
+ ),
2847
3156
  "cart"
2848
3157
  );
2849
3158
  }
@@ -2872,10 +3181,10 @@ var BrainerceClient = class {
2872
3181
  );
2873
3182
  }
2874
3183
  if (this.isVibeCodedMode()) {
2875
- return this.vibeCodedRequest("POST", `/cart/${cartId}/link`);
3184
+ return this.vibeCodedRequest("POST", `/cart/${encodePathSegment(cartId)}/link`);
2876
3185
  }
2877
3186
  if (this.storeId && !this.apiKey) {
2878
- return this.storefrontRequest("POST", `/cart/${cartId}/link`);
3187
+ return this.storefrontRequest("POST", `/cart/${encodePathSegment(cartId)}/link`);
2879
3188
  }
2880
3189
  throw new BrainerceError("linkCart is only available in vibe-coded or storefront mode", 400);
2881
3190
  }
@@ -2938,13 +3247,13 @@ var BrainerceClient = class {
2938
3247
  if (this.isVibeCodedMode()) {
2939
3248
  return this.vibeCodedRequest(
2940
3249
  "GET",
2941
- `/products/${productId}/discount-badge`
3250
+ `/products/${encodePathSegment(productId)}/discount-badge`
2942
3251
  );
2943
3252
  }
2944
3253
  if (this.storeId && !this.apiKey) {
2945
3254
  return this.storefrontRequest(
2946
3255
  "GET",
2947
- `/products/${productId}/discount-badge`
3256
+ `/products/${encodePathSegment(productId)}/discount-badge`
2948
3257
  );
2949
3258
  }
2950
3259
  throw new BrainerceError(
@@ -2968,10 +3277,13 @@ var BrainerceClient = class {
2968
3277
  */
2969
3278
  async getCartNudges(cartId) {
2970
3279
  if (this.isVibeCodedMode()) {
2971
- return this.vibeCodedRequest("GET", `/cart/${cartId}/nudges`);
3280
+ return this.vibeCodedRequest("GET", `/cart/${encodePathSegment(cartId)}/nudges`);
2972
3281
  }
2973
3282
  if (this.storeId && !this.apiKey) {
2974
- return this.storefrontRequest("GET", `/cart/${cartId}/nudges`);
3283
+ return this.storefrontRequest(
3284
+ "GET",
3285
+ `/cart/${encodePathSegment(cartId)}/nudges`
3286
+ );
2975
3287
  }
2976
3288
  throw new BrainerceError("getCartNudges() requires vibe-coded or storefront mode", 400);
2977
3289
  }
@@ -2996,7 +3308,7 @@ var BrainerceClient = class {
2996
3308
  if (this.isVibeCodedMode()) {
2997
3309
  return this.vibeCodedRequest(
2998
3310
  "GET",
2999
- `/products/${productId}/recommendations`,
3311
+ `/products/${encodePathSegment(productId)}/recommendations`,
3000
3312
  void 0,
3001
3313
  queryParams
3002
3314
  );
@@ -3004,7 +3316,7 @@ var BrainerceClient = class {
3004
3316
  if (this.storeId && !this.apiKey) {
3005
3317
  return this.storefrontRequest(
3006
3318
  "GET",
3007
- `/products/${productId}/recommendations`,
3319
+ `/products/${encodePathSegment(productId)}/recommendations`,
3008
3320
  void 0,
3009
3321
  queryParams
3010
3322
  );
@@ -3034,7 +3346,7 @@ var BrainerceClient = class {
3034
3346
  if (this.isVibeCodedMode()) {
3035
3347
  return this.vibeCodedRequest(
3036
3348
  "GET",
3037
- `/products/${productId}/reviews`,
3349
+ `/products/${encodePathSegment(productId)}/reviews`,
3038
3350
  void 0,
3039
3351
  queryParams
3040
3352
  );
@@ -3042,7 +3354,7 @@ var BrainerceClient = class {
3042
3354
  if (this.storeId && !this.apiKey) {
3043
3355
  return this.storefrontRequest(
3044
3356
  "GET",
3045
- `/products/${productId}/reviews`,
3357
+ `/products/${encodePathSegment(productId)}/reviews`,
3046
3358
  void 0,
3047
3359
  queryParams
3048
3360
  );
@@ -3066,10 +3378,16 @@ var BrainerceClient = class {
3066
3378
  */
3067
3379
  async getMyProductReview(productId) {
3068
3380
  if (this.isVibeCodedMode()) {
3069
- return this.vibeCodedRequest("GET", `/products/${productId}/reviews/me`);
3381
+ return this.vibeCodedRequest(
3382
+ "GET",
3383
+ `/products/${encodePathSegment(productId)}/reviews/me`
3384
+ );
3070
3385
  }
3071
3386
  if (this.storeId && !this.apiKey) {
3072
- return this.storefrontRequest("GET", `/products/${productId}/reviews/me`);
3387
+ return this.storefrontRequest(
3388
+ "GET",
3389
+ `/products/${encodePathSegment(productId)}/reviews/me`
3390
+ );
3073
3391
  }
3074
3392
  throw new BrainerceError("getMyProductReview() requires vibe-coded or storefront mode", 400);
3075
3393
  }
@@ -3093,10 +3411,18 @@ var BrainerceClient = class {
3093
3411
  */
3094
3412
  async submitProductReview(productId, input) {
3095
3413
  if (this.isVibeCodedMode()) {
3096
- return this.vibeCodedRequest("POST", `/products/${productId}/reviews`, input);
3414
+ return this.vibeCodedRequest(
3415
+ "POST",
3416
+ `/products/${encodePathSegment(productId)}/reviews`,
3417
+ input
3418
+ );
3097
3419
  }
3098
3420
  if (this.storeId && !this.apiKey) {
3099
- return this.storefrontRequest("POST", `/products/${productId}/reviews`, input);
3421
+ return this.storefrontRequest(
3422
+ "POST",
3423
+ `/products/${encodePathSegment(productId)}/reviews`,
3424
+ input
3425
+ );
3100
3426
  }
3101
3427
  throw new BrainerceError("submitProductReview() requires vibe-coded or storefront mode", 400);
3102
3428
  }
@@ -3109,14 +3435,14 @@ var BrainerceClient = class {
3109
3435
  if (this.isVibeCodedMode()) {
3110
3436
  return this.vibeCodedRequest(
3111
3437
  "PATCH",
3112
- `/products/${productId}/reviews/me`,
3438
+ `/products/${encodePathSegment(productId)}/reviews/me`,
3113
3439
  input
3114
3440
  );
3115
3441
  }
3116
3442
  if (this.storeId && !this.apiKey) {
3117
3443
  return this.storefrontRequest(
3118
3444
  "PATCH",
3119
- `/products/${productId}/reviews/me`,
3445
+ `/products/${encodePathSegment(productId)}/reviews/me`,
3120
3446
  input
3121
3447
  );
3122
3448
  }
@@ -3128,11 +3454,17 @@ var BrainerceClient = class {
3128
3454
  */
3129
3455
  async deleteMyProductReview(productId) {
3130
3456
  if (this.isVibeCodedMode()) {
3131
- await this.vibeCodedRequest("DELETE", `/products/${productId}/reviews/me`);
3457
+ await this.vibeCodedRequest(
3458
+ "DELETE",
3459
+ `/products/${encodePathSegment(productId)}/reviews/me`
3460
+ );
3132
3461
  return;
3133
3462
  }
3134
3463
  if (this.storeId && !this.apiKey) {
3135
- await this.storefrontRequest("DELETE", `/products/${productId}/reviews/me`);
3464
+ await this.storefrontRequest(
3465
+ "DELETE",
3466
+ `/products/${encodePathSegment(productId)}/reviews/me`
3467
+ );
3136
3468
  return;
3137
3469
  }
3138
3470
  throw new BrainerceError("deleteMyProductReview() requires vibe-coded or storefront mode", 400);
@@ -3151,7 +3483,7 @@ var BrainerceClient = class {
3151
3483
  if (params?.visibility) queryParams.visibility = params.visibility;
3152
3484
  return this.adminRequest(
3153
3485
  "GET",
3154
- `/api/v1/products/${productId}/reviews`,
3486
+ `/api/v1/products/${encodePathSegment(productId)}/reviews`,
3155
3487
  void 0,
3156
3488
  queryParams
3157
3489
  );
@@ -3163,7 +3495,7 @@ var BrainerceClient = class {
3163
3495
  }
3164
3496
  return this.adminRequest(
3165
3497
  "PATCH",
3166
- `/api/v1/reviews/${reviewId}/hide`,
3498
+ `/api/v1/reviews/${encodePathSegment(reviewId)}/hide`,
3167
3499
  void 0,
3168
3500
  storeId ? { storeId } : void 0
3169
3501
  );
@@ -3175,7 +3507,7 @@ var BrainerceClient = class {
3175
3507
  }
3176
3508
  return this.adminRequest(
3177
3509
  "PATCH",
3178
- `/api/v1/reviews/${reviewId}/show`,
3510
+ `/api/v1/reviews/${encodePathSegment(reviewId)}/show`,
3179
3511
  void 0,
3180
3512
  storeId ? { storeId } : void 0
3181
3513
  );
@@ -3200,7 +3532,7 @@ var BrainerceClient = class {
3200
3532
  if (this.isVibeCodedMode()) {
3201
3533
  return this.vibeCodedRequest(
3202
3534
  "GET",
3203
- `/cart/${cartId}/recommendations`,
3535
+ `/cart/${encodePathSegment(cartId)}/recommendations`,
3204
3536
  void 0,
3205
3537
  queryParams
3206
3538
  );
@@ -3208,7 +3540,7 @@ var BrainerceClient = class {
3208
3540
  if (this.storeId && !this.apiKey) {
3209
3541
  return this.storefrontRequest(
3210
3542
  "GET",
3211
- `/cart/${cartId}/recommendations`,
3543
+ `/cart/${encodePathSegment(cartId)}/recommendations`,
3212
3544
  void 0,
3213
3545
  queryParams
3214
3546
  );
@@ -3235,10 +3567,16 @@ var BrainerceClient = class {
3235
3567
  */
3236
3568
  async getCartUpgrades(cartId) {
3237
3569
  if (this.isVibeCodedMode()) {
3238
- return this.vibeCodedRequest("GET", `/cart/${cartId}/upgrades`);
3570
+ return this.vibeCodedRequest(
3571
+ "GET",
3572
+ `/cart/${encodePathSegment(cartId)}/upgrades`
3573
+ );
3239
3574
  }
3240
3575
  if (this.storeId && !this.apiKey) {
3241
- return this.storefrontRequest("GET", `/cart/${cartId}/upgrades`);
3576
+ return this.storefrontRequest(
3577
+ "GET",
3578
+ `/cart/${encodePathSegment(cartId)}/upgrades`
3579
+ );
3242
3580
  }
3243
3581
  throw new BrainerceError("getCartUpgrades() requires vibe-coded or storefront mode", 400);
3244
3582
  }
@@ -3260,10 +3598,16 @@ var BrainerceClient = class {
3260
3598
  */
3261
3599
  async getCartBundles(cartId) {
3262
3600
  if (this.isVibeCodedMode()) {
3263
- return this.vibeCodedRequest("GET", `/cart/${cartId}/bundles`);
3601
+ return this.vibeCodedRequest(
3602
+ "GET",
3603
+ `/cart/${encodePathSegment(cartId)}/bundles`
3604
+ );
3264
3605
  }
3265
3606
  if (this.storeId && !this.apiKey) {
3266
- return this.storefrontRequest("GET", `/cart/${cartId}/bundles`);
3607
+ return this.storefrontRequest(
3608
+ "GET",
3609
+ `/cart/${encodePathSegment(cartId)}/bundles`
3610
+ );
3267
3611
  }
3268
3612
  throw new BrainerceError("getCartBundles() requires vibe-coded or storefront mode", 400);
3269
3613
  }
@@ -3275,10 +3619,16 @@ var BrainerceClient = class {
3275
3619
  */
3276
3620
  async getCheckoutBumps(checkoutId) {
3277
3621
  if (this.isVibeCodedMode()) {
3278
- return this.vibeCodedRequest("GET", `/checkout/${checkoutId}/bumps`);
3622
+ return this.vibeCodedRequest(
3623
+ "GET",
3624
+ `/checkout/${encodePathSegment(checkoutId)}/bumps`
3625
+ );
3279
3626
  }
3280
3627
  if (this.storeId && !this.apiKey) {
3281
- return this.storefrontRequest("GET", `/checkout/${checkoutId}/bumps`);
3628
+ return this.storefrontRequest(
3629
+ "GET",
3630
+ `/checkout/${encodePathSegment(checkoutId)}/bumps`
3631
+ );
3282
3632
  }
3283
3633
  throw new BrainerceError("getCheckoutBumps() requires vibe-coded or storefront mode", 400);
3284
3634
  }
@@ -3293,10 +3643,10 @@ var BrainerceClient = class {
3293
3643
  async addOrderBump(cartId, bumpConfigId, variantId) {
3294
3644
  const body = { bumpConfigId, ...variantId && { variantId } };
3295
3645
  if (this.isVibeCodedMode()) {
3296
- return this.vibeCodedRequest("POST", `/cart/${cartId}/bump`, body);
3646
+ return this.vibeCodedRequest("POST", `/cart/${encodePathSegment(cartId)}/bump`, body);
3297
3647
  }
3298
3648
  if (this.storeId && !this.apiKey) {
3299
- return this.storefrontRequest("POST", `/cart/${cartId}/bump`, body);
3649
+ return this.storefrontRequest("POST", `/cart/${encodePathSegment(cartId)}/bump`, body);
3300
3650
  }
3301
3651
  throw new BrainerceError("addOrderBump() requires vibe-coded or storefront mode", 400);
3302
3652
  }
@@ -3309,10 +3659,16 @@ var BrainerceClient = class {
3309
3659
  */
3310
3660
  async removeOrderBump(cartId, bumpConfigId) {
3311
3661
  if (this.isVibeCodedMode()) {
3312
- return this.vibeCodedRequest("DELETE", `/cart/${cartId}/bump/${bumpConfigId}`);
3662
+ return this.vibeCodedRequest(
3663
+ "DELETE",
3664
+ `/cart/${encodePathSegment(cartId)}/bump/${encodePathSegment(bumpConfigId)}`
3665
+ );
3313
3666
  }
3314
3667
  if (this.storeId && !this.apiKey) {
3315
- return this.storefrontRequest("DELETE", `/cart/${cartId}/bump/${bumpConfigId}`);
3668
+ return this.storefrontRequest(
3669
+ "DELETE",
3670
+ `/cart/${encodePathSegment(cartId)}/bump/${encodePathSegment(bumpConfigId)}`
3671
+ );
3316
3672
  }
3317
3673
  throw new BrainerceError("removeOrderBump() requires vibe-coded or storefront mode", 400);
3318
3674
  }
@@ -3343,10 +3699,14 @@ var BrainerceClient = class {
3343
3699
  ...variantSelections && Object.keys(variantSelections).length > 0 ? { variantSelections } : {}
3344
3700
  };
3345
3701
  if (this.isVibeCodedMode()) {
3346
- return this.vibeCodedRequest("POST", `/cart/${cartId}/bundle`, body);
3702
+ return this.vibeCodedRequest("POST", `/cart/${encodePathSegment(cartId)}/bundle`, body);
3347
3703
  }
3348
3704
  if (this.storeId && !this.apiKey) {
3349
- return this.storefrontRequest("POST", `/cart/${cartId}/bundle`, body);
3705
+ return this.storefrontRequest(
3706
+ "POST",
3707
+ `/cart/${encodePathSegment(cartId)}/bundle`,
3708
+ body
3709
+ );
3350
3710
  }
3351
3711
  throw new BrainerceError("addBundleToCart() requires vibe-coded or storefront mode", 400);
3352
3712
  }
@@ -3359,10 +3719,16 @@ var BrainerceClient = class {
3359
3719
  */
3360
3720
  async removeBundleFromCart(cartId, bundleOfferId) {
3361
3721
  if (this.isVibeCodedMode()) {
3362
- return this.vibeCodedRequest("DELETE", `/cart/${cartId}/bundle/${bundleOfferId}`);
3722
+ return this.vibeCodedRequest(
3723
+ "DELETE",
3724
+ `/cart/${encodePathSegment(cartId)}/bundle/${encodePathSegment(bundleOfferId)}`
3725
+ );
3363
3726
  }
3364
3727
  if (this.storeId && !this.apiKey) {
3365
- return this.storefrontRequest("DELETE", `/cart/${cartId}/bundle/${bundleOfferId}`);
3728
+ return this.storefrontRequest(
3729
+ "DELETE",
3730
+ `/cart/${encodePathSegment(cartId)}/bundle/${encodePathSegment(bundleOfferId)}`
3731
+ );
3366
3732
  }
3367
3733
  throw new BrainerceError("removeBundleFromCart() requires vibe-coded or storefront mode", 400);
3368
3734
  }
@@ -3948,18 +4314,18 @@ var BrainerceClient = class {
3948
4314
  async getCheckout(checkoutId) {
3949
4315
  if (this.isVibeCodedMode()) {
3950
4316
  return this.withGuards(
3951
- this.vibeCodedRequest("GET", `/checkout/${checkoutId}`),
4317
+ this.vibeCodedRequest("GET", `/checkout/${encodePathSegment(checkoutId)}`),
3952
4318
  "checkout"
3953
4319
  );
3954
4320
  }
3955
4321
  if (this.storeId && !this.apiKey) {
3956
4322
  return this.withGuards(
3957
- this.storefrontRequest("GET", `/checkout/${checkoutId}`),
4323
+ this.storefrontRequest("GET", `/checkout/${encodePathSegment(checkoutId)}`),
3958
4324
  "checkout"
3959
4325
  );
3960
4326
  }
3961
4327
  return this.withGuards(
3962
- this.adminRequest("GET", `/api/v1/checkout/${checkoutId}`),
4328
+ this.adminRequest("GET", `/api/v1/checkout/${encodePathSegment(checkoutId)}`),
3963
4329
  "checkout"
3964
4330
  );
3965
4331
  }
@@ -3982,18 +4348,30 @@ var BrainerceClient = class {
3982
4348
  async applyCheckoutCoupon(checkoutId, code) {
3983
4349
  if (this.isVibeCodedMode()) {
3984
4350
  return this.withGuards(
3985
- this.vibeCodedRequest("POST", `/checkout/${checkoutId}/coupon`, { code }),
4351
+ this.vibeCodedRequest(
4352
+ "POST",
4353
+ `/checkout/${encodePathSegment(checkoutId)}/coupon`,
4354
+ { code }
4355
+ ),
3986
4356
  "checkout"
3987
4357
  );
3988
4358
  }
3989
4359
  if (this.storeId && !this.apiKey) {
3990
4360
  return this.withGuards(
3991
- this.storefrontRequest("POST", `/checkout/${checkoutId}/coupon`, { code }),
4361
+ this.storefrontRequest(
4362
+ "POST",
4363
+ `/checkout/${encodePathSegment(checkoutId)}/coupon`,
4364
+ { code }
4365
+ ),
3992
4366
  "checkout"
3993
4367
  );
3994
4368
  }
3995
4369
  return this.withGuards(
3996
- this.adminRequest("POST", `/api/v1/checkout/${checkoutId}/coupon`, { code }),
4370
+ this.adminRequest(
4371
+ "POST",
4372
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/coupon`,
4373
+ { code }
4374
+ ),
3997
4375
  "checkout"
3998
4376
  );
3999
4377
  }
@@ -4011,18 +4389,27 @@ var BrainerceClient = class {
4011
4389
  async removeCheckoutCoupon(checkoutId) {
4012
4390
  if (this.isVibeCodedMode()) {
4013
4391
  return this.withGuards(
4014
- this.vibeCodedRequest("DELETE", `/checkout/${checkoutId}/coupon`),
4392
+ this.vibeCodedRequest(
4393
+ "DELETE",
4394
+ `/checkout/${encodePathSegment(checkoutId)}/coupon`
4395
+ ),
4015
4396
  "checkout"
4016
4397
  );
4017
4398
  }
4018
4399
  if (this.storeId && !this.apiKey) {
4019
4400
  return this.withGuards(
4020
- this.storefrontRequest("DELETE", `/checkout/${checkoutId}/coupon`),
4401
+ this.storefrontRequest(
4402
+ "DELETE",
4403
+ `/checkout/${encodePathSegment(checkoutId)}/coupon`
4404
+ ),
4021
4405
  "checkout"
4022
4406
  );
4023
4407
  }
4024
4408
  return this.withGuards(
4025
- this.adminRequest("DELETE", `/api/v1/checkout/${checkoutId}/coupon`),
4409
+ this.adminRequest(
4410
+ "DELETE",
4411
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/coupon`
4412
+ ),
4026
4413
  "checkout"
4027
4414
  );
4028
4415
  }
@@ -4040,12 +4427,24 @@ var BrainerceClient = class {
4040
4427
  */
4041
4428
  async setCheckoutCustomer(checkoutId, data) {
4042
4429
  if (this.isVibeCodedMode()) {
4043
- return this.vibeCodedRequest("PATCH", `/checkout/${checkoutId}/customer`, data);
4430
+ return this.vibeCodedRequest(
4431
+ "PATCH",
4432
+ `/checkout/${encodePathSegment(checkoutId)}/customer`,
4433
+ data
4434
+ );
4044
4435
  }
4045
4436
  if (this.storeId && !this.apiKey) {
4046
- return this.storefrontRequest("PATCH", `/checkout/${checkoutId}/customer`, data);
4437
+ return this.storefrontRequest(
4438
+ "PATCH",
4439
+ `/checkout/${encodePathSegment(checkoutId)}/customer`,
4440
+ data
4441
+ );
4047
4442
  }
4048
- return this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/customer`, data);
4443
+ return this.adminRequest(
4444
+ "PATCH",
4445
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/customer`,
4446
+ data
4447
+ );
4049
4448
  }
4050
4449
  /**
4051
4450
  * Get available shipping destinations for this store.
@@ -4113,20 +4512,20 @@ var BrainerceClient = class {
4113
4512
  if (this.isVibeCodedMode()) {
4114
4513
  return this.vibeCodedRequest(
4115
4514
  "PATCH",
4116
- `/checkout/${checkoutId}/shipping-address`,
4515
+ `/checkout/${encodePathSegment(checkoutId)}/shipping-address`,
4117
4516
  address
4118
4517
  );
4119
4518
  }
4120
4519
  if (this.storeId && !this.apiKey) {
4121
4520
  return this.storefrontRequest(
4122
4521
  "PATCH",
4123
- `/checkout/${checkoutId}/shipping-address`,
4522
+ `/checkout/${encodePathSegment(checkoutId)}/shipping-address`,
4124
4523
  address
4125
4524
  );
4126
4525
  }
4127
4526
  return this.adminRequest(
4128
4527
  "PATCH",
4129
- `/api/v1/checkout/${checkoutId}/shipping-address`,
4528
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/shipping-address`,
4130
4529
  address
4131
4530
  );
4132
4531
  }
@@ -4144,19 +4543,19 @@ var BrainerceClient = class {
4144
4543
  if (this.isVibeCodedMode()) {
4145
4544
  const result = await this.vibeCodedRequest(
4146
4545
  "GET",
4147
- `/checkout/${checkoutId}/shipping-rates`
4546
+ `/checkout/${encodePathSegment(checkoutId)}/shipping-rates`
4148
4547
  );
4149
4548
  return result.rates;
4150
4549
  }
4151
4550
  if (this.storeId && !this.apiKey) {
4152
4551
  return this.storefrontRequest(
4153
4552
  "GET",
4154
- `/checkout/${checkoutId}/shipping-rates`
4553
+ `/checkout/${encodePathSegment(checkoutId)}/shipping-rates`
4155
4554
  );
4156
4555
  }
4157
4556
  return this.adminRequest(
4158
4557
  "GET",
4159
- `/api/v1/checkout/${checkoutId}/shipping-rates`
4558
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/shipping-rates`
4160
4559
  );
4161
4560
  }
4162
4561
  /**
@@ -4171,24 +4570,36 @@ var BrainerceClient = class {
4171
4570
  async selectShippingMethod(checkoutId, shippingRateId) {
4172
4571
  if (this.isVibeCodedMode()) {
4173
4572
  return this.withGuards(
4174
- this.vibeCodedRequest("PATCH", `/checkout/${checkoutId}/shipping-method`, {
4175
- shippingMethodId: shippingRateId
4176
- }),
4573
+ this.vibeCodedRequest(
4574
+ "PATCH",
4575
+ `/checkout/${encodePathSegment(checkoutId)}/shipping-method`,
4576
+ {
4577
+ shippingRateId
4578
+ }
4579
+ ),
4177
4580
  "checkout"
4178
4581
  );
4179
4582
  }
4180
4583
  if (this.storeId && !this.apiKey) {
4181
4584
  return this.withGuards(
4182
- this.storefrontRequest("PATCH", `/checkout/${checkoutId}/shipping-method`, {
4183
- shippingRateId
4184
- }),
4585
+ this.storefrontRequest(
4586
+ "PATCH",
4587
+ `/checkout/${encodePathSegment(checkoutId)}/shipping-method`,
4588
+ {
4589
+ shippingRateId
4590
+ }
4591
+ ),
4185
4592
  "checkout"
4186
4593
  );
4187
4594
  }
4188
4595
  return this.withGuards(
4189
- this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/shipping-method`, {
4190
- shippingRateId
4191
- }),
4596
+ this.adminRequest(
4597
+ "PATCH",
4598
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/shipping-method`,
4599
+ {
4600
+ shippingRateId
4601
+ }
4602
+ ),
4192
4603
  "checkout"
4193
4604
  );
4194
4605
  }
@@ -4227,18 +4638,30 @@ var BrainerceClient = class {
4227
4638
  */
4228
4639
  async setDeliveryType(checkoutId, deliveryType) {
4229
4640
  if (this.isVibeCodedMode()) {
4230
- return this.vibeCodedRequest("PATCH", `/checkout/${checkoutId}/delivery-type`, {
4231
- deliveryType
4232
- });
4641
+ return this.vibeCodedRequest(
4642
+ "PATCH",
4643
+ `/checkout/${encodePathSegment(checkoutId)}/delivery-type`,
4644
+ {
4645
+ deliveryType
4646
+ }
4647
+ );
4233
4648
  }
4234
4649
  if (this.storeId && !this.apiKey) {
4235
- return this.storefrontRequest("PATCH", `/checkout/${checkoutId}/delivery-type`, {
4236
- deliveryType
4237
- });
4650
+ return this.storefrontRequest(
4651
+ "PATCH",
4652
+ `/checkout/${encodePathSegment(checkoutId)}/delivery-type`,
4653
+ {
4654
+ deliveryType
4655
+ }
4656
+ );
4238
4657
  }
4239
- return this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/delivery-type`, {
4240
- deliveryType
4241
- });
4658
+ return this.adminRequest(
4659
+ "PATCH",
4660
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/delivery-type`,
4661
+ {
4662
+ deliveryType
4663
+ }
4664
+ );
4242
4665
  }
4243
4666
  /**
4244
4667
  * Select a pickup location for checkout.
@@ -4260,20 +4683,20 @@ var BrainerceClient = class {
4260
4683
  if (this.isVibeCodedMode()) {
4261
4684
  return this.vibeCodedRequest(
4262
4685
  "PATCH",
4263
- `/checkout/${checkoutId}/pickup-location`,
4686
+ `/checkout/${encodePathSegment(checkoutId)}/pickup-location`,
4264
4687
  data
4265
4688
  );
4266
4689
  }
4267
4690
  if (this.storeId && !this.apiKey) {
4268
4691
  return this.storefrontRequest(
4269
4692
  "PATCH",
4270
- `/checkout/${checkoutId}/pickup-location`,
4693
+ `/checkout/${encodePathSegment(checkoutId)}/pickup-location`,
4271
4694
  data
4272
4695
  );
4273
4696
  }
4274
4697
  return this.adminRequest(
4275
4698
  "PATCH",
4276
- `/api/v1/checkout/${checkoutId}/pickup-location`,
4699
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/pickup-location`,
4277
4700
  data
4278
4701
  );
4279
4702
  }
@@ -4305,20 +4728,20 @@ var BrainerceClient = class {
4305
4728
  if (this.isVibeCodedMode()) {
4306
4729
  return this.vibeCodedRequest(
4307
4730
  "PATCH",
4308
- `/checkout/${checkoutId}/billing-address`,
4731
+ `/checkout/${encodePathSegment(checkoutId)}/billing-address`,
4309
4732
  address
4310
4733
  );
4311
4734
  }
4312
4735
  if (this.storeId && !this.apiKey) {
4313
4736
  return this.storefrontRequest(
4314
4737
  "PATCH",
4315
- `/checkout/${checkoutId}/billing-address`,
4738
+ `/checkout/${encodePathSegment(checkoutId)}/billing-address`,
4316
4739
  address
4317
4740
  );
4318
4741
  }
4319
4742
  return this.adminRequest(
4320
4743
  "PATCH",
4321
- `/api/v1/checkout/${checkoutId}/billing-address`,
4744
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/billing-address`,
4322
4745
  address
4323
4746
  );
4324
4747
  }
@@ -4337,17 +4760,17 @@ var BrainerceClient = class {
4337
4760
  if (this.isVibeCodedMode()) {
4338
4761
  result = await this.vibeCodedRequest(
4339
4762
  "POST",
4340
- `/checkout/${checkoutId}/complete`
4763
+ `/checkout/${encodePathSegment(checkoutId)}/complete`
4341
4764
  );
4342
4765
  } else if (this.storeId && !this.apiKey) {
4343
4766
  result = await this.storefrontRequest(
4344
4767
  "POST",
4345
- `/checkout/${checkoutId}/complete`
4768
+ `/checkout/${encodePathSegment(checkoutId)}/complete`
4346
4769
  );
4347
4770
  } else {
4348
4771
  result = await this.adminRequest(
4349
4772
  "POST",
4350
- `/api/v1/checkout/${checkoutId}/complete`
4773
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}/complete`
4351
4774
  );
4352
4775
  }
4353
4776
  this.customerCartId = null;
@@ -4365,18 +4788,18 @@ var BrainerceClient = class {
4365
4788
  if (this.isVibeCodedMode()) {
4366
4789
  return this.vibeCodedRequest(
4367
4790
  "GET",
4368
- `/checkout/${checkoutId}/custom-fields`
4791
+ `/checkout/${encodePathSegment(checkoutId)}/custom-fields`
4369
4792
  );
4370
4793
  }
4371
4794
  if (this.storeId && !this.apiKey) {
4372
4795
  return this.storefrontRequest(
4373
4796
  "GET",
4374
- `/checkout/${checkoutId}/custom-fields`
4797
+ `/checkout/${encodePathSegment(checkoutId)}/custom-fields`
4375
4798
  );
4376
4799
  }
4377
4800
  return this.adminRequest(
4378
4801
  "GET",
4379
- `/api/v1/checkouts/${checkoutId}/custom-fields`
4802
+ `/api/v1/checkouts/${encodePathSegment(checkoutId)}/custom-fields`
4380
4803
  );
4381
4804
  }
4382
4805
  /**
@@ -4399,20 +4822,20 @@ var BrainerceClient = class {
4399
4822
  if (this.isVibeCodedMode()) {
4400
4823
  return this.vibeCodedRequest(
4401
4824
  "PATCH",
4402
- `/checkout/${checkoutId}/custom-fields`,
4825
+ `/checkout/${encodePathSegment(checkoutId)}/custom-fields`,
4403
4826
  data
4404
4827
  );
4405
4828
  }
4406
4829
  if (this.storeId && !this.apiKey) {
4407
4830
  return this.storefrontRequest(
4408
4831
  "PATCH",
4409
- `/checkout/${checkoutId}/custom-fields`,
4832
+ `/checkout/${encodePathSegment(checkoutId)}/custom-fields`,
4410
4833
  data
4411
4834
  );
4412
4835
  }
4413
4836
  return this.adminRequest(
4414
4837
  "PATCH",
4415
- `/api/v1/checkouts/${checkoutId}/custom-fields`,
4838
+ `/api/v1/checkouts/${encodePathSegment(checkoutId)}/custom-fields`,
4416
4839
  data
4417
4840
  );
4418
4841
  }
@@ -4427,17 +4850,17 @@ var BrainerceClient = class {
4427
4850
  if (this.isVibeCodedMode()) {
4428
4851
  result = await this.vibeCodedRequest(
4429
4852
  "DELETE",
4430
- `/checkout/${checkoutId}`
4853
+ `/checkout/${encodePathSegment(checkoutId)}`
4431
4854
  );
4432
4855
  } else if (this.storeId && !this.apiKey) {
4433
4856
  result = await this.storefrontRequest(
4434
4857
  "DELETE",
4435
- `/checkout/${checkoutId}`
4858
+ `/checkout/${encodePathSegment(checkoutId)}`
4436
4859
  );
4437
4860
  } else {
4438
4861
  result = await this.adminRequest(
4439
4862
  "DELETE",
4440
- `/api/v1/checkout/${checkoutId}`
4863
+ `/api/v1/checkout/${encodePathSegment(checkoutId)}`
4441
4864
  );
4442
4865
  }
4443
4866
  this.clearActiveCheckoutStorage();
@@ -4605,7 +5028,10 @@ var BrainerceClient = class {
4605
5028
  400
4606
5029
  );
4607
5030
  }
4608
- return this.vibeCodedRequest("GET", `/checkout/${checkoutId}/payment-status`);
5031
+ return this.vibeCodedRequest(
5032
+ "GET",
5033
+ `/checkout/${encodePathSegment(checkoutId)}/payment-status`
5034
+ );
4609
5035
  }
4610
5036
  /**
4611
5037
  * Confirm a client-side SDK payment from the frontend.
@@ -4704,7 +5130,7 @@ var BrainerceClient = class {
4704
5130
  const startTime = Date.now();
4705
5131
  let attempts = 0;
4706
5132
  let currentDelay = initialDelayMs;
4707
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5133
+ const sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
4708
5134
  while (Date.now() - startTime < maxWaitMs) {
4709
5135
  attempts++;
4710
5136
  const status = await this.getPaymentStatus(checkoutId);
@@ -4729,7 +5155,7 @@ var BrainerceClient = class {
4729
5155
  const remainingTime = maxWaitMs - (Date.now() - startTime);
4730
5156
  const sleepTime = Math.min(currentDelay, remainingTime, 8e3);
4731
5157
  if (sleepTime > 0) {
4732
- await sleep(sleepTime);
5158
+ await sleep2(sleepTime);
4733
5159
  currentDelay = Math.min(currentDelay * 2, 8e3);
4734
5160
  }
4735
5161
  }
@@ -5244,7 +5670,7 @@ var BrainerceClient = class {
5244
5670
  if (data.shippingAddress) {
5245
5671
  const result = await this.vibeCodedRequest(
5246
5672
  "PATCH",
5247
- `/checkout/${checkoutId}/shipping-address`,
5673
+ `/checkout/${encodePathSegment(checkoutId)}/shipping-address`,
5248
5674
  data.shippingAddress
5249
5675
  );
5250
5676
  checkout = result.checkout;
@@ -5252,7 +5678,7 @@ var BrainerceClient = class {
5252
5678
  if (data.billingAddress) {
5253
5679
  checkout = await this.vibeCodedRequest(
5254
5680
  "PATCH",
5255
- `/checkout/${checkoutId}/billing-address`,
5681
+ `/checkout/${encodePathSegment(checkoutId)}/billing-address`,
5256
5682
  data.billingAddress
5257
5683
  );
5258
5684
  }
@@ -5286,7 +5712,7 @@ var BrainerceClient = class {
5286
5712
  async completeGuestCheckout(checkoutId, options) {
5287
5713
  const result = await this.vibeCodedRequest(
5288
5714
  "POST",
5289
- `/checkout/${checkoutId}/complete`,
5715
+ `/checkout/${encodePathSegment(checkoutId)}/complete`,
5290
5716
  {}
5291
5717
  );
5292
5718
  if (options?.clearCartOnSuccess !== false) {
@@ -5594,13 +6020,13 @@ var BrainerceClient = class {
5594
6020
  if (this.isVibeCodedMode()) {
5595
6021
  return this.vibeCodedRequest(
5596
6022
  "GET",
5597
- `/customers/me/orders/${orderId}/downloads${qs}`
6023
+ `/customers/me/orders/${encodePathSegment(orderId)}/downloads${qs}`
5598
6024
  );
5599
6025
  }
5600
6026
  if (this.storeId && !this.apiKey) {
5601
6027
  return this.storefrontRequest(
5602
6028
  "GET",
5603
- `/customers/me/orders/${orderId}/downloads${qs}`
6029
+ `/customers/me/orders/${encodePathSegment(orderId)}/downloads${qs}`
5604
6030
  );
5605
6031
  }
5606
6032
  throw new BrainerceError(
@@ -5693,14 +6119,14 @@ var BrainerceClient = class {
5693
6119
  if (this.isVibeCodedMode()) {
5694
6120
  return this.vibeCodedRequest(
5695
6121
  "PATCH",
5696
- `/customers/me/addresses/${addressId}`,
6122
+ `/customers/me/addresses/${encodePathSegment(addressId)}`,
5697
6123
  data
5698
6124
  );
5699
6125
  }
5700
6126
  if (this.storeId && !this.apiKey) {
5701
6127
  return this.storefrontRequest(
5702
6128
  "PATCH",
5703
- `/customers/me/addresses/${addressId}`,
6129
+ `/customers/me/addresses/${encodePathSegment(addressId)}`,
5704
6130
  data
5705
6131
  );
5706
6132
  }
@@ -5721,11 +6147,17 @@ var BrainerceClient = class {
5721
6147
  );
5722
6148
  }
5723
6149
  if (this.isVibeCodedMode()) {
5724
- await this.vibeCodedRequest("DELETE", `/customers/me/addresses/${addressId}`);
6150
+ await this.vibeCodedRequest(
6151
+ "DELETE",
6152
+ `/customers/me/addresses/${encodePathSegment(addressId)}`
6153
+ );
5725
6154
  return;
5726
6155
  }
5727
6156
  if (this.storeId && !this.apiKey) {
5728
- await this.storefrontRequest("DELETE", `/customers/me/addresses/${addressId}`);
6157
+ await this.storefrontRequest(
6158
+ "DELETE",
6159
+ `/customers/me/addresses/${encodePathSegment(addressId)}`
6160
+ );
5729
6161
  return;
5730
6162
  }
5731
6163
  throw new BrainerceError(
@@ -5778,7 +6210,10 @@ var BrainerceClient = class {
5778
6210
  * ```
5779
6211
  */
5780
6212
  async getCustomApiIntegration(integrationId) {
5781
- return this.adminRequest("GET", `/api/v1/custom-api/${integrationId}`);
6213
+ return this.adminRequest(
6214
+ "GET",
6215
+ `/api/v1/custom-api/${encodePathSegment(integrationId)}`
6216
+ );
5782
6217
  }
5783
6218
  /**
5784
6219
  * Create a new Custom API integration
@@ -5821,7 +6256,7 @@ var BrainerceClient = class {
5821
6256
  async updateCustomApiIntegration(integrationId, data) {
5822
6257
  return this.adminRequest(
5823
6258
  "PATCH",
5824
- `/api/v1/custom-api/${integrationId}`,
6259
+ `/api/v1/custom-api/${encodePathSegment(integrationId)}`,
5825
6260
  data
5826
6261
  );
5827
6262
  }
@@ -5835,7 +6270,10 @@ var BrainerceClient = class {
5835
6270
  * ```
5836
6271
  */
5837
6272
  async deleteCustomApiIntegration(integrationId) {
5838
- await this.adminRequest("DELETE", `/api/v1/custom-api/${integrationId}`);
6273
+ await this.adminRequest(
6274
+ "DELETE",
6275
+ `/api/v1/custom-api/${encodePathSegment(integrationId)}`
6276
+ );
5839
6277
  }
5840
6278
  /**
5841
6279
  * Test connection to a Custom API
@@ -5854,7 +6292,7 @@ var BrainerceClient = class {
5854
6292
  async testCustomApiConnection(integrationId) {
5855
6293
  return this.adminRequest(
5856
6294
  "POST",
5857
- `/api/v1/custom-api/${integrationId}/test`
6295
+ `/api/v1/custom-api/${encodePathSegment(integrationId)}/test`
5858
6296
  );
5859
6297
  }
5860
6298
  // -------------------- Inventory Reservations --------------------
@@ -5975,7 +6413,10 @@ var BrainerceClient = class {
5975
6413
  * Requires Admin mode (apiKey)
5976
6414
  */
5977
6415
  async getCategory(categoryId) {
5978
- return this.adminRequest("GET", `/api/v1/categories/${categoryId}`);
6416
+ return this.adminRequest(
6417
+ "GET",
6418
+ `/api/v1/categories/${encodePathSegment(categoryId)}`
6419
+ );
5979
6420
  }
5980
6421
  /**
5981
6422
  * Create a new category
@@ -5998,14 +6439,18 @@ var BrainerceClient = class {
5998
6439
  * Requires Admin mode (apiKey)
5999
6440
  */
6000
6441
  async updateCategory(categoryId, data) {
6001
- return this.adminRequest("PATCH", `/api/v1/categories/${categoryId}`, data);
6442
+ return this.adminRequest(
6443
+ "PATCH",
6444
+ `/api/v1/categories/${encodePathSegment(categoryId)}`,
6445
+ data
6446
+ );
6002
6447
  }
6003
6448
  /**
6004
6449
  * Delete a category
6005
6450
  * Requires Admin mode (apiKey)
6006
6451
  */
6007
6452
  async deleteCategory(categoryId) {
6008
- await this.adminRequest("DELETE", `/api/v1/categories/${categoryId}`);
6453
+ await this.adminRequest("DELETE", `/api/v1/categories/${encodePathSegment(categoryId)}`);
6009
6454
  }
6010
6455
  // -------------------- Taxonomy: Brands (Admin) --------------------
6011
6456
  // These methods require Admin mode (apiKey)
@@ -6021,7 +6466,7 @@ var BrainerceClient = class {
6021
6466
  * Requires Admin mode (apiKey)
6022
6467
  */
6023
6468
  async getBrand(brandId) {
6024
- return this.adminRequest("GET", `/api/v1/brands/${brandId}`);
6469
+ return this.adminRequest("GET", `/api/v1/brands/${encodePathSegment(brandId)}`);
6025
6470
  }
6026
6471
  /**
6027
6472
  * Create a new brand
@@ -6044,14 +6489,14 @@ var BrainerceClient = class {
6044
6489
  * Requires Admin mode (apiKey)
6045
6490
  */
6046
6491
  async updateBrand(brandId, data) {
6047
- return this.adminRequest("PATCH", `/api/v1/brands/${brandId}`, data);
6492
+ return this.adminRequest("PATCH", `/api/v1/brands/${encodePathSegment(brandId)}`, data);
6048
6493
  }
6049
6494
  /**
6050
6495
  * Delete a brand
6051
6496
  * Requires Admin mode (apiKey)
6052
6497
  */
6053
6498
  async deleteBrand(brandId) {
6054
- await this.adminRequest("DELETE", `/api/v1/brands/${brandId}`);
6499
+ await this.adminRequest("DELETE", `/api/v1/brands/${encodePathSegment(brandId)}`);
6055
6500
  }
6056
6501
  // -------------------- Taxonomy: Tags (Admin) --------------------
6057
6502
  // These methods require Admin mode (apiKey)
@@ -6067,7 +6512,7 @@ var BrainerceClient = class {
6067
6512
  * Requires Admin mode (apiKey)
6068
6513
  */
6069
6514
  async getTag(tagId) {
6070
- return this.adminRequest("GET", `/api/v1/tags/${tagId}`);
6515
+ return this.adminRequest("GET", `/api/v1/tags/${encodePathSegment(tagId)}`);
6071
6516
  }
6072
6517
  /**
6073
6518
  * Create a new tag
@@ -6089,14 +6534,14 @@ var BrainerceClient = class {
6089
6534
  * Requires Admin mode (apiKey)
6090
6535
  */
6091
6536
  async updateTag(tagId, data) {
6092
- return this.adminRequest("PATCH", `/api/v1/tags/${tagId}`, data);
6537
+ return this.adminRequest("PATCH", `/api/v1/tags/${encodePathSegment(tagId)}`, data);
6093
6538
  }
6094
6539
  /**
6095
6540
  * Delete a tag
6096
6541
  * Requires Admin mode (apiKey)
6097
6542
  */
6098
6543
  async deleteTag(tagId) {
6099
- await this.adminRequest("DELETE", `/api/v1/tags/${tagId}`);
6544
+ await this.adminRequest("DELETE", `/api/v1/tags/${encodePathSegment(tagId)}`);
6100
6545
  }
6101
6546
  // -------------------- Taxonomy: Attributes (Admin) --------------------
6102
6547
  // These methods require Admin mode (apiKey)
@@ -6117,7 +6562,10 @@ var BrainerceClient = class {
6117
6562
  * Requires Admin mode (apiKey)
6118
6563
  */
6119
6564
  async getAttribute(attributeId) {
6120
- return this.adminRequest("GET", `/api/v1/attributes/${attributeId}`);
6565
+ return this.adminRequest(
6566
+ "GET",
6567
+ `/api/v1/attributes/${encodePathSegment(attributeId)}`
6568
+ );
6121
6569
  }
6122
6570
  /**
6123
6571
  * Create a new attribute
@@ -6140,21 +6588,28 @@ var BrainerceClient = class {
6140
6588
  * Requires Admin mode (apiKey)
6141
6589
  */
6142
6590
  async updateAttribute(attributeId, data) {
6143
- return this.adminRequest("PATCH", `/api/v1/attributes/${attributeId}`, data);
6591
+ return this.adminRequest(
6592
+ "PATCH",
6593
+ `/api/v1/attributes/${encodePathSegment(attributeId)}`,
6594
+ data
6595
+ );
6144
6596
  }
6145
6597
  /**
6146
6598
  * Delete an attribute
6147
6599
  * Requires Admin mode (apiKey)
6148
6600
  */
6149
6601
  async deleteAttribute(attributeId) {
6150
- await this.adminRequest("DELETE", `/api/v1/attributes/${attributeId}`);
6602
+ await this.adminRequest("DELETE", `/api/v1/attributes/${encodePathSegment(attributeId)}`);
6151
6603
  }
6152
6604
  /**
6153
6605
  * Get all options for an attribute
6154
6606
  * Requires Admin mode (apiKey)
6155
6607
  */
6156
6608
  async getAttributeOptions(attributeId) {
6157
- return this.adminRequest("GET", `/api/v1/attributes/${attributeId}/options`);
6609
+ return this.adminRequest(
6610
+ "GET",
6611
+ `/api/v1/attributes/${encodePathSegment(attributeId)}/options`
6612
+ );
6158
6613
  }
6159
6614
  /**
6160
6615
  * Create a new option for an attribute
@@ -6172,7 +6627,7 @@ var BrainerceClient = class {
6172
6627
  async createAttributeOption(attributeId, data) {
6173
6628
  return this.adminRequest(
6174
6629
  "POST",
6175
- `/api/v1/attributes/${attributeId}/options`,
6630
+ `/api/v1/attributes/${encodePathSegment(attributeId)}/options`,
6176
6631
  data
6177
6632
  );
6178
6633
  }
@@ -6183,7 +6638,7 @@ var BrainerceClient = class {
6183
6638
  async updateAttributeOption(attributeId, optionId, data) {
6184
6639
  return this.adminRequest(
6185
6640
  "PATCH",
6186
- `/api/v1/attributes/${attributeId}/options/${optionId}`,
6641
+ `/api/v1/attributes/${encodePathSegment(attributeId)}/options/${encodePathSegment(optionId)}`,
6187
6642
  data
6188
6643
  );
6189
6644
  }
@@ -6194,7 +6649,7 @@ var BrainerceClient = class {
6194
6649
  async deleteAttributeOption(attributeId, optionId) {
6195
6650
  await this.adminRequest(
6196
6651
  "DELETE",
6197
- `/api/v1/attributes/${attributeId}/options/${optionId}`
6652
+ `/api/v1/attributes/${encodePathSegment(attributeId)}/options/${encodePathSegment(optionId)}`
6198
6653
  );
6199
6654
  }
6200
6655
  // -------------------- Modifier Groups (Admin) --------------------
@@ -6223,7 +6678,7 @@ var BrainerceClient = class {
6223
6678
  async listModifierGroups(storeId, params) {
6224
6679
  return this.adminRequest(
6225
6680
  "GET",
6226
- `/api/stores/${storeId}/modifier-groups`,
6681
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups`,
6227
6682
  void 0,
6228
6683
  params
6229
6684
  );
@@ -6238,7 +6693,7 @@ var BrainerceClient = class {
6238
6693
  async getModifierGroup(storeId, groupId) {
6239
6694
  return this.adminRequest(
6240
6695
  "GET",
6241
- `/api/stores/${storeId}/modifier-groups/${groupId}`
6696
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups/${encodePathSegment(groupId)}`
6242
6697
  );
6243
6698
  }
6244
6699
  /**
@@ -6260,7 +6715,11 @@ var BrainerceClient = class {
6260
6715
  * ```
6261
6716
  */
6262
6717
  async createModifierGroup(storeId, data) {
6263
- return this.adminRequest("POST", `/api/stores/${storeId}/modifier-groups`, data);
6718
+ return this.adminRequest(
6719
+ "POST",
6720
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups`,
6721
+ data
6722
+ );
6264
6723
  }
6265
6724
  /**
6266
6725
  * Update a modifier group's metadata or selection rules. Pass `status: 'archived'`
@@ -6270,7 +6729,7 @@ var BrainerceClient = class {
6270
6729
  async updateModifierGroup(storeId, groupId, data) {
6271
6730
  return this.adminRequest(
6272
6731
  "PATCH",
6273
- `/api/stores/${storeId}/modifier-groups/${groupId}`,
6732
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups/${encodePathSegment(groupId)}`,
6274
6733
  data
6275
6734
  );
6276
6735
  }
@@ -6281,7 +6740,10 @@ var BrainerceClient = class {
6281
6740
  * Requires Admin mode (apiKey).
6282
6741
  */
6283
6742
  async deleteModifierGroup(storeId, groupId) {
6284
- await this.adminRequest("DELETE", `/api/stores/${storeId}/modifier-groups/${groupId}`);
6743
+ await this.adminRequest(
6744
+ "DELETE",
6745
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups/${encodePathSegment(groupId)}`
6746
+ );
6285
6747
  }
6286
6748
  /**
6287
6749
  * Create a modifier inside a group (e.g., "Olives" inside the "Toppings" group).
@@ -6305,7 +6767,7 @@ var BrainerceClient = class {
6305
6767
  async createModifier(storeId, groupId, data) {
6306
6768
  return this.adminRequest(
6307
6769
  "POST",
6308
- `/api/stores/${storeId}/modifier-groups/${groupId}/modifiers`,
6770
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups/${encodePathSegment(groupId)}/modifiers`,
6309
6771
  data
6310
6772
  );
6311
6773
  }
@@ -6316,7 +6778,7 @@ var BrainerceClient = class {
6316
6778
  async updateModifier(storeId, groupId, modifierId, data) {
6317
6779
  return this.adminRequest(
6318
6780
  "PATCH",
6319
- `/api/stores/${storeId}/modifier-groups/${groupId}/modifiers/${modifierId}`,
6781
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups/${encodePathSegment(groupId)}/modifiers/${encodePathSegment(modifierId)}`,
6320
6782
  data
6321
6783
  );
6322
6784
  }
@@ -6328,7 +6790,7 @@ var BrainerceClient = class {
6328
6790
  async deleteModifier(storeId, groupId, modifierId) {
6329
6791
  await this.adminRequest(
6330
6792
  "DELETE",
6331
- `/api/stores/${storeId}/modifier-groups/${groupId}/modifiers/${modifierId}`
6793
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups/${encodePathSegment(groupId)}/modifiers/${encodePathSegment(modifierId)}`
6332
6794
  );
6333
6795
  }
6334
6796
  /**
@@ -6347,7 +6809,7 @@ var BrainerceClient = class {
6347
6809
  async toggleModifierAvailability(storeId, groupId, modifierId, available) {
6348
6810
  return this.adminRequest(
6349
6811
  "POST",
6350
- `/api/stores/${storeId}/modifier-groups/${groupId}/modifiers/${modifierId}/availability-toggle`,
6812
+ `/api/stores/${encodePathSegment(storeId)}/modifier-groups/${encodePathSegment(groupId)}/modifiers/${encodePathSegment(modifierId)}/availability-toggle`,
6351
6813
  { available }
6352
6814
  );
6353
6815
  }
@@ -6368,7 +6830,7 @@ var BrainerceClient = class {
6368
6830
  async attachModifierGroup(storeId, productId, data) {
6369
6831
  return this.adminRequest(
6370
6832
  "POST",
6371
- `/api/stores/${storeId}/products/${productId}/modifier-groups`,
6833
+ `/api/stores/${encodePathSegment(storeId)}/products/${encodePathSegment(productId)}/modifier-groups`,
6372
6834
  data
6373
6835
  );
6374
6836
  }
@@ -6381,7 +6843,7 @@ var BrainerceClient = class {
6381
6843
  async updateAttachment(storeId, productId, attachmentId, data) {
6382
6844
  return this.adminRequest(
6383
6845
  "PATCH",
6384
- `/api/stores/${storeId}/products/${productId}/modifier-groups/${attachmentId}`,
6846
+ `/api/stores/${encodePathSegment(storeId)}/products/${encodePathSegment(productId)}/modifier-groups/${encodePathSegment(attachmentId)}`,
6385
6847
  data
6386
6848
  );
6387
6849
  }
@@ -6392,7 +6854,7 @@ var BrainerceClient = class {
6392
6854
  async detachModifierGroup(storeId, productId, attachmentId) {
6393
6855
  await this.adminRequest(
6394
6856
  "DELETE",
6395
- `/api/stores/${storeId}/products/${productId}/modifier-groups/${attachmentId}`
6857
+ `/api/stores/${encodePathSegment(storeId)}/products/${encodePathSegment(productId)}/modifier-groups/${encodePathSegment(attachmentId)}`
6396
6858
  );
6397
6859
  }
6398
6860
  // -------------------- Shipping: Zones and Rates (Admin) --------------------
@@ -6414,7 +6876,10 @@ var BrainerceClient = class {
6414
6876
  * Requires Admin mode (apiKey)
6415
6877
  */
6416
6878
  async getShippingZone(zoneId) {
6417
- return this.adminRequest("GET", `/api/v1/shipping/zones/${zoneId}`);
6879
+ return this.adminRequest(
6880
+ "GET",
6881
+ `/api/v1/shipping/zones/${encodePathSegment(zoneId)}`
6882
+ );
6418
6883
  }
6419
6884
  /**
6420
6885
  * Create a new shipping zone
@@ -6437,21 +6902,28 @@ var BrainerceClient = class {
6437
6902
  * Requires Admin mode (apiKey)
6438
6903
  */
6439
6904
  async updateShippingZone(zoneId, data) {
6440
- return this.adminRequest("PATCH", `/api/v1/shipping/zones/${zoneId}`, data);
6905
+ return this.adminRequest(
6906
+ "PATCH",
6907
+ `/api/v1/shipping/zones/${encodePathSegment(zoneId)}`,
6908
+ data
6909
+ );
6441
6910
  }
6442
6911
  /**
6443
6912
  * Delete a shipping zone
6444
6913
  * Requires Admin mode (apiKey)
6445
6914
  */
6446
6915
  async deleteShippingZone(zoneId) {
6447
- await this.adminRequest("DELETE", `/api/v1/shipping/zones/${zoneId}`);
6916
+ await this.adminRequest("DELETE", `/api/v1/shipping/zones/${encodePathSegment(zoneId)}`);
6448
6917
  }
6449
6918
  /**
6450
6919
  * Get all shipping rates for a zone
6451
6920
  * Requires Admin mode (apiKey)
6452
6921
  */
6453
6922
  async getZoneShippingRates(zoneId) {
6454
- return this.adminRequest("GET", `/api/v1/shipping/zones/${zoneId}/rates`);
6923
+ return this.adminRequest(
6924
+ "GET",
6925
+ `/api/v1/shipping/zones/${encodePathSegment(zoneId)}/rates`
6926
+ );
6455
6927
  }
6456
6928
  /**
6457
6929
  * Create a new shipping rate for a zone
@@ -6471,7 +6943,7 @@ var BrainerceClient = class {
6471
6943
  async createZoneShippingRate(zoneId, data) {
6472
6944
  return this.adminRequest(
6473
6945
  "POST",
6474
- `/api/v1/shipping/zones/${zoneId}/rates`,
6946
+ `/api/v1/shipping/zones/${encodePathSegment(zoneId)}/rates`,
6475
6947
  data
6476
6948
  );
6477
6949
  }
@@ -6482,7 +6954,7 @@ var BrainerceClient = class {
6482
6954
  async updateZoneShippingRate(zoneId, rateId, data) {
6483
6955
  return this.adminRequest(
6484
6956
  "PATCH",
6485
- `/api/v1/shipping/zones/${zoneId}/rates/${rateId}`,
6957
+ `/api/v1/shipping/zones/${encodePathSegment(zoneId)}/rates/${encodePathSegment(rateId)}`,
6486
6958
  data
6487
6959
  );
6488
6960
  }
@@ -6491,7 +6963,149 @@ var BrainerceClient = class {
6491
6963
  * Requires Admin mode (apiKey)
6492
6964
  */
6493
6965
  async deleteZoneShippingRate(zoneId, rateId) {
6494
- await this.adminRequest("DELETE", `/api/v1/shipping/zones/${zoneId}/rates/${rateId}`);
6966
+ await this.adminRequest(
6967
+ "DELETE",
6968
+ `/api/v1/shipping/zones/${encodePathSegment(zoneId)}/rates/${encodePathSegment(rateId)}`
6969
+ );
6970
+ }
6971
+ // -------------------- Regions (Admin mode, apiKey) --------------------
6972
+ // Multi-region commerce. storeId is derived from the api_key — do not pass it.
6973
+ // Requires the `regions:read` / `regions:write` scopes on the key.
6974
+ /** List the store's regions (paginated). */
6975
+ async getRegions() {
6976
+ return this.adminRequest("GET", "/api/v1/regions");
6977
+ }
6978
+ async getRegion(regionId) {
6979
+ return this.adminRequest("GET", `/api/v1/regions/${encodePathSegment(regionId)}`);
6980
+ }
6981
+ async createRegion(data) {
6982
+ return this.adminRequest("POST", "/api/v1/regions", data);
6983
+ }
6984
+ async updateRegion(regionId, data) {
6985
+ return this.adminRequest(
6986
+ "PATCH",
6987
+ `/api/v1/regions/${encodePathSegment(regionId)}`,
6988
+ data
6989
+ );
6990
+ }
6991
+ async deleteRegion(regionId) {
6992
+ await this.adminRequest("DELETE", `/api/v1/regions/${encodePathSegment(regionId)}`);
6993
+ }
6994
+ async setDefaultRegion(regionId) {
6995
+ return this.adminRequest(
6996
+ "PATCH",
6997
+ `/api/v1/regions/${encodePathSegment(regionId)}/set-default`
6998
+ );
6999
+ }
7000
+ /** Replace the region's enabled payment providers (AppInstallation IDs). */
7001
+ async updateRegionPaymentProviders(regionId, providerIds) {
7002
+ return this.adminRequest(
7003
+ "PUT",
7004
+ `/api/v1/regions/${encodePathSegment(regionId)}/payment-providers`,
7005
+ { providerIds }
7006
+ );
7007
+ }
7008
+ async addRegionCountries(regionId, countries) {
7009
+ return this.adminRequest(
7010
+ "POST",
7011
+ `/api/v1/regions/${encodePathSegment(regionId)}/countries`,
7012
+ { countries }
7013
+ );
7014
+ }
7015
+ async removeRegionCountry(regionId, countryCode) {
7016
+ return this.adminRequest(
7017
+ "DELETE",
7018
+ `/api/v1/regions/${encodePathSegment(regionId)}/countries/${encodePathSegment(countryCode)}`
7019
+ );
7020
+ }
7021
+ /** Installed payment providers compatible with this region's countries. */
7022
+ async getRegionCompatibleProviders(regionId) {
7023
+ return this.adminRequest(
7024
+ "GET",
7025
+ `/api/v1/regions/${encodePathSegment(regionId)}/compatible-providers`
7026
+ );
7027
+ }
7028
+ // -------------------- Regions (Storefront mode, public — no apiKey) --------------------
7029
+ // storeId-based, no auth. Call these from a storefront to detect the buyer's
7030
+ // region (story S1), then pair with detectRegion(). Admin/api-key callers use
7031
+ // getRegions()/getRegion() instead.
7032
+ /**
7033
+ * List the store's ACTIVE regions (public, no apiKey). Requires storeId mode.
7034
+ * Returns only storefront-safe fields (no internal flags). Default region first.
7035
+ */
7036
+ async getStoreRegions() {
7037
+ return this.storefrontRequest("GET", "/regions");
7038
+ }
7039
+ /**
7040
+ * Get one active public region plus its enabled payment providers (public).
7041
+ * Requires storeId mode. Throws 404 if the region is inactive or not found.
7042
+ */
7043
+ async getStoreRegion(regionId) {
7044
+ return this.storefrontRequest(
7045
+ "GET",
7046
+ `/regions/${encodePathSegment(regionId)}`
7047
+ );
7048
+ }
7049
+ /**
7050
+ * Client-side region detection — no network call. Returns the region whose
7051
+ * `countries` includes `country`, else the default region, else null.
7052
+ */
7053
+ detectRegion(country, regions) {
7054
+ const code = country.toUpperCase();
7055
+ return regions.find((r) => r.countries.includes(code)) ?? regions.find((r) => r.isDefault) ?? null;
7056
+ }
7057
+ // -------------------- Tax Classes (Storefront mode, public — no apiKey) --------------------
7058
+ /**
7059
+ * List the store's tax classes (public, no apiKey — storeId mode). Storefront-
7060
+ * safe fields only (id/name/slug/description/isDefault) for transparency UIs
7061
+ * such as a "9% VAT" badge. Admin/api-key callers use getTaxClasses().
7062
+ */
7063
+ async getStoreTaxClasses() {
7064
+ return this.storefrontRequest("GET", "/tax-classes");
7065
+ }
7066
+ // -------------------- Tax Classes (Admin mode, apiKey) --------------------
7067
+ // Requires the `tax-classes:read` / `tax-classes:write` scopes on the key.
7068
+ /** List the store's tax classes. */
7069
+ async getTaxClasses() {
7070
+ return this.adminRequest("GET", "/api/v1/tax-classes");
7071
+ }
7072
+ /** Get a tax class with its dependent counts (products/variants/categories/rates). */
7073
+ async getTaxClass(id) {
7074
+ return this.adminRequest("GET", `/api/v1/tax-classes/${encodePathSegment(id)}`);
7075
+ }
7076
+ async createTaxClass(data) {
7077
+ return this.adminRequest("POST", "/api/v1/tax-classes", data);
7078
+ }
7079
+ async updateTaxClass(id, data) {
7080
+ return this.adminRequest(
7081
+ "PATCH",
7082
+ `/api/v1/tax-classes/${encodePathSegment(id)}`,
7083
+ data
7084
+ );
7085
+ }
7086
+ async deleteTaxClass(id) {
7087
+ await this.adminRequest("DELETE", `/api/v1/tax-classes/${encodePathSegment(id)}`);
7088
+ }
7089
+ async setDefaultTaxClass(id) {
7090
+ return this.adminRequest(
7091
+ "PATCH",
7092
+ `/api/v1/tax-classes/${encodePathSegment(id)}/set-default`
7093
+ );
7094
+ }
7095
+ /** Bulk-assign this tax class to products / variants / categories. */
7096
+ async assignTaxClass(id, data) {
7097
+ return this.adminRequest(
7098
+ "POST",
7099
+ `/api/v1/tax-classes/${encodePathSegment(id)}/assign`,
7100
+ data
7101
+ );
7102
+ }
7103
+ /** Merge this tax class into another, moving all FKs, then delete it. */
7104
+ async mergeTaxClasses(id, targetId) {
7105
+ await this.adminRequest(
7106
+ "POST",
7107
+ `/api/v1/tax-classes/${encodePathSegment(id)}/merge-into/${encodePathSegment(targetId)}`
7108
+ );
6495
7109
  }
6496
7110
  // -------------------- Tax: Rates --------------------
6497
7111
  // These methods require Admin mode (apiKey)
@@ -6507,7 +7121,7 @@ var BrainerceClient = class {
6507
7121
  * Requires Admin mode (apiKey)
6508
7122
  */
6509
7123
  async getTaxRate(rateId) {
6510
- return this.adminRequest("GET", `/api/v1/tax/rates/${rateId}`);
7124
+ return this.adminRequest("GET", `/api/v1/tax/rates/${encodePathSegment(rateId)}`);
6511
7125
  }
6512
7126
  /**
6513
7127
  * Create a new tax rate
@@ -6532,14 +7146,18 @@ var BrainerceClient = class {
6532
7146
  * Requires Admin mode (apiKey)
6533
7147
  */
6534
7148
  async updateTaxRate(rateId, data) {
6535
- return this.adminRequest("PATCH", `/api/v1/tax/rates/${rateId}`, data);
7149
+ return this.adminRequest(
7150
+ "PATCH",
7151
+ `/api/v1/tax/rates/${encodePathSegment(rateId)}`,
7152
+ data
7153
+ );
6536
7154
  }
6537
7155
  /**
6538
7156
  * Delete a tax rate
6539
7157
  * Requires Admin mode (apiKey)
6540
7158
  */
6541
7159
  async deleteTaxRate(rateId) {
6542
- await this.adminRequest("DELETE", `/api/v1/tax/rates/${rateId}`);
7160
+ await this.adminRequest("DELETE", `/api/v1/tax/rates/${encodePathSegment(rateId)}`);
6543
7161
  }
6544
7162
  // -------------------- Metafields: Definitions --------------------
6545
7163
  // These methods require Admin mode (apiKey)
@@ -6595,7 +7213,7 @@ var BrainerceClient = class {
6595
7213
  async getMetafieldDefinition(definitionId) {
6596
7214
  return this.adminRequest(
6597
7215
  "GET",
6598
- `/api/v1/metafield-definitions/${definitionId}`
7216
+ `/api/v1/metafield-definitions/${encodePathSegment(definitionId)}`
6599
7217
  );
6600
7218
  }
6601
7219
  /**
@@ -6622,7 +7240,7 @@ var BrainerceClient = class {
6622
7240
  async updateMetafieldDefinition(definitionId, data) {
6623
7241
  return this.adminRequest(
6624
7242
  "PATCH",
6625
- `/api/v1/metafield-definitions/${definitionId}`,
7243
+ `/api/v1/metafield-definitions/${encodePathSegment(definitionId)}`,
6626
7244
  data
6627
7245
  );
6628
7246
  }
@@ -6631,7 +7249,10 @@ var BrainerceClient = class {
6631
7249
  * Requires Admin mode (apiKey)
6632
7250
  */
6633
7251
  async deleteMetafieldDefinition(definitionId) {
6634
- await this.adminRequest("DELETE", `/api/v1/metafield-definitions/${definitionId}`);
7252
+ await this.adminRequest(
7253
+ "DELETE",
7254
+ `/api/v1/metafield-definitions/${encodePathSegment(definitionId)}`
7255
+ );
6635
7256
  }
6636
7257
  /**
6637
7258
  * Replace the platform publishing configuration on a metafield definition.
@@ -6655,7 +7276,7 @@ var BrainerceClient = class {
6655
7276
  async setMetafieldPlatforms(definitionId, data) {
6656
7277
  return this.adminRequest(
6657
7278
  "PUT",
6658
- `/api/v1/metafield-definitions/${definitionId}/platforms`,
7279
+ `/api/v1/metafield-definitions/${encodePathSegment(definitionId)}/platforms`,
6659
7280
  data
6660
7281
  );
6661
7282
  }
@@ -6674,7 +7295,7 @@ var BrainerceClient = class {
6674
7295
  async publishMetafieldDefinitionToVibeCodedSite(definitionId, vibeCodedConnectionId) {
6675
7296
  return this.adminRequest(
6676
7297
  "POST",
6677
- `/api/v1/metafield-definitions/${definitionId}/publish-vibe-coded`,
7298
+ `/api/v1/metafield-definitions/${encodePathSegment(definitionId)}/publish-vibe-coded`,
6678
7299
  { vibeCodedConnectionId }
6679
7300
  );
6680
7301
  }
@@ -6682,7 +7303,7 @@ var BrainerceClient = class {
6682
7303
  async unpublishMetafieldDefinitionFromVibeCodedSite(definitionId, vibeCodedConnectionId) {
6683
7304
  return this.adminRequest(
6684
7305
  "POST",
6685
- `/api/v1/metafield-definitions/${definitionId}/unpublish-vibe-coded`,
7306
+ `/api/v1/metafield-definitions/${encodePathSegment(definitionId)}/unpublish-vibe-coded`,
6686
7307
  { vibeCodedConnectionId }
6687
7308
  );
6688
7309
  }
@@ -6690,7 +7311,7 @@ var BrainerceClient = class {
6690
7311
  async publishCategoryToVibeCodedSite(categoryId, vibeCodedConnectionId) {
6691
7312
  return this.adminRequest(
6692
7313
  "POST",
6693
- `/api/v1/categories/${categoryId}/publish-vibe-coded`,
7314
+ `/api/v1/categories/${encodePathSegment(categoryId)}/publish-vibe-coded`,
6694
7315
  { vibeCodedConnectionId }
6695
7316
  );
6696
7317
  }
@@ -6698,7 +7319,7 @@ var BrainerceClient = class {
6698
7319
  async unpublishCategoryFromVibeCodedSite(categoryId, vibeCodedConnectionId) {
6699
7320
  return this.adminRequest(
6700
7321
  "POST",
6701
- `/api/v1/categories/${categoryId}/unpublish-vibe-coded`,
7322
+ `/api/v1/categories/${encodePathSegment(categoryId)}/unpublish-vibe-coded`,
6702
7323
  { vibeCodedConnectionId }
6703
7324
  );
6704
7325
  }
@@ -6706,7 +7327,7 @@ var BrainerceClient = class {
6706
7327
  async publishTagToVibeCodedSite(tagId, vibeCodedConnectionId) {
6707
7328
  return this.adminRequest(
6708
7329
  "POST",
6709
- `/api/v1/tags/${tagId}/publish-vibe-coded`,
7330
+ `/api/v1/tags/${encodePathSegment(tagId)}/publish-vibe-coded`,
6710
7331
  { vibeCodedConnectionId }
6711
7332
  );
6712
7333
  }
@@ -6714,7 +7335,7 @@ var BrainerceClient = class {
6714
7335
  async unpublishTagFromVibeCodedSite(tagId, vibeCodedConnectionId) {
6715
7336
  return this.adminRequest(
6716
7337
  "POST",
6717
- `/api/v1/tags/${tagId}/unpublish-vibe-coded`,
7338
+ `/api/v1/tags/${encodePathSegment(tagId)}/unpublish-vibe-coded`,
6718
7339
  { vibeCodedConnectionId }
6719
7340
  );
6720
7341
  }
@@ -6722,7 +7343,7 @@ var BrainerceClient = class {
6722
7343
  async publishBrandToVibeCodedSite(brandId, vibeCodedConnectionId) {
6723
7344
  return this.adminRequest(
6724
7345
  "POST",
6725
- `/api/v1/brands/${brandId}/publish-vibe-coded`,
7346
+ `/api/v1/brands/${encodePathSegment(brandId)}/publish-vibe-coded`,
6726
7347
  { vibeCodedConnectionId }
6727
7348
  );
6728
7349
  }
@@ -6730,7 +7351,7 @@ var BrainerceClient = class {
6730
7351
  async unpublishBrandFromVibeCodedSite(brandId, vibeCodedConnectionId) {
6731
7352
  return this.adminRequest(
6732
7353
  "POST",
6733
- `/api/v1/brands/${brandId}/unpublish-vibe-coded`,
7354
+ `/api/v1/brands/${encodePathSegment(brandId)}/unpublish-vibe-coded`,
6734
7355
  { vibeCodedConnectionId }
6735
7356
  );
6736
7357
  }
@@ -6756,7 +7377,7 @@ var BrainerceClient = class {
6756
7377
  async setDefinitionProducts(definitionId, data) {
6757
7378
  return this.adminRequest(
6758
7379
  "PATCH",
6759
- `/api/v1/metafield-definitions/${definitionId}/products`,
7380
+ `/api/v1/metafield-definitions/${encodePathSegment(definitionId)}/products`,
6760
7381
  data
6761
7382
  );
6762
7383
  }
@@ -6769,7 +7390,7 @@ var BrainerceClient = class {
6769
7390
  async getProductMetafields(productId) {
6770
7391
  return this.adminRequest(
6771
7392
  "GET",
6772
- `/api/v1/products/${productId}/metafields`
7393
+ `/api/v1/products/${encodePathSegment(productId)}/metafields`
6773
7394
  );
6774
7395
  }
6775
7396
  /**
@@ -6786,7 +7407,7 @@ var BrainerceClient = class {
6786
7407
  async setProductMetafield(productId, definitionId, data) {
6787
7408
  return this.adminRequest(
6788
7409
  "PUT",
6789
- `/api/v1/products/${productId}/metafields/${definitionId}`,
7410
+ `/api/v1/products/${encodePathSegment(productId)}/metafields/${encodePathSegment(definitionId)}`,
6790
7411
  data
6791
7412
  );
6792
7413
  }
@@ -6797,7 +7418,7 @@ var BrainerceClient = class {
6797
7418
  async deleteProductMetafield(productId, definitionId) {
6798
7419
  await this.adminRequest(
6799
7420
  "DELETE",
6800
- `/api/v1/products/${productId}/metafields/${definitionId}`
7421
+ `/api/v1/products/${encodePathSegment(productId)}/metafields/${encodePathSegment(definitionId)}`
6801
7422
  );
6802
7423
  }
6803
7424
  // -------------------- Product Customization Fields (Admin) --------------------
@@ -6808,7 +7429,7 @@ var BrainerceClient = class {
6808
7429
  async getProductCustomizationFields(productId) {
6809
7430
  return this.adminRequest(
6810
7431
  "GET",
6811
- `/api/v1/metafield-definitions/products/${productId}/customization-fields`
7432
+ `/api/v1/metafield-definitions/products/${encodePathSegment(productId)}/customization-fields`
6812
7433
  );
6813
7434
  }
6814
7435
  /**
@@ -6819,7 +7440,7 @@ var BrainerceClient = class {
6819
7440
  async setProductCustomizationFields(productId, definitionIds) {
6820
7441
  return this.adminRequest(
6821
7442
  "PATCH",
6822
- `/api/v1/metafield-definitions/products/${productId}/customization-fields`,
7443
+ `/api/v1/metafield-definitions/products/${encodePathSegment(productId)}/customization-fields`,
6823
7444
  { definitionIds }
6824
7445
  );
6825
7446
  }
@@ -6899,26 +7520,33 @@ var BrainerceClient = class {
6899
7520
  async resendTeamInvitation(invitationId) {
6900
7521
  return this.adminRequest(
6901
7522
  "POST",
6902
- `/api/v1/team/invitations/${invitationId}/resend`
7523
+ `/api/v1/team/invitations/${encodePathSegment(invitationId)}/resend`
6903
7524
  );
6904
7525
  }
6905
7526
  /**
6906
7527
  * @deprecated Use `revokeStoreInvitation(storeId, invitationId)` instead.
6907
7528
  */
6908
7529
  async revokeTeamInvitation(invitationId) {
6909
- await this.adminRequest("DELETE", `/api/v1/team/invitations/${invitationId}`);
7530
+ await this.adminRequest(
7531
+ "DELETE",
7532
+ `/api/v1/team/invitations/${encodePathSegment(invitationId)}`
7533
+ );
6910
7534
  }
6911
7535
  /**
6912
7536
  * @deprecated Use `updateStoreMember(storeId, memberId, data)` instead.
6913
7537
  */
6914
7538
  async updateTeamMemberRole(memberId, data) {
6915
- return this.adminRequest("PATCH", `/api/v1/team/members/${memberId}/role`, data);
7539
+ return this.adminRequest(
7540
+ "PATCH",
7541
+ `/api/v1/team/members/${encodePathSegment(memberId)}/role`,
7542
+ data
7543
+ );
6916
7544
  }
6917
7545
  /**
6918
7546
  * @deprecated Use `removeStoreMember(storeId, memberId)` instead.
6919
7547
  */
6920
7548
  async removeTeamMember(memberId) {
6921
- await this.adminRequest("DELETE", `/api/v1/team/members/${memberId}`);
7549
+ await this.adminRequest("DELETE", `/api/v1/team/members/${encodePathSegment(memberId)}`);
6922
7550
  }
6923
7551
  // -------------------- Store Team Management (Admin) --------------------
6924
7552
  // Store-level team management. Each store has its own team with roles and permissions.
@@ -6932,7 +7560,10 @@ var BrainerceClient = class {
6932
7560
  * ```
6933
7561
  */
6934
7562
  async getStoreTeam(storeId) {
6935
- return this.adminRequest("GET", `/api/v1/stores/${storeId}/team`);
7563
+ return this.adminRequest(
7564
+ "GET",
7565
+ `/api/v1/stores/${encodePathSegment(storeId)}/team`
7566
+ );
6936
7567
  }
6937
7568
  /**
6938
7569
  * Invite a new member to a store
@@ -6943,13 +7574,16 @@ var BrainerceClient = class {
6943
7574
  * const invitation = await client.inviteStoreMember('store_id', {
6944
7575
  * email: 'newmember@example.com',
6945
7576
  * role: 'MANAGER', // 'MANAGER' | 'STAFF' | 'VIEWER'
7577
+ * // Optional: restrict to specific vibe-coded channels (connectionId, vc_*).
7578
+ * // Omit or pass [] for unrestricted access to all channels.
7579
+ * salesChannelIds: ['vc_abc123', 'vc_def456'],
6946
7580
  * });
6947
7581
  * ```
6948
7582
  */
6949
7583
  async inviteStoreMember(storeId, data) {
6950
7584
  return this.adminRequest(
6951
7585
  "POST",
6952
- `/api/v1/stores/${storeId}/team/invite`,
7586
+ `/api/v1/stores/${encodePathSegment(storeId)}/team/invite`,
6953
7587
  data
6954
7588
  );
6955
7589
  }
@@ -6971,7 +7605,33 @@ var BrainerceClient = class {
6971
7605
  async updateStoreMember(storeId, memberId, data) {
6972
7606
  return this.adminRequest(
6973
7607
  "PATCH",
6974
- `/api/v1/stores/${storeId}/team/${memberId}`,
7608
+ `/api/v1/stores/${encodePathSegment(storeId)}/team/${encodePathSegment(memberId)}`,
7609
+ data
7610
+ );
7611
+ }
7612
+ /**
7613
+ * Replace the set of vibe-coded sales channels a store member is restricted to.
7614
+ * Channels are identified by their public `connectionId` (`vc_*` format). Pass
7615
+ * an empty array to clear all restrictions (member becomes unrestricted).
7616
+ * Requires Admin mode (apiKey) and MANAGE_TEAM permission
7617
+ *
7618
+ * @example
7619
+ * ```typescript
7620
+ * // Restrict to two vibe-coded channels
7621
+ * await client.updateStoreMemberSalesChannels('store_id', 'member_id', {
7622
+ * salesChannelIds: ['vc_abc123', 'vc_def456'],
7623
+ * });
7624
+ *
7625
+ * // Clear all restrictions (unrestricted access)
7626
+ * await client.updateStoreMemberSalesChannels('store_id', 'member_id', {
7627
+ * salesChannelIds: [],
7628
+ * });
7629
+ * ```
7630
+ */
7631
+ async updateStoreMemberSalesChannels(storeId, memberId, data) {
7632
+ return this.adminRequest(
7633
+ "PATCH",
7634
+ `/api/v1/stores/${encodePathSegment(storeId)}/team/${encodePathSegment(memberId)}/sales-channels`,
6975
7635
  data
6976
7636
  );
6977
7637
  }
@@ -6980,7 +7640,10 @@ var BrainerceClient = class {
6980
7640
  * Requires Admin mode (apiKey) and MANAGE_TEAM permission
6981
7641
  */
6982
7642
  async removeStoreMember(storeId, memberId) {
6983
- await this.adminRequest("DELETE", `/api/v1/stores/${storeId}/team/${memberId}`);
7643
+ await this.adminRequest(
7644
+ "DELETE",
7645
+ `/api/v1/stores/${encodePathSegment(storeId)}/team/${encodePathSegment(memberId)}`
7646
+ );
6984
7647
  }
6985
7648
  /**
6986
7649
  * Resend a store invitation email
@@ -6989,7 +7652,7 @@ var BrainerceClient = class {
6989
7652
  async resendStoreInvitation(storeId, invitationId) {
6990
7653
  return this.adminRequest(
6991
7654
  "POST",
6992
- `/api/v1/stores/${storeId}/team/invitations/${invitationId}/resend`
7655
+ `/api/v1/stores/${encodePathSegment(storeId)}/team/invitations/${encodePathSegment(invitationId)}/resend`
6993
7656
  );
6994
7657
  }
6995
7658
  /**
@@ -6999,7 +7662,7 @@ var BrainerceClient = class {
6999
7662
  async revokeStoreInvitation(storeId, invitationId) {
7000
7663
  await this.adminRequest(
7001
7664
  "DELETE",
7002
- `/api/v1/stores/${storeId}/team/invitations/${invitationId}`
7665
+ `/api/v1/stores/${encodePathSegment(storeId)}/team/invitations/${encodePathSegment(invitationId)}`
7003
7666
  );
7004
7667
  }
7005
7668
  /**
@@ -7007,14 +7670,20 @@ var BrainerceClient = class {
7007
7670
  * Used on the invitation acceptance page
7008
7671
  */
7009
7672
  async getStoreInvitationByToken(token) {
7010
- return this.request("GET", `/api/v1/store-invitations/${token}`);
7673
+ return this.request(
7674
+ "GET",
7675
+ `/api/v1/store-invitations/${encodePathSegment(token)}`
7676
+ );
7011
7677
  }
7012
7678
  /**
7013
7679
  * Accept a store invitation
7014
7680
  * Requires Admin mode (apiKey)
7015
7681
  */
7016
7682
  async acceptStoreInvitation(token) {
7017
- await this.adminRequest("POST", `/api/v1/store-invitations/${token}/accept`);
7683
+ await this.adminRequest(
7684
+ "POST",
7685
+ `/api/v1/store-invitations/${encodePathSegment(token)}/accept`
7686
+ );
7018
7687
  }
7019
7688
  /**
7020
7689
  * Get all stores accessible to the current user (owned + member of)
@@ -7047,7 +7716,7 @@ var BrainerceClient = class {
7047
7716
  async getMyStorePermissions(storeId) {
7048
7717
  return this.adminRequest(
7049
7718
  "GET",
7050
- `/api/v1/me/stores/${storeId}/permissions`
7719
+ `/api/v1/me/stores/${encodePathSegment(storeId)}/permissions`
7051
7720
  );
7052
7721
  }
7053
7722
  // -------------------- Email Settings & Templates (Admin) --------------------
@@ -7080,7 +7749,10 @@ var BrainerceClient = class {
7080
7749
  * Requires Admin mode (apiKey)
7081
7750
  */
7082
7751
  async getEmailTemplate(templateId) {
7083
- return this.adminRequest("GET", `/api/v1/email/templates/${templateId}`);
7752
+ return this.adminRequest(
7753
+ "GET",
7754
+ `/api/v1/email/templates/${encodePathSegment(templateId)}`
7755
+ );
7084
7756
  }
7085
7757
  /**
7086
7758
  * Create a new email template
@@ -7104,14 +7776,21 @@ var BrainerceClient = class {
7104
7776
  * Requires Admin mode (apiKey)
7105
7777
  */
7106
7778
  async updateEmailTemplate(templateId, data) {
7107
- return this.adminRequest("PUT", `/api/v1/email/templates/${templateId}`, data);
7779
+ return this.adminRequest(
7780
+ "PUT",
7781
+ `/api/v1/email/templates/${encodePathSegment(templateId)}`,
7782
+ data
7783
+ );
7108
7784
  }
7109
7785
  /**
7110
7786
  * Delete an email template
7111
7787
  * Requires Admin mode (apiKey)
7112
7788
  */
7113
7789
  async deleteEmailTemplate(templateId) {
7114
- await this.adminRequest("DELETE", `/api/v1/email/templates/${templateId}`);
7790
+ await this.adminRequest(
7791
+ "DELETE",
7792
+ `/api/v1/email/templates/${encodePathSegment(templateId)}`
7793
+ );
7115
7794
  }
7116
7795
  /**
7117
7796
  * Preview an email template with sample data
@@ -7120,7 +7799,7 @@ var BrainerceClient = class {
7120
7799
  async previewEmailTemplate(templateId, data) {
7121
7800
  return this.adminRequest(
7122
7801
  "POST",
7123
- `/api/v1/email/templates/${templateId}/preview`,
7802
+ `/api/v1/email/templates/${encodePathSegment(templateId)}/preview`,
7124
7803
  data || {}
7125
7804
  );
7126
7805
  }
@@ -7141,9 +7820,13 @@ var BrainerceClient = class {
7141
7820
  * @param resolution - 'MERGE' to link to existing product, 'CREATE_NEW' to create new product
7142
7821
  */
7143
7822
  async resolveSyncConflict(conflictId, resolution) {
7144
- return this.adminRequest("POST", `/api/v1/sync-conflicts/${conflictId}/resolve`, {
7145
- resolution
7146
- });
7823
+ return this.adminRequest(
7824
+ "POST",
7825
+ `/api/v1/sync-conflicts/${encodePathSegment(conflictId)}/resolve`,
7826
+ {
7827
+ resolution
7828
+ }
7829
+ );
7147
7830
  }
7148
7831
  // -------------------- Metafield Conflicts (Admin) --------------------
7149
7832
  // These methods require Admin mode (apiKey)
@@ -7164,7 +7847,7 @@ var BrainerceClient = class {
7164
7847
  async resolveMetafieldConflict(conflictId, data) {
7165
7848
  return this.adminRequest(
7166
7849
  "POST",
7167
- `/api/v1/metafield-conflicts/${conflictId}/resolve`,
7850
+ `/api/v1/metafield-conflicts/${encodePathSegment(conflictId)}/resolve`,
7168
7851
  data
7169
7852
  );
7170
7853
  }
@@ -7175,7 +7858,7 @@ var BrainerceClient = class {
7175
7858
  async ignoreMetafieldConflict(conflictId) {
7176
7859
  return this.adminRequest(
7177
7860
  "POST",
7178
- `/api/v1/metafield-conflicts/${conflictId}/ignore`
7861
+ `/api/v1/metafield-conflicts/${encodePathSegment(conflictId)}/ignore`
7179
7862
  );
7180
7863
  }
7181
7864
  // -------------------- OAuth Provider Configuration (Admin) --------------------
@@ -7192,7 +7875,10 @@ var BrainerceClient = class {
7192
7875
  * Requires Admin mode (apiKey)
7193
7876
  */
7194
7877
  async getOAuthProvider(provider) {
7195
- return this.adminRequest("GET", `/api/v1/oauth-providers/${provider}`);
7878
+ return this.adminRequest(
7879
+ "GET",
7880
+ `/api/v1/oauth-providers/${encodePathSegment(provider)}`
7881
+ );
7196
7882
  }
7197
7883
  /**
7198
7884
  * Configure an OAuth provider for customer login
@@ -7218,7 +7904,7 @@ var BrainerceClient = class {
7218
7904
  async updateOAuthProvider(provider, data) {
7219
7905
  return this.adminRequest(
7220
7906
  "PATCH",
7221
- `/api/v1/oauth-providers/${provider}`,
7907
+ `/api/v1/oauth-providers/${encodePathSegment(provider)}`,
7222
7908
  data
7223
7909
  );
7224
7910
  }
@@ -7227,7 +7913,10 @@ var BrainerceClient = class {
7227
7913
  * Requires Admin mode (apiKey)
7228
7914
  */
7229
7915
  async deleteOAuthProvider(provider) {
7230
- await this.adminRequest("DELETE", `/api/v1/oauth-providers/${provider}`);
7916
+ await this.adminRequest(
7917
+ "DELETE",
7918
+ `/api/v1/oauth-providers/${encodePathSegment(provider)}`
7919
+ );
7231
7920
  }
7232
7921
  };
7233
7922
  var BrainerceError = class extends Error {
@@ -7324,7 +8013,7 @@ var ALLOWED_PAYMENT_HOSTS = [
7324
8013
  // Brainerce-hosted payment embeds (backend payment-embed proxy at
7325
8014
  // `/api/payment/embed/...` that fronts provider apps' embed shells —
7326
8015
  // e.g. cardcom-payments OpenFields wrapper). The match also covers
7327
- // subdomains like `api.brainerce.com`, `staging.brainerce.com`.
8016
+ // every brainerce.com subdomain (api., docs., …).
7328
8017
  "brainerce.com"
7329
8018
  ];
7330
8019
  function isAllowedPaymentUrl(url, options) {
@@ -7352,6 +8041,55 @@ function safePaymentRedirect(url, options) {
7352
8041
  }
7353
8042
  }
7354
8043
 
8044
+ // src/format-price.ts
8045
+ var DEFAULT_LOCALE = "en";
8046
+ function formatProductPrice(product, options = {}) {
8047
+ const { locale = DEFAULT_LOCALE, prefer = "sale-if-available", storeCurrency } = options;
8048
+ const usingDisplay = product.displayPrice != null;
8049
+ const currency = usingDisplay ? product.displayCurrency : storeCurrency;
8050
+ const baseAmount = usingDisplay ? product.displayPrice : product.basePrice;
8051
+ const saleAmount = usingDisplay ? product.displaySalePrice : product.salePrice;
8052
+ const amount = prefer === "sale-if-available" && saleAmount != null && saleAmount !== "" ? saleAmount : baseAmount;
8053
+ if (amount == null || amount === "") return null;
8054
+ const parsed = parseFloat(amount);
8055
+ if (Number.isNaN(parsed)) return null;
8056
+ return formatAmount(parsed, currency, locale);
8057
+ }
8058
+ function formatVariantPrice(variant, options = {}) {
8059
+ const { locale = DEFAULT_LOCALE, prefer = "sale-if-available", storeCurrency } = options;
8060
+ const usingDisplay = variant.displayPrice != null;
8061
+ const currency = usingDisplay ? variant.displayCurrency : storeCurrency;
8062
+ const baseAmount = usingDisplay ? variant.displayPrice : variant.price;
8063
+ const saleAmount = usingDisplay ? variant.displaySalePrice : variant.salePrice;
8064
+ const amount = prefer === "sale-if-available" && saleAmount != null && saleAmount !== "" ? saleAmount : baseAmount;
8065
+ if (amount == null || amount === "") return null;
8066
+ const parsed = parseFloat(amount);
8067
+ if (Number.isNaN(parsed)) return null;
8068
+ return formatAmount(parsed, currency, locale);
8069
+ }
8070
+ function formatMoney(amount, currency, locale = DEFAULT_LOCALE) {
8071
+ return formatAmount(amount, currency, locale);
8072
+ }
8073
+ function formatAmount(amount, currency, locale) {
8074
+ if (!currency) {
8075
+ return new Intl.NumberFormat(locale, {
8076
+ minimumFractionDigits: 2,
8077
+ maximumFractionDigits: 2
8078
+ }).format(amount);
8079
+ }
8080
+ try {
8081
+ return new Intl.NumberFormat(locale, {
8082
+ style: "currency",
8083
+ currency
8084
+ }).format(amount);
8085
+ } catch {
8086
+ return new Intl.NumberFormat(locale, {
8087
+ minimumFractionDigits: 2,
8088
+ maximumFractionDigits: 2
8089
+ }).format(amount);
8090
+ }
8091
+ }
8092
+
7355
8093
  // src/types.ts
7356
8094
  function isHtmlDescription(product) {
7357
8095
  if (product?.descriptionFormat === "html") return true;
@@ -7443,7 +8181,9 @@ function getProductPriceInfo(product) {
7443
8181
  if (!product) {
7444
8182
  return { price: 0, originalPrice: 0, isOnSale: false, discountAmount: 0, discountPercent: 0 };
7445
8183
  }
7446
- const resolvedBasePrice = parseFloat(product.basePrice) === 0 && product.priceMin ? product.priceMin : product.basePrice;
8184
+ const parsedBase = parseFloat(product.basePrice);
8185
+ const baseIsUsable = typeof product.basePrice === "string" && product.basePrice.length > 0 && !isNaN(parsedBase) && parsedBase > 0;
8186
+ const resolvedBasePrice = !baseIsUsable && product.priceMin ? product.priceMin : product.basePrice;
7447
8187
  if (product.discount) {
7448
8188
  const ruleOriginal = parseFloat(product.discount.originalPrice) || 0;
7449
8189
  const ruleDiscounted = parseFloat(product.discount.discountedPrice) || 0;
@@ -7491,7 +8231,7 @@ function getCartTotals(cart, shippingPrice) {
7491
8231
  const subtotal = parseFloat(cart.subtotal) || 0;
7492
8232
  const discount = parseFloat(cart.discountAmount) || 0;
7493
8233
  const shipping = typeof shippingPrice === "string" ? parseFloat(shippingPrice) || 0 : shippingPrice || 0;
7494
- const total = subtotal - discount + shipping;
8234
+ const total = Math.max(0, subtotal - discount + shipping);
7495
8235
  return { subtotal, discount, shipping, total };
7496
8236
  }
7497
8237
  function getCartItemName(item) {
@@ -7599,7 +8339,10 @@ function isCouponApplicableToProduct(coupon, productId) {
7599
8339
  createWebhookHandler,
7600
8340
  deriveSeoDescription,
7601
8341
  enableDevGuards,
8342
+ formatMoney,
7602
8343
  formatPrice,
8344
+ formatProductPrice,
8345
+ formatVariantPrice,
7603
8346
  getCartItemImage,
7604
8347
  getCartItemName,
7605
8348
  getCartTotals,