brainerce 1.0.0 → 1.0.2
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/AI_BUILDER_PROMPT.md +700 -716
- package/README.md +3974 -4409
- package/dist/index.d.mts +353 -306
- package/dist/index.d.ts +353 -306
- package/dist/index.js +570 -321
- package/dist/index.mjs +559 -325
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/dev-guards.ts
|
|
9
2
|
var CART_GUARDS = [
|
|
10
3
|
{
|
|
@@ -128,24 +121,31 @@ var BrainerceClient = class {
|
|
|
128
121
|
constructor(options) {
|
|
129
122
|
this.customerToken = null;
|
|
130
123
|
this.customerCartId = null;
|
|
124
|
+
// Session cart state (server-side guest carts)
|
|
125
|
+
this.sessionCartId = null;
|
|
126
|
+
this.sessionToken = null;
|
|
127
|
+
this._sessionCartPromise = null;
|
|
128
|
+
this._migrationDone = false;
|
|
129
|
+
/** localStorage key for session cart reference (sessionToken + cartId) */
|
|
130
|
+
this.SESSION_CART_KEY = "brainerce_session";
|
|
131
131
|
/**
|
|
132
132
|
* Virtual cart ID used for localStorage carts (guest users not logged in).
|
|
133
|
-
*
|
|
133
|
+
* @deprecated Guest carts now use server-side sessions. Kept for backward compatibility.
|
|
134
134
|
*/
|
|
135
135
|
this.VIRTUAL_LOCAL_CART_ID = "__local__";
|
|
136
136
|
/**
|
|
137
137
|
* localStorage key for persisting active checkout across page redirects.
|
|
138
138
|
* This is needed because Stripe redirects lose in-memory state.
|
|
139
139
|
*/
|
|
140
|
-
this.ACTIVE_CHECKOUT_KEY = "
|
|
140
|
+
this.ACTIVE_CHECKOUT_KEY = "brainerce_active_checkout";
|
|
141
141
|
// -------------------- Local Cart (Client-Side for Guests) --------------------
|
|
142
142
|
// These methods store cart data in localStorage - NO API calls!
|
|
143
143
|
// Use for guest users in vibe-coded sites
|
|
144
|
-
this.LOCAL_CART_KEY = "
|
|
144
|
+
this.LOCAL_CART_KEY = "brainerce_cart";
|
|
145
145
|
if (!options.apiKey && !options.storeId && !options.connectionId) {
|
|
146
146
|
throw new Error("BrainerceClient: either connectionId, apiKey, or storeId is required");
|
|
147
147
|
}
|
|
148
|
-
if (options.apiKey && !options.apiKey.startsWith("brainerce_")
|
|
148
|
+
if (options.apiKey && !options.apiKey.startsWith("brainerce_")) {
|
|
149
149
|
console.warn('BrainerceClient: apiKey should start with "brainerce_"');
|
|
150
150
|
}
|
|
151
151
|
if (options.connectionId && !options.connectionId.startsWith("vc_")) {
|
|
@@ -162,6 +162,7 @@ var BrainerceClient = class {
|
|
|
162
162
|
this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
163
163
|
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
164
164
|
this.onAuthError = options.onAuthError;
|
|
165
|
+
this.hydrateSessionCart();
|
|
165
166
|
}
|
|
166
167
|
withGuards(result, type) {
|
|
167
168
|
if (!isDevGuardsEnabled()) return result;
|
|
@@ -219,11 +220,11 @@ var BrainerceClient = class {
|
|
|
219
220
|
*
|
|
220
221
|
* @example
|
|
221
222
|
* ```typescript
|
|
222
|
-
* const auth = await
|
|
223
|
-
*
|
|
223
|
+
* const auth = await client.loginCustomer('user@example.com', 'password');
|
|
224
|
+
* client.setCustomerToken(auth.token);
|
|
224
225
|
*
|
|
225
226
|
* // Now can access customer data
|
|
226
|
-
* const profile = await
|
|
227
|
+
* const profile = await client.getMyProfile();
|
|
227
228
|
* ```
|
|
228
229
|
*/
|
|
229
230
|
setCustomerToken(token) {
|
|
@@ -461,10 +462,10 @@ var BrainerceClient = class {
|
|
|
461
462
|
* @example
|
|
462
463
|
* ```typescript
|
|
463
464
|
* // Basic usage
|
|
464
|
-
* const products = await
|
|
465
|
+
* const products = await client.getProducts({ page: 1, limit: 20 });
|
|
465
466
|
*
|
|
466
467
|
* // With filters (vibe-coded mode)
|
|
467
|
-
* const filtered = await
|
|
468
|
+
* const filtered = await client.getProducts({
|
|
468
469
|
* categories: ['cat_123', 'cat_456'],
|
|
469
470
|
* minPrice: 10,
|
|
470
471
|
* maxPrice: 100,
|
|
@@ -535,7 +536,7 @@ var BrainerceClient = class {
|
|
|
535
536
|
* @example
|
|
536
537
|
* ```typescript
|
|
537
538
|
* // Get product by its URL-friendly slug
|
|
538
|
-
* const product = await
|
|
539
|
+
* const product = await client.getProductBySlug('awesome-product-name');
|
|
539
540
|
* ```
|
|
540
541
|
*/
|
|
541
542
|
async getProductBySlug(slug) {
|
|
@@ -553,7 +554,7 @@ var BrainerceClient = class {
|
|
|
553
554
|
*
|
|
554
555
|
* @example
|
|
555
556
|
* ```typescript
|
|
556
|
-
* const { categories } = await
|
|
557
|
+
* const { categories } = await client.getCategories();
|
|
557
558
|
* // categories is a tree structure with children
|
|
558
559
|
* ```
|
|
559
560
|
*/
|
|
@@ -569,7 +570,7 @@ var BrainerceClient = class {
|
|
|
569
570
|
*
|
|
570
571
|
* @example
|
|
571
572
|
* ```typescript
|
|
572
|
-
* const { brands } = await
|
|
573
|
+
* const { brands } = await client.getBrands();
|
|
573
574
|
* // Use brand IDs in getProducts({ brands: ['brand_id'] })
|
|
574
575
|
* ```
|
|
575
576
|
*/
|
|
@@ -585,7 +586,7 @@ var BrainerceClient = class {
|
|
|
585
586
|
*
|
|
586
587
|
* @example
|
|
587
588
|
* ```typescript
|
|
588
|
-
* const { tags } = await
|
|
589
|
+
* const { tags } = await client.getTags();
|
|
589
590
|
* // Use tag IDs in getProducts({ tags: ['tag_id'] })
|
|
590
591
|
* ```
|
|
591
592
|
*/
|
|
@@ -607,12 +608,12 @@ var BrainerceClient = class {
|
|
|
607
608
|
* @example
|
|
608
609
|
* ```typescript
|
|
609
610
|
* // Basic autocomplete
|
|
610
|
-
* const suggestions = await
|
|
611
|
+
* const suggestions = await client.getSearchSuggestions('shirt');
|
|
611
612
|
* console.log(suggestions.products); // [{ id, name, image, basePrice, type }]
|
|
612
613
|
* console.log(suggestions.categories); // [{ id, name, productCount }]
|
|
613
614
|
*
|
|
614
615
|
* // With custom limit
|
|
615
|
-
* const suggestions = await
|
|
616
|
+
* const suggestions = await client.getSearchSuggestions('dress', 3);
|
|
616
617
|
* ```
|
|
617
618
|
*/
|
|
618
619
|
async getSearchSuggestions(query, limit) {
|
|
@@ -665,11 +666,11 @@ var BrainerceClient = class {
|
|
|
665
666
|
*
|
|
666
667
|
* @example
|
|
667
668
|
* ```typescript
|
|
668
|
-
* // Delete from
|
|
669
|
-
* const result = await
|
|
669
|
+
* // Delete from Brainerce only
|
|
670
|
+
* const result = await client.deleteProduct('prod_123');
|
|
670
671
|
*
|
|
671
|
-
* // Delete from
|
|
672
|
-
* const result = await
|
|
672
|
+
* // Delete from Brainerce and connected platforms
|
|
673
|
+
* const result = await client.deleteProduct('prod_123', {
|
|
673
674
|
* platforms: ['SHOPIFY', 'WOOCOMMERCE']
|
|
674
675
|
* });
|
|
675
676
|
* console.log(result.success); // true
|
|
@@ -691,7 +692,7 @@ var BrainerceClient = class {
|
|
|
691
692
|
*
|
|
692
693
|
* @example
|
|
693
694
|
* ```typescript
|
|
694
|
-
* const product = await
|
|
695
|
+
* const product = await client.convertToVariable('prod_123');
|
|
695
696
|
* console.log('Product type:', product.type); // 'VARIABLE'
|
|
696
697
|
* ```
|
|
697
698
|
*/
|
|
@@ -704,7 +705,7 @@ var BrainerceClient = class {
|
|
|
704
705
|
*
|
|
705
706
|
* @example
|
|
706
707
|
* ```typescript
|
|
707
|
-
* const product = await
|
|
708
|
+
* const product = await client.convertToSimple('prod_123');
|
|
708
709
|
* console.log('Product type:', product.type); // 'SIMPLE'
|
|
709
710
|
* ```
|
|
710
711
|
*/
|
|
@@ -716,7 +717,7 @@ var BrainerceClient = class {
|
|
|
716
717
|
*
|
|
717
718
|
* @example
|
|
718
719
|
* ```typescript
|
|
719
|
-
* const result = await
|
|
720
|
+
* const result = await client.publishProduct('prod_123', ['SHOPIFY', 'WOOCOMMERCE']);
|
|
720
721
|
* console.log('Publish results:', result.results);
|
|
721
722
|
* ```
|
|
722
723
|
*/
|
|
@@ -731,7 +732,7 @@ var BrainerceClient = class {
|
|
|
731
732
|
*
|
|
732
733
|
* @example
|
|
733
734
|
* ```typescript
|
|
734
|
-
* const variant = await
|
|
735
|
+
* const variant = await client.createVariant('prod_123', {
|
|
735
736
|
* sku: 'PROD-SM-RED',
|
|
736
737
|
* name: 'Small / Red',
|
|
737
738
|
* attributes: { size: 'S', color: 'Red' },
|
|
@@ -748,7 +749,7 @@ var BrainerceClient = class {
|
|
|
748
749
|
*
|
|
749
750
|
* @example
|
|
750
751
|
* ```typescript
|
|
751
|
-
* const result = await
|
|
752
|
+
* const result = await client.bulkSaveVariants('prod_123', {
|
|
752
753
|
* variants: [
|
|
753
754
|
* { sku: 'SM-RED', attributes: { size: 'S', color: 'Red' }, stock: 10, isEnabled: true },
|
|
754
755
|
* { id: 'var_456', sku: 'MD-BLUE', attributes: { size: 'M', color: 'Blue' }, stock: 5, isEnabled: true },
|
|
@@ -770,7 +771,7 @@ var BrainerceClient = class {
|
|
|
770
771
|
*
|
|
771
772
|
* @example
|
|
772
773
|
* ```typescript
|
|
773
|
-
* const variant = await
|
|
774
|
+
* const variant = await client.updateVariant('prod_123', 'var_456', {
|
|
774
775
|
* price: 34.99,
|
|
775
776
|
* salePrice: 29.99,
|
|
776
777
|
* });
|
|
@@ -788,7 +789,7 @@ var BrainerceClient = class {
|
|
|
788
789
|
*
|
|
789
790
|
* @example
|
|
790
791
|
* ```typescript
|
|
791
|
-
* await
|
|
792
|
+
* await client.deleteVariant('prod_123', 'var_456');
|
|
792
793
|
* ```
|
|
793
794
|
*/
|
|
794
795
|
async deleteVariant(productId, variantId) {
|
|
@@ -799,7 +800,7 @@ var BrainerceClient = class {
|
|
|
799
800
|
*
|
|
800
801
|
* @example
|
|
801
802
|
* ```typescript
|
|
802
|
-
* const inventory = await
|
|
803
|
+
* const inventory = await client.getVariantInventory('prod_123', 'var_456');
|
|
803
804
|
* console.log('Available:', inventory.available);
|
|
804
805
|
* ```
|
|
805
806
|
*/
|
|
@@ -814,7 +815,7 @@ var BrainerceClient = class {
|
|
|
814
815
|
*
|
|
815
816
|
* @example
|
|
816
817
|
* ```typescript
|
|
817
|
-
* const inventory = await
|
|
818
|
+
* const inventory = await client.updateVariantInventory('prod_123', 'var_456', {
|
|
818
819
|
* newTotal: 50,
|
|
819
820
|
* reason: 'Restocked from supplier',
|
|
820
821
|
* });
|
|
@@ -867,7 +868,7 @@ var BrainerceClient = class {
|
|
|
867
868
|
*
|
|
868
869
|
* @example
|
|
869
870
|
* ```typescript
|
|
870
|
-
* const order = await
|
|
871
|
+
* const order = await client.updateOrderStatus('order_123', 'shipped');
|
|
871
872
|
* ```
|
|
872
873
|
*/
|
|
873
874
|
async updateOrderStatus(orderId, status) {
|
|
@@ -879,7 +880,7 @@ var BrainerceClient = class {
|
|
|
879
880
|
*
|
|
880
881
|
* @example
|
|
881
882
|
* ```typescript
|
|
882
|
-
* const order = await
|
|
883
|
+
* const order = await client.updatePaymentMethod('order_123', 'credit_card');
|
|
883
884
|
* ```
|
|
884
885
|
*/
|
|
885
886
|
async updatePaymentMethod(orderId, paymentMethod) {
|
|
@@ -892,7 +893,7 @@ var BrainerceClient = class {
|
|
|
892
893
|
*
|
|
893
894
|
* @example
|
|
894
895
|
* ```typescript
|
|
895
|
-
* const order = await
|
|
896
|
+
* const order = await client.updateOrderNotes('order_123', 'Customer requested gift wrapping');
|
|
896
897
|
* ```
|
|
897
898
|
*/
|
|
898
899
|
async updateOrderNotes(orderId, notes) {
|
|
@@ -904,7 +905,7 @@ var BrainerceClient = class {
|
|
|
904
905
|
*
|
|
905
906
|
* @example
|
|
906
907
|
* ```typescript
|
|
907
|
-
* const refunds = await
|
|
908
|
+
* const refunds = await client.getOrderRefunds('order_123');
|
|
908
909
|
* console.log('Total refunds:', refunds.length);
|
|
909
910
|
* ```
|
|
910
911
|
*/
|
|
@@ -918,7 +919,7 @@ var BrainerceClient = class {
|
|
|
918
919
|
* @example
|
|
919
920
|
* ```typescript
|
|
920
921
|
* // Full refund
|
|
921
|
-
* const refund = await
|
|
922
|
+
* const refund = await client.createRefund('order_123', {
|
|
922
923
|
* type: 'full',
|
|
923
924
|
* restockInventory: true,
|
|
924
925
|
* notifyCustomer: true,
|
|
@@ -926,7 +927,7 @@ var BrainerceClient = class {
|
|
|
926
927
|
* });
|
|
927
928
|
*
|
|
928
929
|
* // Partial refund
|
|
929
|
-
* const partialRefund = await
|
|
930
|
+
* const partialRefund = await client.createRefund('order_123', {
|
|
930
931
|
* type: 'partial',
|
|
931
932
|
* items: [
|
|
932
933
|
* { lineItemId: 'item_456', quantity: 1 },
|
|
@@ -944,7 +945,7 @@ var BrainerceClient = class {
|
|
|
944
945
|
*
|
|
945
946
|
* @example
|
|
946
947
|
* ```typescript
|
|
947
|
-
* const order = await
|
|
948
|
+
* const order = await client.updateOrderShipping('order_123', {
|
|
948
949
|
* firstName: 'John',
|
|
949
950
|
* lastName: 'Doe',
|
|
950
951
|
* line1: '456 New Address',
|
|
@@ -964,7 +965,7 @@ var BrainerceClient = class {
|
|
|
964
965
|
*
|
|
965
966
|
* @example
|
|
966
967
|
* ```typescript
|
|
967
|
-
* const order = await
|
|
968
|
+
* const order = await client.cancelOrder('order_123');
|
|
968
969
|
* console.log('Order status:', order.status); // 'cancelled'
|
|
969
970
|
* ```
|
|
970
971
|
*/
|
|
@@ -977,7 +978,7 @@ var BrainerceClient = class {
|
|
|
977
978
|
*
|
|
978
979
|
* @example
|
|
979
980
|
* ```typescript
|
|
980
|
-
* const order = await
|
|
981
|
+
* const order = await client.fulfillOrder('order_123', {
|
|
981
982
|
* trackingNumber: '1Z999AA10123456784',
|
|
982
983
|
* trackingCompany: 'UPS',
|
|
983
984
|
* notifyCustomer: true,
|
|
@@ -992,7 +993,7 @@ var BrainerceClient = class {
|
|
|
992
993
|
*
|
|
993
994
|
* @example
|
|
994
995
|
* ```typescript
|
|
995
|
-
* const result = await
|
|
996
|
+
* const result = await client.syncDraftOrders();
|
|
996
997
|
* console.log('Draft orders synced');
|
|
997
998
|
* ```
|
|
998
999
|
*/
|
|
@@ -1004,7 +1005,7 @@ var BrainerceClient = class {
|
|
|
1004
1005
|
*
|
|
1005
1006
|
* @example
|
|
1006
1007
|
* ```typescript
|
|
1007
|
-
* const order = await
|
|
1008
|
+
* const order = await client.completeDraftOrder('draft_123', {
|
|
1008
1009
|
* paymentPending: false,
|
|
1009
1010
|
* });
|
|
1010
1011
|
* ```
|
|
@@ -1017,7 +1018,7 @@ var BrainerceClient = class {
|
|
|
1017
1018
|
*
|
|
1018
1019
|
* @example
|
|
1019
1020
|
* ```typescript
|
|
1020
|
-
* await
|
|
1021
|
+
* await client.sendDraftInvoice('draft_123', {
|
|
1021
1022
|
* to: 'customer@example.com',
|
|
1022
1023
|
* subject: 'Your Invoice',
|
|
1023
1024
|
* customMessage: 'Thank you for your order!',
|
|
@@ -1036,7 +1037,7 @@ var BrainerceClient = class {
|
|
|
1036
1037
|
*
|
|
1037
1038
|
* @example
|
|
1038
1039
|
* ```typescript
|
|
1039
|
-
* await
|
|
1040
|
+
* await client.deleteDraftOrder('draft_123');
|
|
1040
1041
|
* ```
|
|
1041
1042
|
*/
|
|
1042
1043
|
async deleteDraftOrder(orderId) {
|
|
@@ -1047,7 +1048,7 @@ var BrainerceClient = class {
|
|
|
1047
1048
|
*
|
|
1048
1049
|
* @example
|
|
1049
1050
|
* ```typescript
|
|
1050
|
-
* const order = await
|
|
1051
|
+
* const order = await client.updateDraftOrder('draft_123', {
|
|
1051
1052
|
* note: 'Updated customer note',
|
|
1052
1053
|
* email: 'newemail@example.com',
|
|
1053
1054
|
* shippingAddress: {
|
|
@@ -1084,7 +1085,7 @@ var BrainerceClient = class {
|
|
|
1084
1085
|
*
|
|
1085
1086
|
* @example
|
|
1086
1087
|
* ```typescript
|
|
1087
|
-
* const inventory = await
|
|
1088
|
+
* const inventory = await client.editInventory({
|
|
1088
1089
|
* productId: 'prod_123',
|
|
1089
1090
|
* newTotal: 100,
|
|
1090
1091
|
* reason: 'Restocked from warehouse',
|
|
@@ -1099,7 +1100,7 @@ var BrainerceClient = class {
|
|
|
1099
1100
|
*
|
|
1100
1101
|
* @example
|
|
1101
1102
|
* ```typescript
|
|
1102
|
-
* const status = await
|
|
1103
|
+
* const status = await client.getInventorySyncStatus();
|
|
1103
1104
|
* console.log(`${status.pending} products pending sync`);
|
|
1104
1105
|
* console.log(`Last sync: ${status.lastSyncAt}`);
|
|
1105
1106
|
* ```
|
|
@@ -1112,7 +1113,7 @@ var BrainerceClient = class {
|
|
|
1112
1113
|
*
|
|
1113
1114
|
* @example
|
|
1114
1115
|
* ```typescript
|
|
1115
|
-
* const inventories = await
|
|
1116
|
+
* const inventories = await client.getBulkInventory(['prod_123', 'prod_456', 'prod_789']);
|
|
1116
1117
|
* inventories.forEach(inv => {
|
|
1117
1118
|
* console.log(`${inv.productId}: ${inv.available} available`);
|
|
1118
1119
|
* });
|
|
@@ -1128,10 +1129,10 @@ var BrainerceClient = class {
|
|
|
1128
1129
|
* @example
|
|
1129
1130
|
* ```typescript
|
|
1130
1131
|
* // Reconcile single product (dry run)
|
|
1131
|
-
* const result = await
|
|
1132
|
+
* const result = await client.reconcileInventory({ productId: 'prod_123' });
|
|
1132
1133
|
*
|
|
1133
1134
|
* // Reconcile all products with auto-fix
|
|
1134
|
-
* const summary = await
|
|
1135
|
+
* const summary = await client.reconcileInventory({ autoFix: true });
|
|
1135
1136
|
* console.log(`Reconciled ${summary.reconciled} products`);
|
|
1136
1137
|
* ```
|
|
1137
1138
|
*/
|
|
@@ -1153,7 +1154,7 @@ var BrainerceClient = class {
|
|
|
1153
1154
|
* @example
|
|
1154
1155
|
* ```typescript
|
|
1155
1156
|
* // Check if items are available before adding to cart
|
|
1156
|
-
* const result = await
|
|
1157
|
+
* const result = await client.checkStockAvailability([
|
|
1157
1158
|
* { productId: 'prod_123', quantity: 2 },
|
|
1158
1159
|
* { productId: 'prod_456', variantId: 'var_789', quantity: 1 }
|
|
1159
1160
|
* ]);
|
|
@@ -1203,10 +1204,10 @@ var BrainerceClient = class {
|
|
|
1203
1204
|
* @example
|
|
1204
1205
|
* ```typescript
|
|
1205
1206
|
* // Check all cart items (full checkout)
|
|
1206
|
-
* const result = await
|
|
1207
|
+
* const result = await client.checkCartStock(cart);
|
|
1207
1208
|
*
|
|
1208
1209
|
* // Check only selected items (partial checkout - server cart only)
|
|
1209
|
-
* const result = await
|
|
1210
|
+
* const result = await client.checkCartStock(cart, ['item_1', 'item_3']);
|
|
1210
1211
|
*
|
|
1211
1212
|
* if (!result.allAvailable) {
|
|
1212
1213
|
* const unavailable = result.results.filter(r => !r.isAvailable);
|
|
@@ -1268,7 +1269,7 @@ var BrainerceClient = class {
|
|
|
1268
1269
|
*
|
|
1269
1270
|
* @example
|
|
1270
1271
|
* ```typescript
|
|
1271
|
-
* const coupon = await
|
|
1272
|
+
* const coupon = await client.createCoupon({
|
|
1272
1273
|
* code: 'SUMMER20',
|
|
1273
1274
|
* type: 'PERCENTAGE',
|
|
1274
1275
|
* value: 20,
|
|
@@ -1312,7 +1313,7 @@ var BrainerceClient = class {
|
|
|
1312
1313
|
* @example
|
|
1313
1314
|
* ```typescript
|
|
1314
1315
|
* // Only sync to WooCommerce and Shopify
|
|
1315
|
-
* await
|
|
1316
|
+
* await client.publishCoupon('coupon_123', ['WOOCOMMERCE', 'SHOPIFY']);
|
|
1316
1317
|
* ```
|
|
1317
1318
|
*/
|
|
1318
1319
|
async publishCoupon(couponId, platforms) {
|
|
@@ -1324,7 +1325,7 @@ var BrainerceClient = class {
|
|
|
1324
1325
|
*
|
|
1325
1326
|
* @example
|
|
1326
1327
|
* ```typescript
|
|
1327
|
-
* const capabilities = await
|
|
1328
|
+
* const capabilities = await client.getCouponPlatformCapabilities();
|
|
1328
1329
|
* if (!capabilities.SHOPIFY.supportsProductExclusions) {
|
|
1329
1330
|
* console.log('Shopify does not support product exclusions');
|
|
1330
1331
|
* }
|
|
@@ -1342,7 +1343,7 @@ var BrainerceClient = class {
|
|
|
1342
1343
|
*
|
|
1343
1344
|
* @example
|
|
1344
1345
|
* ```typescript
|
|
1345
|
-
* const customer = await
|
|
1346
|
+
* const customer = await client.createCustomer({
|
|
1346
1347
|
* email: 'customer@example.com',
|
|
1347
1348
|
* firstName: 'John',
|
|
1348
1349
|
* lastName: 'Doe',
|
|
@@ -1377,7 +1378,7 @@ var BrainerceClient = class {
|
|
|
1377
1378
|
*
|
|
1378
1379
|
* @example
|
|
1379
1380
|
* ```typescript
|
|
1380
|
-
* const auth = await
|
|
1381
|
+
* const auth = await client.loginCustomer('customer@example.com', 'password123');
|
|
1381
1382
|
* console.log('Customer logged in:', auth.customer.email);
|
|
1382
1383
|
* // Store auth.token for subsequent authenticated requests
|
|
1383
1384
|
* ```
|
|
@@ -1406,7 +1407,7 @@ var BrainerceClient = class {
|
|
|
1406
1407
|
*
|
|
1407
1408
|
* @example
|
|
1408
1409
|
* ```typescript
|
|
1409
|
-
* const auth = await
|
|
1410
|
+
* const auth = await client.registerCustomer({
|
|
1410
1411
|
* email: 'newcustomer@example.com',
|
|
1411
1412
|
* password: 'securepassword123',
|
|
1412
1413
|
* firstName: 'Jane',
|
|
@@ -1452,14 +1453,14 @@ var BrainerceClient = class {
|
|
|
1452
1453
|
* @example
|
|
1453
1454
|
* ```typescript
|
|
1454
1455
|
* // Option 1: Pass token directly (recommended for verification flow)
|
|
1455
|
-
* const auth = await
|
|
1456
|
+
* const auth = await client.registerCustomer({...});
|
|
1456
1457
|
* if (auth.requiresVerification) {
|
|
1457
|
-
* const result = await
|
|
1458
|
+
* const result = await client.verifyEmail('123456', auth.token);
|
|
1458
1459
|
* }
|
|
1459
1460
|
*
|
|
1460
1461
|
* // Option 2: Use setCustomerToken first
|
|
1461
|
-
*
|
|
1462
|
-
* const result = await
|
|
1462
|
+
* client.setCustomerToken(auth.token);
|
|
1463
|
+
* const result = await client.verifyEmail('123456');
|
|
1463
1464
|
* ```
|
|
1464
1465
|
*/
|
|
1465
1466
|
async verifyEmail(code, token) {
|
|
@@ -1501,11 +1502,11 @@ var BrainerceClient = class {
|
|
|
1501
1502
|
* @example
|
|
1502
1503
|
* ```typescript
|
|
1503
1504
|
* // Option 1: Pass token directly
|
|
1504
|
-
* await
|
|
1505
|
+
* await client.resendVerificationEmail(auth.token);
|
|
1505
1506
|
*
|
|
1506
1507
|
* // Option 2: Use setCustomerToken first
|
|
1507
|
-
*
|
|
1508
|
-
* await
|
|
1508
|
+
* client.setCustomerToken(auth.token);
|
|
1509
|
+
* await client.resendVerificationEmail();
|
|
1509
1510
|
* ```
|
|
1510
1511
|
*/
|
|
1511
1512
|
async resendVerificationEmail(token) {
|
|
@@ -1546,7 +1547,7 @@ var BrainerceClient = class {
|
|
|
1546
1547
|
*
|
|
1547
1548
|
* @example
|
|
1548
1549
|
* ```typescript
|
|
1549
|
-
* const { providers } = await
|
|
1550
|
+
* const { providers } = await client.getAvailableOAuthProviders();
|
|
1550
1551
|
* // providers: ['GOOGLE', 'FACEBOOK'] - array of strings, not objects!
|
|
1551
1552
|
*
|
|
1552
1553
|
* // To display with friendly names:
|
|
@@ -1586,7 +1587,7 @@ var BrainerceClient = class {
|
|
|
1586
1587
|
* @example
|
|
1587
1588
|
* ```typescript
|
|
1588
1589
|
* // Get authorization URL (redirectUrl MUST be absolute with origin)
|
|
1589
|
-
* const { authorizationUrl } = await
|
|
1590
|
+
* const { authorizationUrl } = await client.getOAuthAuthorizeUrl('GOOGLE', {
|
|
1590
1591
|
* redirectUrl: window.location.origin + '/auth/callback'
|
|
1591
1592
|
* });
|
|
1592
1593
|
*
|
|
@@ -1597,7 +1598,7 @@ var BrainerceClient = class {
|
|
|
1597
1598
|
* const params = new URLSearchParams(window.location.search);
|
|
1598
1599
|
* if (params.get('oauth_success') === 'true') {
|
|
1599
1600
|
* const token = params.get('token');
|
|
1600
|
-
*
|
|
1601
|
+
* client.setCustomerToken(token);
|
|
1601
1602
|
* // Also available: customer_id, customer_email, is_new
|
|
1602
1603
|
* } else if (params.get('oauth_error')) {
|
|
1603
1604
|
* // Show error
|
|
@@ -1666,10 +1667,10 @@ var BrainerceClient = class {
|
|
|
1666
1667
|
* @example
|
|
1667
1668
|
* ```typescript
|
|
1668
1669
|
* // Customer must be logged in first
|
|
1669
|
-
*
|
|
1670
|
+
* client.setCustomerToken(auth.token);
|
|
1670
1671
|
*
|
|
1671
1672
|
* // Get authorization URL for linking
|
|
1672
|
-
* const { authorizationUrl } = await
|
|
1673
|
+
* const { authorizationUrl } = await client.linkOAuthProvider('GITHUB', {
|
|
1673
1674
|
* redirectUrl: '/settings'
|
|
1674
1675
|
* });
|
|
1675
1676
|
*
|
|
@@ -1706,8 +1707,8 @@ var BrainerceClient = class {
|
|
|
1706
1707
|
*
|
|
1707
1708
|
* @example
|
|
1708
1709
|
* ```typescript
|
|
1709
|
-
*
|
|
1710
|
-
* await
|
|
1710
|
+
* client.setCustomerToken(auth.token);
|
|
1711
|
+
* await client.unlinkOAuthProvider('FACEBOOK');
|
|
1711
1712
|
* ```
|
|
1712
1713
|
*/
|
|
1713
1714
|
async unlinkOAuthProvider(provider) {
|
|
@@ -1731,8 +1732,8 @@ var BrainerceClient = class {
|
|
|
1731
1732
|
*
|
|
1732
1733
|
* @example
|
|
1733
1734
|
* ```typescript
|
|
1734
|
-
*
|
|
1735
|
-
* const { connections } = await
|
|
1735
|
+
* client.setCustomerToken(auth.token);
|
|
1736
|
+
* const { connections } = await client.getOAuthConnections();
|
|
1736
1737
|
* // connections: [{ id: '...', provider: 'GOOGLE', email: 'user@gmail.com', createdAt: '...' }]
|
|
1737
1738
|
* ```
|
|
1738
1739
|
*/
|
|
@@ -1762,10 +1763,10 @@ var BrainerceClient = class {
|
|
|
1762
1763
|
* @example
|
|
1763
1764
|
* ```typescript
|
|
1764
1765
|
* // After login/register, set the token
|
|
1765
|
-
*
|
|
1766
|
+
* client.setCustomerToken(auth.token);
|
|
1766
1767
|
*
|
|
1767
1768
|
* // Then get the profile
|
|
1768
|
-
* const profile = await
|
|
1769
|
+
* const profile = await client.getCustomerProfile();
|
|
1769
1770
|
* console.log('Customer:', profile.email);
|
|
1770
1771
|
* ```
|
|
1771
1772
|
*/
|
|
@@ -1795,7 +1796,7 @@ var BrainerceClient = class {
|
|
|
1795
1796
|
*
|
|
1796
1797
|
* @example
|
|
1797
1798
|
* ```typescript
|
|
1798
|
-
* const address = await
|
|
1799
|
+
* const address = await client.addCustomerAddress('cust_123', {
|
|
1799
1800
|
* firstName: 'John',
|
|
1800
1801
|
* lastName: 'Doe',
|
|
1801
1802
|
* line1: '123 Main St',
|
|
@@ -1835,7 +1836,7 @@ var BrainerceClient = class {
|
|
|
1835
1836
|
*
|
|
1836
1837
|
* @example
|
|
1837
1838
|
* ```typescript
|
|
1838
|
-
* const orders = await
|
|
1839
|
+
* const orders = await client.getCustomerOrders('cust_123', { page: 1, limit: 10 });
|
|
1839
1840
|
* console.log(`Customer has ${orders.meta.total} total orders`);
|
|
1840
1841
|
* ```
|
|
1841
1842
|
*/
|
|
@@ -1854,16 +1855,12 @@ var BrainerceClient = class {
|
|
|
1854
1855
|
*
|
|
1855
1856
|
* @example
|
|
1856
1857
|
* ```typescript
|
|
1857
|
-
* const cart = await
|
|
1858
|
+
* const cart = await client.createCart();
|
|
1858
1859
|
* console.log('Cart session:', cart.sessionToken);
|
|
1859
1860
|
* // Store sessionToken in localStorage or cookie
|
|
1860
1861
|
* ```
|
|
1861
1862
|
*/
|
|
1862
1863
|
async createCart() {
|
|
1863
|
-
if (this.isVibeCodedMode() && !this.isCustomerLoggedIn()) {
|
|
1864
|
-
const localCart = this.getLocalCart();
|
|
1865
|
-
return this.localCartToCart(localCart);
|
|
1866
|
-
}
|
|
1867
1864
|
if (this.isVibeCodedMode()) {
|
|
1868
1865
|
return this.vibeCodedRequest("POST", "/cart");
|
|
1869
1866
|
}
|
|
@@ -1877,11 +1874,14 @@ var BrainerceClient = class {
|
|
|
1877
1874
|
*
|
|
1878
1875
|
* @example
|
|
1879
1876
|
* ```typescript
|
|
1880
|
-
* const cart = await
|
|
1877
|
+
* const cart = await client.getCartBySession('sess_abc123');
|
|
1881
1878
|
* console.log('Items in cart:', cart.itemCount);
|
|
1882
1879
|
* ```
|
|
1883
1880
|
*/
|
|
1884
1881
|
async getCartBySession(sessionToken) {
|
|
1882
|
+
if (this.isVibeCodedMode()) {
|
|
1883
|
+
return this.vibeCodedRequest("GET", `/cart/session/${sessionToken}`);
|
|
1884
|
+
}
|
|
1885
1885
|
if (this.storeId && !this.apiKey) {
|
|
1886
1886
|
return this.storefrontRequest("GET", `/cart/session/${sessionToken}`);
|
|
1887
1887
|
}
|
|
@@ -1892,7 +1892,7 @@ var BrainerceClient = class {
|
|
|
1892
1892
|
*
|
|
1893
1893
|
* @example
|
|
1894
1894
|
* ```typescript
|
|
1895
|
-
* const cart = await
|
|
1895
|
+
* const cart = await client.getCartByCustomer('cust_123');
|
|
1896
1896
|
* console.log('Customer cart total:', cart.subtotal);
|
|
1897
1897
|
* ```
|
|
1898
1898
|
*/
|
|
@@ -1907,6 +1907,7 @@ var BrainerceClient = class {
|
|
|
1907
1907
|
*/
|
|
1908
1908
|
async getCart(cartId) {
|
|
1909
1909
|
if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
|
|
1910
|
+
console.warn('getCart("__local__") is deprecated. Use smartGetCart() instead.');
|
|
1910
1911
|
return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
|
|
1911
1912
|
}
|
|
1912
1913
|
if (this.isVibeCodedMode()) {
|
|
@@ -1922,7 +1923,7 @@ var BrainerceClient = class {
|
|
|
1922
1923
|
*
|
|
1923
1924
|
* @example
|
|
1924
1925
|
* ```typescript
|
|
1925
|
-
* const cart = await
|
|
1926
|
+
* const cart = await client.addToCart('cart_123', {
|
|
1926
1927
|
* productId: 'prod_abc',
|
|
1927
1928
|
* quantity: 2,
|
|
1928
1929
|
* notes: 'Gift wrap please',
|
|
@@ -1931,38 +1932,14 @@ var BrainerceClient = class {
|
|
|
1931
1932
|
*/
|
|
1932
1933
|
async addToCart(cartId, item) {
|
|
1933
1934
|
if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
|
|
1934
|
-
|
|
1935
|
-
let productPrice = "0";
|
|
1936
|
-
let productImage;
|
|
1937
|
-
if (item.productInfo) {
|
|
1938
|
-
productName = item.productInfo.name;
|
|
1939
|
-
productPrice = item.productInfo.price;
|
|
1940
|
-
productImage = item.productInfo.image;
|
|
1941
|
-
} else {
|
|
1942
|
-
try {
|
|
1943
|
-
const product = await this.getProduct(item.productId);
|
|
1944
|
-
productName = product.name;
|
|
1945
|
-
productPrice = product.salePrice || product.basePrice;
|
|
1946
|
-
productImage = product.images?.[0]?.url;
|
|
1947
|
-
if (item.variantId && product.variants) {
|
|
1948
|
-
const variant = product.variants.find((v) => v.id === item.variantId);
|
|
1949
|
-
if (variant) {
|
|
1950
|
-
productPrice = variant.salePrice || variant.price || productPrice;
|
|
1951
|
-
if (variant.image) {
|
|
1952
|
-
productImage = typeof variant.image === "string" ? variant.image : variant.image.url;
|
|
1953
|
-
}
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
|
-
} catch {
|
|
1957
|
-
}
|
|
1958
|
-
}
|
|
1935
|
+
console.warn('addToCart("__local__", ...) is deprecated. Use smartAddToCart() instead.');
|
|
1959
1936
|
this.addToLocalCart({
|
|
1960
1937
|
productId: item.productId,
|
|
1961
1938
|
variantId: item.variantId,
|
|
1962
1939
|
quantity: item.quantity,
|
|
1963
|
-
name:
|
|
1964
|
-
price:
|
|
1965
|
-
image:
|
|
1940
|
+
name: item.productInfo?.name || "Unknown Product",
|
|
1941
|
+
price: item.productInfo?.price || "0",
|
|
1942
|
+
image: item.productInfo?.image
|
|
1966
1943
|
});
|
|
1967
1944
|
return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
|
|
1968
1945
|
}
|
|
@@ -1988,11 +1965,12 @@ var BrainerceClient = class {
|
|
|
1988
1965
|
*
|
|
1989
1966
|
* @example
|
|
1990
1967
|
* ```typescript
|
|
1991
|
-
* const cart = await
|
|
1968
|
+
* const cart = await client.updateCartItem('cart_123', 'item_456', { quantity: 3 });
|
|
1992
1969
|
* ```
|
|
1993
1970
|
*/
|
|
1994
1971
|
async updateCartItem(cartId, itemId, data) {
|
|
1995
1972
|
if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
|
|
1973
|
+
console.warn('updateCartItem("__local__", ...) is deprecated. Use smartUpdateCartItem() instead.');
|
|
1996
1974
|
const index = parseInt(itemId.replace("local_", ""), 10);
|
|
1997
1975
|
const localCart = this.getLocalCart();
|
|
1998
1976
|
if (index >= 0 && index < localCart.items.length) {
|
|
@@ -2023,11 +2001,12 @@ var BrainerceClient = class {
|
|
|
2023
2001
|
*
|
|
2024
2002
|
* @example
|
|
2025
2003
|
* ```typescript
|
|
2026
|
-
* const cart = await
|
|
2004
|
+
* const cart = await client.removeCartItem('cart_123', 'item_456');
|
|
2027
2005
|
* ```
|
|
2028
2006
|
*/
|
|
2029
2007
|
async removeCartItem(cartId, itemId) {
|
|
2030
2008
|
if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
|
|
2009
|
+
console.warn('removeCartItem("__local__", ...) is deprecated. Use smartRemoveFromCart() instead.');
|
|
2031
2010
|
const index = parseInt(itemId.replace("local_", ""), 10);
|
|
2032
2011
|
const localCart = this.getLocalCart();
|
|
2033
2012
|
if (index >= 0 && index < localCart.items.length) {
|
|
@@ -2058,11 +2037,12 @@ var BrainerceClient = class {
|
|
|
2058
2037
|
*
|
|
2059
2038
|
* @example
|
|
2060
2039
|
* ```typescript
|
|
2061
|
-
* await
|
|
2040
|
+
* await client.clearCart('cart_123');
|
|
2062
2041
|
* ```
|
|
2063
2042
|
*/
|
|
2064
2043
|
async clearCart(cartId) {
|
|
2065
2044
|
if (cartId === this.VIRTUAL_LOCAL_CART_ID) {
|
|
2045
|
+
console.warn('clearCart("__local__") is deprecated. Use onCheckoutComplete() or clearLocalCart() directly.');
|
|
2066
2046
|
this.clearLocalCart();
|
|
2067
2047
|
return this.withGuards(this.localCartToCart(this.getLocalCart()), "cart");
|
|
2068
2048
|
}
|
|
@@ -2081,7 +2061,7 @@ var BrainerceClient = class {
|
|
|
2081
2061
|
*
|
|
2082
2062
|
* @example
|
|
2083
2063
|
* ```typescript
|
|
2084
|
-
* const cart = await
|
|
2064
|
+
* const cart = await client.applyCoupon('cart_123', 'SAVE20');
|
|
2085
2065
|
* console.log('Discount:', cart.discountAmount);
|
|
2086
2066
|
* ```
|
|
2087
2067
|
*/
|
|
@@ -2108,7 +2088,7 @@ var BrainerceClient = class {
|
|
|
2108
2088
|
*
|
|
2109
2089
|
* @example
|
|
2110
2090
|
* ```typescript
|
|
2111
|
-
* const cart = await
|
|
2091
|
+
* const cart = await client.removeCoupon('cart_123');
|
|
2112
2092
|
* ```
|
|
2113
2093
|
*/
|
|
2114
2094
|
async removeCoupon(cartId) {
|
|
@@ -2141,8 +2121,8 @@ var BrainerceClient = class {
|
|
|
2141
2121
|
* @example
|
|
2142
2122
|
* ```typescript
|
|
2143
2123
|
* // After customer logs in
|
|
2144
|
-
*
|
|
2145
|
-
* const cart = await
|
|
2124
|
+
* client.setCustomerToken(authResponse.token);
|
|
2125
|
+
* const cart = await client.linkCart('cart_123'); // cartId is REQUIRED
|
|
2146
2126
|
* // Cart is now linked to the customer
|
|
2147
2127
|
* ```
|
|
2148
2128
|
*/
|
|
@@ -2168,7 +2148,7 @@ var BrainerceClient = class {
|
|
|
2168
2148
|
* @example
|
|
2169
2149
|
* ```typescript
|
|
2170
2150
|
* // After customer logs in, merge their guest cart
|
|
2171
|
-
* const mergedCart = await
|
|
2151
|
+
* const mergedCart = await client.mergeCarts({
|
|
2172
2152
|
* sourceSessionToken: 'sess_guest_abc',
|
|
2173
2153
|
* targetCustomerId: 'cust_123',
|
|
2174
2154
|
* });
|
|
@@ -2187,7 +2167,7 @@ var BrainerceClient = class {
|
|
|
2187
2167
|
*
|
|
2188
2168
|
* @example
|
|
2189
2169
|
* ```typescript
|
|
2190
|
-
* const banners = await
|
|
2170
|
+
* const banners = await client.getDiscountBanners();
|
|
2191
2171
|
* banners.forEach(b => console.log(b.text));
|
|
2192
2172
|
* ```
|
|
2193
2173
|
*/
|
|
@@ -2209,7 +2189,7 @@ var BrainerceClient = class {
|
|
|
2209
2189
|
*
|
|
2210
2190
|
* @example
|
|
2211
2191
|
* ```typescript
|
|
2212
|
-
* const badge = await
|
|
2192
|
+
* const badge = await client.getProductDiscountBadge('prod_123');
|
|
2213
2193
|
* if (badge) {
|
|
2214
2194
|
* console.log(badge.badgeText); // e.g., "20% OFF"
|
|
2215
2195
|
* console.log(badge.discountedPrice); // e.g., "39.99"
|
|
@@ -2242,7 +2222,7 @@ var BrainerceClient = class {
|
|
|
2242
2222
|
*
|
|
2243
2223
|
* @example
|
|
2244
2224
|
* ```typescript
|
|
2245
|
-
* const nudges = await
|
|
2225
|
+
* const nudges = await client.getCartNudges('cart_123');
|
|
2246
2226
|
* nudges.forEach(n => {
|
|
2247
2227
|
* console.log(n.text); // e.g., "Add $12.50 more for free shipping!"
|
|
2248
2228
|
* });
|
|
@@ -2267,7 +2247,7 @@ var BrainerceClient = class {
|
|
|
2267
2247
|
*
|
|
2268
2248
|
* @example
|
|
2269
2249
|
* ```typescript
|
|
2270
|
-
* const recs = await
|
|
2250
|
+
* const recs = await client.getProductRecommendations('prod_123');
|
|
2271
2251
|
* console.log(recs.crossSells); // complementary products
|
|
2272
2252
|
* console.log(recs.upsells); // premium alternatives
|
|
2273
2253
|
* console.log(recs.related); // related products
|
|
@@ -2301,7 +2281,7 @@ var BrainerceClient = class {
|
|
|
2301
2281
|
*
|
|
2302
2282
|
* @example
|
|
2303
2283
|
* ```typescript
|
|
2304
|
-
* const recs = await
|
|
2284
|
+
* const recs = await client.getCartRecommendations('cart_123', 6);
|
|
2305
2285
|
* recs.recommendations.forEach(product => {
|
|
2306
2286
|
* console.log(product.name, product.basePrice);
|
|
2307
2287
|
* });
|
|
@@ -2333,7 +2313,7 @@ var BrainerceClient = class {
|
|
|
2333
2313
|
*
|
|
2334
2314
|
* @example
|
|
2335
2315
|
* ```typescript
|
|
2336
|
-
* if (
|
|
2316
|
+
* if (client.isCustomerLoggedIn()) {
|
|
2337
2317
|
* console.log('Cart will be stored on server');
|
|
2338
2318
|
* } else {
|
|
2339
2319
|
* console.log('Cart will be stored in localStorage');
|
|
@@ -2343,6 +2323,230 @@ var BrainerceClient = class {
|
|
|
2343
2323
|
isCustomerLoggedIn() {
|
|
2344
2324
|
return !!this.customerToken;
|
|
2345
2325
|
}
|
|
2326
|
+
// -------------------- Session Cart Helpers --------------------
|
|
2327
|
+
/**
|
|
2328
|
+
* Hydrate session cart state from localStorage on construction.
|
|
2329
|
+
* @internal
|
|
2330
|
+
*/
|
|
2331
|
+
hydrateSessionCart() {
|
|
2332
|
+
if (!this.isLocalStorageAvailable()) return;
|
|
2333
|
+
try {
|
|
2334
|
+
const stored = window.localStorage.getItem(this.SESSION_CART_KEY);
|
|
2335
|
+
if (stored) {
|
|
2336
|
+
const ref = JSON.parse(stored);
|
|
2337
|
+
this.sessionToken = ref.sessionToken;
|
|
2338
|
+
this.sessionCartId = ref.cartId;
|
|
2339
|
+
}
|
|
2340
|
+
} catch {
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
/**
|
|
2344
|
+
* Persist session cart reference to localStorage.
|
|
2345
|
+
* @internal
|
|
2346
|
+
*/
|
|
2347
|
+
saveSessionCart(ref) {
|
|
2348
|
+
this.sessionToken = ref.sessionToken;
|
|
2349
|
+
this.sessionCartId = ref.cartId;
|
|
2350
|
+
if (!this.isLocalStorageAvailable()) return;
|
|
2351
|
+
window.localStorage.setItem(this.SESSION_CART_KEY, JSON.stringify(ref));
|
|
2352
|
+
}
|
|
2353
|
+
/**
|
|
2354
|
+
* Clear session cart reference from localStorage and memory.
|
|
2355
|
+
* @internal
|
|
2356
|
+
*/
|
|
2357
|
+
clearSessionCart() {
|
|
2358
|
+
this.sessionToken = null;
|
|
2359
|
+
this.sessionCartId = null;
|
|
2360
|
+
this._sessionCartPromise = null;
|
|
2361
|
+
if (!this.isLocalStorageAvailable()) return;
|
|
2362
|
+
window.localStorage.removeItem(this.SESSION_CART_KEY);
|
|
2363
|
+
}
|
|
2364
|
+
/**
|
|
2365
|
+
* Update the cached item count in the session reference.
|
|
2366
|
+
* @internal
|
|
2367
|
+
*/
|
|
2368
|
+
updateSessionCartItemCount(count) {
|
|
2369
|
+
if (!this.sessionToken || !this.sessionCartId) return;
|
|
2370
|
+
this.saveSessionCart({
|
|
2371
|
+
sessionToken: this.sessionToken,
|
|
2372
|
+
cartId: this.sessionCartId,
|
|
2373
|
+
itemCount: count
|
|
2374
|
+
});
|
|
2375
|
+
}
|
|
2376
|
+
/**
|
|
2377
|
+
* Return a synthetic empty Cart object for display when no server cart exists yet.
|
|
2378
|
+
* Avoids creating a server cart just to show "your cart is empty."
|
|
2379
|
+
* @internal
|
|
2380
|
+
*/
|
|
2381
|
+
emptyCart() {
|
|
2382
|
+
return {
|
|
2383
|
+
id: "",
|
|
2384
|
+
sessionToken: null,
|
|
2385
|
+
customerId: null,
|
|
2386
|
+
status: "ACTIVE",
|
|
2387
|
+
currency: "USD",
|
|
2388
|
+
notes: null,
|
|
2389
|
+
subtotal: "0",
|
|
2390
|
+
discountAmount: "0",
|
|
2391
|
+
couponCode: null,
|
|
2392
|
+
items: [],
|
|
2393
|
+
itemCount: 0,
|
|
2394
|
+
expiresAt: null,
|
|
2395
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2396
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
/**
|
|
2400
|
+
* Create a server-side cart via API. Never falls back to localStorage.
|
|
2401
|
+
* @internal
|
|
2402
|
+
*/
|
|
2403
|
+
async createServerCart() {
|
|
2404
|
+
if (this.isVibeCodedMode()) {
|
|
2405
|
+
return this.vibeCodedRequest("POST", "/cart");
|
|
2406
|
+
}
|
|
2407
|
+
if (this.storeId && !this.apiKey) {
|
|
2408
|
+
return this.storefrontRequest("POST", "/cart");
|
|
2409
|
+
}
|
|
2410
|
+
return this.adminRequest("POST", "/api/v1/cart");
|
|
2411
|
+
}
|
|
2412
|
+
/**
|
|
2413
|
+
* Get or create a server-side session cart for guest users.
|
|
2414
|
+
* Lazily creates the cart on first call (e.g., first add-to-cart).
|
|
2415
|
+
* Uses promise dedup lock to prevent race conditions on parallel calls.
|
|
2416
|
+
* @internal
|
|
2417
|
+
*/
|
|
2418
|
+
async getOrCreateSessionCart() {
|
|
2419
|
+
if (this._sessionCartPromise) return this._sessionCartPromise;
|
|
2420
|
+
this._sessionCartPromise = this._getOrCreateSessionCartImpl();
|
|
2421
|
+
try {
|
|
2422
|
+
return await this._sessionCartPromise;
|
|
2423
|
+
} finally {
|
|
2424
|
+
this._sessionCartPromise = null;
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
/** @internal */
|
|
2428
|
+
async _getOrCreateSessionCartImpl() {
|
|
2429
|
+
const migrated = await this.migrateLocalCartToSession();
|
|
2430
|
+
if (migrated) return migrated;
|
|
2431
|
+
if (this.sessionCartId && this.sessionToken) {
|
|
2432
|
+
try {
|
|
2433
|
+
const cart2 = await this.getCart(this.sessionCartId);
|
|
2434
|
+
if (cart2.status === "ACTIVE") {
|
|
2435
|
+
return cart2;
|
|
2436
|
+
}
|
|
2437
|
+
this.clearSessionCart();
|
|
2438
|
+
} catch {
|
|
2439
|
+
this.clearSessionCart();
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
if (this.sessionToken) {
|
|
2443
|
+
try {
|
|
2444
|
+
const cart2 = await this.getCartBySession(this.sessionToken);
|
|
2445
|
+
if (cart2 && cart2.status === "ACTIVE") {
|
|
2446
|
+
this.saveSessionCart({
|
|
2447
|
+
sessionToken: this.sessionToken,
|
|
2448
|
+
cartId: cart2.id,
|
|
2449
|
+
itemCount: cart2.itemCount
|
|
2450
|
+
});
|
|
2451
|
+
return cart2;
|
|
2452
|
+
}
|
|
2453
|
+
} catch {
|
|
2454
|
+
this.clearSessionCart();
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
const cart = await this.createServerCart();
|
|
2458
|
+
if (cart.sessionToken) {
|
|
2459
|
+
this.saveSessionCart({
|
|
2460
|
+
sessionToken: cart.sessionToken,
|
|
2461
|
+
cartId: cart.id,
|
|
2462
|
+
itemCount: cart.itemCount
|
|
2463
|
+
});
|
|
2464
|
+
}
|
|
2465
|
+
return cart;
|
|
2466
|
+
}
|
|
2467
|
+
/**
|
|
2468
|
+
* Migrate legacy localStorage cart to server session cart.
|
|
2469
|
+
* Called once, on first smart method call if migration is needed.
|
|
2470
|
+
* @internal
|
|
2471
|
+
*/
|
|
2472
|
+
async migrateLocalCartToSession() {
|
|
2473
|
+
if (this._migrationDone) return null;
|
|
2474
|
+
this._migrationDone = true;
|
|
2475
|
+
if (this.sessionToken || this.sessionCartId) return null;
|
|
2476
|
+
const localCart = this.getLocalCart();
|
|
2477
|
+
if (localCart.items.length === 0) return null;
|
|
2478
|
+
try {
|
|
2479
|
+
const cart = await this.createServerCart();
|
|
2480
|
+
for (const item of localCart.items) {
|
|
2481
|
+
try {
|
|
2482
|
+
await this.addToCart(cart.id, {
|
|
2483
|
+
productId: item.productId,
|
|
2484
|
+
variantId: item.variantId,
|
|
2485
|
+
quantity: item.quantity
|
|
2486
|
+
});
|
|
2487
|
+
} catch {
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
if (cart.sessionToken) {
|
|
2491
|
+
this.saveSessionCart({
|
|
2492
|
+
sessionToken: cart.sessionToken,
|
|
2493
|
+
cartId: cart.id
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
this.clearLocalCart();
|
|
2497
|
+
return this.getCart(cart.id);
|
|
2498
|
+
} catch {
|
|
2499
|
+
this._migrationDone = false;
|
|
2500
|
+
return null;
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
/**
|
|
2504
|
+
* Merge the guest session cart into the customer's cart on the server.
|
|
2505
|
+
* Tries linkCart first (fast, single call), falls back to mergeCarts endpoint.
|
|
2506
|
+
* @internal
|
|
2507
|
+
*/
|
|
2508
|
+
async mergeSessionCartOnLogin() {
|
|
2509
|
+
if (this.sessionCartId) {
|
|
2510
|
+
try {
|
|
2511
|
+
return await this.linkCart(this.sessionCartId);
|
|
2512
|
+
} catch {
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
if (this.isVibeCodedMode()) {
|
|
2516
|
+
return this.vibeCodedRequest("POST", "/cart/merge", {
|
|
2517
|
+
sessionToken: this.sessionToken
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
if (this.storeId && !this.apiKey) {
|
|
2521
|
+
return this.storefrontRequest("POST", "/cart/merge", {
|
|
2522
|
+
sessionToken: this.sessionToken
|
|
2523
|
+
});
|
|
2524
|
+
}
|
|
2525
|
+
return this.adminRequest("POST", "/api/v1/cart/merge", {
|
|
2526
|
+
sessionToken: this.sessionToken
|
|
2527
|
+
});
|
|
2528
|
+
}
|
|
2529
|
+
/**
|
|
2530
|
+
* Get the cart item count without a full cart fetch.
|
|
2531
|
+
* Returns the cached count from localStorage if available, or 0.
|
|
2532
|
+
* For accurate counts, use smartGetCart() and read cart.itemCount.
|
|
2533
|
+
*/
|
|
2534
|
+
getSmartCartItemCount() {
|
|
2535
|
+
if (this.isCustomerLoggedIn()) {
|
|
2536
|
+
return 0;
|
|
2537
|
+
}
|
|
2538
|
+
if (!this.isLocalStorageAvailable()) return 0;
|
|
2539
|
+
try {
|
|
2540
|
+
const stored = window.localStorage.getItem(this.SESSION_CART_KEY);
|
|
2541
|
+
if (stored) {
|
|
2542
|
+
const ref = JSON.parse(stored);
|
|
2543
|
+
return ref.itemCount ?? 0;
|
|
2544
|
+
}
|
|
2545
|
+
} catch {
|
|
2546
|
+
}
|
|
2547
|
+
return 0;
|
|
2548
|
+
}
|
|
2549
|
+
// -------------------- Customer Cart --------------------
|
|
2346
2550
|
/**
|
|
2347
2551
|
* Get or create a server cart for the logged-in customer
|
|
2348
2552
|
* Caches the cart ID for subsequent calls
|
|
@@ -2395,40 +2599,50 @@ var BrainerceClient = class {
|
|
|
2395
2599
|
throw new BrainerceError("fetchCustomerCart requires vibe-coded or storefront mode", 400);
|
|
2396
2600
|
}
|
|
2397
2601
|
/**
|
|
2398
|
-
* Smart add to cart - automatically uses
|
|
2602
|
+
* Smart add to cart - automatically uses the correct cart based on auth state
|
|
2399
2603
|
*
|
|
2400
|
-
* - **
|
|
2401
|
-
* - **
|
|
2604
|
+
* - **Logged in**: Uses customer's server cart
|
|
2605
|
+
* - **Guest**: Uses server-side session cart (creates one if needed)
|
|
2402
2606
|
*
|
|
2403
2607
|
* @example
|
|
2404
2608
|
* ```typescript
|
|
2405
2609
|
* // Works the same whether logged in or not
|
|
2406
|
-
* await
|
|
2610
|
+
* await client.smartAddToCart({
|
|
2407
2611
|
* productId: 'prod_123',
|
|
2408
2612
|
* quantity: 2,
|
|
2409
|
-
* name: 'Cool Product', // Optional: for localStorage display
|
|
2410
|
-
* price: '29.99',
|
|
2411
2613
|
* });
|
|
2412
2614
|
* ```
|
|
2413
2615
|
*/
|
|
2414
2616
|
async smartAddToCart(item) {
|
|
2415
2617
|
if (this.isCustomerLoggedIn()) {
|
|
2416
2618
|
const cart = await this.getOrCreateCustomerCart();
|
|
2417
|
-
|
|
2619
|
+
const updated = await this.addToCart(cart.id, {
|
|
2418
2620
|
productId: item.productId,
|
|
2419
2621
|
variantId: item.variantId,
|
|
2420
2622
|
quantity: item.quantity
|
|
2421
2623
|
});
|
|
2624
|
+
return updated;
|
|
2422
2625
|
} else {
|
|
2423
|
-
|
|
2626
|
+
const cart = await this.getOrCreateSessionCart();
|
|
2627
|
+
const updated = await this.addToCart(cart.id, {
|
|
2628
|
+
productId: item.productId,
|
|
2629
|
+
variantId: item.variantId,
|
|
2630
|
+
quantity: item.quantity
|
|
2631
|
+
});
|
|
2632
|
+
this.updateSessionCartItemCount(updated.items?.length ?? 0);
|
|
2633
|
+
return updated;
|
|
2424
2634
|
}
|
|
2425
2635
|
}
|
|
2426
2636
|
/**
|
|
2427
|
-
* Smart get cart - returns
|
|
2637
|
+
* Smart get cart - returns the current cart (server-side for both guests and logged-in users)
|
|
2638
|
+
*
|
|
2639
|
+
* - **Logged in**: Returns customer's server cart
|
|
2640
|
+
* - **Guest with session**: Returns server-side session cart
|
|
2641
|
+
* - **Guest without session**: Returns empty cart (no server call, cart created lazily on add)
|
|
2428
2642
|
*
|
|
2429
2643
|
* @example
|
|
2430
2644
|
* ```typescript
|
|
2431
|
-
* const cart = await
|
|
2645
|
+
* const cart = await client.smartGetCart();
|
|
2432
2646
|
* console.log('Items:', cart.items.length);
|
|
2433
2647
|
* ```
|
|
2434
2648
|
*/
|
|
@@ -2436,7 +2650,10 @@ var BrainerceClient = class {
|
|
|
2436
2650
|
if (this.isCustomerLoggedIn()) {
|
|
2437
2651
|
return this.getOrCreateCustomerCart();
|
|
2438
2652
|
} else {
|
|
2439
|
-
|
|
2653
|
+
if (!this.sessionToken) {
|
|
2654
|
+
return this.emptyCart();
|
|
2655
|
+
}
|
|
2656
|
+
return this.getOrCreateSessionCart();
|
|
2440
2657
|
}
|
|
2441
2658
|
}
|
|
2442
2659
|
/**
|
|
@@ -2444,8 +2661,8 @@ var BrainerceClient = class {
|
|
|
2444
2661
|
*
|
|
2445
2662
|
* @example
|
|
2446
2663
|
* ```typescript
|
|
2447
|
-
* await
|
|
2448
|
-
* await
|
|
2664
|
+
* await client.smartUpdateCartItem('prod_123', 3); // Set quantity to 3
|
|
2665
|
+
* await client.smartUpdateCartItem('prod_123', 0); // Remove item
|
|
2449
2666
|
* ```
|
|
2450
2667
|
*/
|
|
2451
2668
|
async smartUpdateCartItem(productId, quantity, variantId) {
|
|
@@ -2462,7 +2679,24 @@ var BrainerceClient = class {
|
|
|
2462
2679
|
}
|
|
2463
2680
|
return this.updateCartItem(cart.id, item.id, { quantity });
|
|
2464
2681
|
} else {
|
|
2465
|
-
|
|
2682
|
+
if (!this.sessionToken) {
|
|
2683
|
+
return this.emptyCart();
|
|
2684
|
+
}
|
|
2685
|
+
const cart = await this.getOrCreateSessionCart();
|
|
2686
|
+
const item = cart.items.find(
|
|
2687
|
+
(i) => i.productId === productId && i.variantId === (variantId ?? null)
|
|
2688
|
+
);
|
|
2689
|
+
if (!item) {
|
|
2690
|
+
return cart;
|
|
2691
|
+
}
|
|
2692
|
+
let updated;
|
|
2693
|
+
if (quantity <= 0) {
|
|
2694
|
+
updated = await this.removeCartItem(cart.id, item.id);
|
|
2695
|
+
} else {
|
|
2696
|
+
updated = await this.updateCartItem(cart.id, item.id, { quantity });
|
|
2697
|
+
}
|
|
2698
|
+
this.updateSessionCartItemCount(updated.items?.length ?? 0);
|
|
2699
|
+
return updated;
|
|
2466
2700
|
}
|
|
2467
2701
|
}
|
|
2468
2702
|
/**
|
|
@@ -2470,32 +2704,30 @@ var BrainerceClient = class {
|
|
|
2470
2704
|
*
|
|
2471
2705
|
* @example
|
|
2472
2706
|
* ```typescript
|
|
2473
|
-
* await
|
|
2474
|
-
* await
|
|
2707
|
+
* await client.smartRemoveFromCart('prod_123');
|
|
2708
|
+
* await client.smartRemoveFromCart('prod_456', 'variant_789');
|
|
2475
2709
|
* ```
|
|
2476
2710
|
*/
|
|
2477
2711
|
async smartRemoveFromCart(productId, variantId) {
|
|
2478
2712
|
return this.smartUpdateCartItem(productId, 0, variantId);
|
|
2479
2713
|
}
|
|
2480
2714
|
/**
|
|
2481
|
-
* Sync
|
|
2715
|
+
* Sync guest cart to customer cart on login
|
|
2482
2716
|
*
|
|
2483
2717
|
* Call this AFTER setCustomerToken() when a customer logs in.
|
|
2484
2718
|
* This will:
|
|
2485
|
-
* 1.
|
|
2486
|
-
* 2.
|
|
2487
|
-
* 3. Clear localStorage
|
|
2488
|
-
*
|
|
2489
|
-
* Items that fail to sync (e.g., out of stock) are silently skipped.
|
|
2719
|
+
* 1. If a server-side session cart exists, merge it into the customer cart (atomic, server-side)
|
|
2720
|
+
* 2. If only a legacy localStorage cart exists, sync items one by one (backward compat)
|
|
2721
|
+
* 3. Clear the session/localStorage after merge
|
|
2490
2722
|
*
|
|
2491
2723
|
* @example
|
|
2492
2724
|
* ```typescript
|
|
2493
2725
|
* // Customer logs in
|
|
2494
|
-
* const auth = await
|
|
2495
|
-
*
|
|
2726
|
+
* const auth = await client.login(email, password);
|
|
2727
|
+
* client.setCustomerToken(auth.token);
|
|
2496
2728
|
*
|
|
2497
|
-
* //
|
|
2498
|
-
* const cart = await
|
|
2729
|
+
* // Merge their guest cart into customer cart
|
|
2730
|
+
* const cart = await client.syncCartOnLogin();
|
|
2499
2731
|
* console.log('Cart synced, items:', cart.items.length);
|
|
2500
2732
|
* ```
|
|
2501
2733
|
*/
|
|
@@ -2506,6 +2738,14 @@ var BrainerceClient = class {
|
|
|
2506
2738
|
401
|
|
2507
2739
|
);
|
|
2508
2740
|
}
|
|
2741
|
+
if (this.sessionToken) {
|
|
2742
|
+
try {
|
|
2743
|
+
const merged = await this.mergeSessionCartOnLogin();
|
|
2744
|
+
this.clearSessionCart();
|
|
2745
|
+
return merged;
|
|
2746
|
+
} catch {
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2509
2749
|
const localCart = this.getLocalCart();
|
|
2510
2750
|
const serverCart = await this.getOrCreateCustomerCart();
|
|
2511
2751
|
if (localCart.items.length === 0) {
|
|
@@ -2527,16 +2767,16 @@ var BrainerceClient = class {
|
|
|
2527
2767
|
/**
|
|
2528
2768
|
* Clear cart state on logout
|
|
2529
2769
|
*
|
|
2530
|
-
* Call this when a customer logs out to clear the cached cart ID.
|
|
2531
|
-
* The
|
|
2770
|
+
* Call this when a customer logs out to clear the cached customer cart ID.
|
|
2771
|
+
* The session cart (if any) remains available for the next guest session.
|
|
2532
2772
|
*
|
|
2533
2773
|
* @example
|
|
2534
2774
|
* ```typescript
|
|
2535
|
-
*
|
|
2536
|
-
*
|
|
2775
|
+
* client.clearCustomerToken();
|
|
2776
|
+
* client.onLogout();
|
|
2537
2777
|
*
|
|
2538
|
-
* // Now back to guest mode - cart uses
|
|
2539
|
-
* await
|
|
2778
|
+
* // Now back to guest mode - cart uses server-side session
|
|
2779
|
+
* await client.smartAddToCart({ productId: 'prod_123', quantity: 1 });
|
|
2540
2780
|
* ```
|
|
2541
2781
|
*/
|
|
2542
2782
|
onLogout() {
|
|
@@ -2552,13 +2792,13 @@ var BrainerceClient = class {
|
|
|
2552
2792
|
* ```typescript
|
|
2553
2793
|
* // After payment success
|
|
2554
2794
|
* if (paymentStatus === 'succeeded') {
|
|
2555
|
-
*
|
|
2556
|
-
* omni.clearLocalCart(); // Also clear localStorage for guests
|
|
2795
|
+
* client.onCheckoutComplete();
|
|
2557
2796
|
* }
|
|
2558
2797
|
* ```
|
|
2559
2798
|
*/
|
|
2560
2799
|
onCheckoutComplete() {
|
|
2561
2800
|
this.customerCartId = null;
|
|
2801
|
+
this.clearSessionCart();
|
|
2562
2802
|
}
|
|
2563
2803
|
// -------------------- Checkout --------------------
|
|
2564
2804
|
/**
|
|
@@ -2573,10 +2813,10 @@ var BrainerceClient = class {
|
|
|
2573
2813
|
* @example
|
|
2574
2814
|
* ```typescript
|
|
2575
2815
|
* // Full cart checkout (default)
|
|
2576
|
-
* const checkout = await
|
|
2816
|
+
* const checkout = await client.createCheckout({ cartId: 'cart_123' });
|
|
2577
2817
|
*
|
|
2578
2818
|
* // Partial checkout - only buy selected items
|
|
2579
|
-
* const checkout = await
|
|
2819
|
+
* const checkout = await client.createCheckout({
|
|
2580
2820
|
* cartId: 'cart_123',
|
|
2581
2821
|
* selectedItemIds: ['item_1', 'item_3'], // Only these items will be purchased
|
|
2582
2822
|
* });
|
|
@@ -2585,7 +2825,7 @@ var BrainerceClient = class {
|
|
|
2585
2825
|
async createCheckout(data) {
|
|
2586
2826
|
if (data.cartId === this.VIRTUAL_LOCAL_CART_ID) {
|
|
2587
2827
|
throw new BrainerceError(
|
|
2588
|
-
|
|
2828
|
+
'Cannot create checkout from "__local__" cart. Use startGuestCheckout() or smartAddToCart() to create a server-side cart first.',
|
|
2589
2829
|
400
|
|
2590
2830
|
);
|
|
2591
2831
|
}
|
|
@@ -2611,7 +2851,7 @@ var BrainerceClient = class {
|
|
|
2611
2851
|
*
|
|
2612
2852
|
* @example
|
|
2613
2853
|
* ```typescript
|
|
2614
|
-
* const checkout = await
|
|
2854
|
+
* const checkout = await client.getCheckout('checkout_123');
|
|
2615
2855
|
* console.log('Status:', checkout.status);
|
|
2616
2856
|
* ```
|
|
2617
2857
|
*/
|
|
@@ -2638,7 +2878,7 @@ var BrainerceClient = class {
|
|
|
2638
2878
|
*
|
|
2639
2879
|
* @example
|
|
2640
2880
|
* ```typescript
|
|
2641
|
-
* const checkout = await
|
|
2881
|
+
* const checkout = await client.setCheckoutCustomer('checkout_123', {
|
|
2642
2882
|
* email: 'customer@example.com',
|
|
2643
2883
|
* firstName: 'John',
|
|
2644
2884
|
* lastName: 'Doe',
|
|
@@ -2663,7 +2903,7 @@ var BrainerceClient = class {
|
|
|
2663
2903
|
*
|
|
2664
2904
|
* @example
|
|
2665
2905
|
* ```typescript
|
|
2666
|
-
* const { checkout, rates } = await
|
|
2906
|
+
* const { checkout, rates } = await client.setShippingAddress('checkout_123', {
|
|
2667
2907
|
* email: 'customer@example.com', // Required!
|
|
2668
2908
|
* firstName: 'John',
|
|
2669
2909
|
* lastName: 'Doe',
|
|
@@ -2703,7 +2943,7 @@ var BrainerceClient = class {
|
|
|
2703
2943
|
*
|
|
2704
2944
|
* @example
|
|
2705
2945
|
* ```typescript
|
|
2706
|
-
* const rates = await
|
|
2946
|
+
* const rates = await client.getShippingRates('checkout_123');
|
|
2707
2947
|
* console.log('Shipping options:', rates);
|
|
2708
2948
|
* ```
|
|
2709
2949
|
*/
|
|
@@ -2731,7 +2971,7 @@ var BrainerceClient = class {
|
|
|
2731
2971
|
*
|
|
2732
2972
|
* @example
|
|
2733
2973
|
* ```typescript
|
|
2734
|
-
* const checkout = await
|
|
2974
|
+
* const checkout = await client.selectShippingMethod('checkout_123', 'rate_express');
|
|
2735
2975
|
* console.log('Shipping cost:', checkout.shippingAmount);
|
|
2736
2976
|
* ```
|
|
2737
2977
|
*/
|
|
@@ -2766,13 +3006,13 @@ var BrainerceClient = class {
|
|
|
2766
3006
|
* @example
|
|
2767
3007
|
* ```typescript
|
|
2768
3008
|
* // Use same as shipping
|
|
2769
|
-
* const checkout = await
|
|
3009
|
+
* const checkout = await client.setBillingAddress('checkout_123', {
|
|
2770
3010
|
* ...shippingAddress,
|
|
2771
3011
|
* sameAsShipping: true,
|
|
2772
3012
|
* });
|
|
2773
3013
|
*
|
|
2774
3014
|
* // Or set different billing address
|
|
2775
|
-
* const checkout = await
|
|
3015
|
+
* const checkout = await client.setBillingAddress('checkout_123', {
|
|
2776
3016
|
* firstName: 'John',
|
|
2777
3017
|
* lastName: 'Doe',
|
|
2778
3018
|
* line1: '456 Business Ave',
|
|
@@ -2810,7 +3050,7 @@ var BrainerceClient = class {
|
|
|
2810
3050
|
*
|
|
2811
3051
|
* @example
|
|
2812
3052
|
* ```typescript
|
|
2813
|
-
* const { orderId } = await
|
|
3053
|
+
* const { orderId } = await client.completeCheckout('checkout_123');
|
|
2814
3054
|
* console.log('Order created:', orderId);
|
|
2815
3055
|
* ```
|
|
2816
3056
|
*/
|
|
@@ -2849,7 +3089,7 @@ var BrainerceClient = class {
|
|
|
2849
3089
|
*
|
|
2850
3090
|
* @example
|
|
2851
3091
|
* ```typescript
|
|
2852
|
-
* const config = await
|
|
3092
|
+
* const config = await client.getPaymentConfig();
|
|
2853
3093
|
*
|
|
2854
3094
|
* // Initialize Stripe.js with the public key
|
|
2855
3095
|
* const stripe = Stripe(config.publicKey);
|
|
@@ -2882,7 +3122,7 @@ var BrainerceClient = class {
|
|
|
2882
3122
|
*
|
|
2883
3123
|
* @example
|
|
2884
3124
|
* ```typescript
|
|
2885
|
-
* const { providers, hasPayments, defaultProvider } = await
|
|
3125
|
+
* const { providers, hasPayments, defaultProvider } = await client.getPaymentProviders();
|
|
2886
3126
|
*
|
|
2887
3127
|
* if (!hasPayments) {
|
|
2888
3128
|
* // Show error: "Payment is not configured for this store"
|
|
@@ -2934,7 +3174,7 @@ var BrainerceClient = class {
|
|
|
2934
3174
|
* @example
|
|
2935
3175
|
* ```typescript
|
|
2936
3176
|
* // After completing checkout steps (shipping address, method, etc.)
|
|
2937
|
-
* const intent = await
|
|
3177
|
+
* const intent = await client.createPaymentIntent(checkout.id, {
|
|
2938
3178
|
* successUrl: `${window.location.origin}/order-confirmation?checkout_id=${checkout.id}`,
|
|
2939
3179
|
* cancelUrl: `${window.location.origin}/checkout?error=cancelled`,
|
|
2940
3180
|
* });
|
|
@@ -2981,7 +3221,7 @@ var BrainerceClient = class {
|
|
|
2981
3221
|
* @example
|
|
2982
3222
|
* ```typescript
|
|
2983
3223
|
* // After returning from Stripe redirect
|
|
2984
|
-
* const status = await
|
|
3224
|
+
* const status = await client.getPaymentStatus(checkoutId);
|
|
2985
3225
|
*
|
|
2986
3226
|
* if (status.status === 'succeeded') {
|
|
2987
3227
|
* // Redirect to order confirmation
|
|
@@ -3031,7 +3271,7 @@ var BrainerceClient = class {
|
|
|
3031
3271
|
* @example
|
|
3032
3272
|
* ```typescript
|
|
3033
3273
|
* // Basic usage - wait up to 30 seconds
|
|
3034
|
-
* const result = await
|
|
3274
|
+
* const result = await client.waitForOrder(checkoutId);
|
|
3035
3275
|
*
|
|
3036
3276
|
* if (result.success) {
|
|
3037
3277
|
* console.log('Order created:', result.status.orderNumber);
|
|
@@ -3044,7 +3284,7 @@ var BrainerceClient = class {
|
|
|
3044
3284
|
* @example
|
|
3045
3285
|
* ```typescript
|
|
3046
3286
|
* // With progress callback for UI updates
|
|
3047
|
-
* const result = await
|
|
3287
|
+
* const result = await client.waitForOrder(checkoutId, {
|
|
3048
3288
|
* maxWaitMs: 20000,
|
|
3049
3289
|
* onPollAttempt: (attempt, status) => {
|
|
3050
3290
|
* setLoadingMessage(`Confirming order... (attempt ${attempt})`);
|
|
@@ -3112,7 +3352,7 @@ var BrainerceClient = class {
|
|
|
3112
3352
|
if (typeof window === "undefined" || !window.localStorage) {
|
|
3113
3353
|
return false;
|
|
3114
3354
|
}
|
|
3115
|
-
const test = "
|
|
3355
|
+
const test = "__brainerce_test__";
|
|
3116
3356
|
window.localStorage.setItem(test, test);
|
|
3117
3357
|
window.localStorage.removeItem(test);
|
|
3118
3358
|
return true;
|
|
@@ -3121,14 +3361,8 @@ var BrainerceClient = class {
|
|
|
3121
3361
|
}
|
|
3122
3362
|
}
|
|
3123
3363
|
/**
|
|
3124
|
-
*
|
|
3125
|
-
* Returns empty cart if none exists
|
|
3126
|
-
*
|
|
3127
|
-
* @example
|
|
3128
|
-
* ```typescript
|
|
3129
|
-
* const cart = omni.getLocalCart();
|
|
3130
|
-
* console.log('Items in cart:', cart.items.length);
|
|
3131
|
-
* ```
|
|
3364
|
+
* @deprecated Use `smartGetCart()` instead. Guest carts are now stored on the server.
|
|
3365
|
+
* Get local cart from localStorage. Returns empty cart if none exists.
|
|
3132
3366
|
*/
|
|
3133
3367
|
getLocalCart() {
|
|
3134
3368
|
if (!this.isLocalStorageAvailable()) {
|
|
@@ -3210,18 +3444,8 @@ var BrainerceClient = class {
|
|
|
3210
3444
|
};
|
|
3211
3445
|
}
|
|
3212
3446
|
/**
|
|
3213
|
-
*
|
|
3214
|
-
* If item already exists, updates quantity
|
|
3215
|
-
*
|
|
3216
|
-
* @example
|
|
3217
|
-
* ```typescript
|
|
3218
|
-
* omni.addToLocalCart({
|
|
3219
|
-
* productId: 'prod_123',
|
|
3220
|
-
* quantity: 2,
|
|
3221
|
-
* name: 'Cool Shirt',
|
|
3222
|
-
* price: '29.99',
|
|
3223
|
-
* });
|
|
3224
|
-
* ```
|
|
3447
|
+
* @deprecated Use `smartAddToCart()` instead. Guest carts are now stored on the server.
|
|
3448
|
+
* Add item to local cart (NO API call). If item already exists, updates quantity.
|
|
3225
3449
|
*/
|
|
3226
3450
|
addToLocalCart(item) {
|
|
3227
3451
|
const cart = this.getLocalCart();
|
|
@@ -3243,14 +3467,8 @@ var BrainerceClient = class {
|
|
|
3243
3467
|
return cart;
|
|
3244
3468
|
}
|
|
3245
3469
|
/**
|
|
3246
|
-
*
|
|
3247
|
-
* Set quantity to 0 to remove item
|
|
3248
|
-
*
|
|
3249
|
-
* @example
|
|
3250
|
-
* ```typescript
|
|
3251
|
-
* omni.updateLocalCartItem('prod_123', 3); // Set quantity to 3
|
|
3252
|
-
* omni.updateLocalCartItem('prod_123', 0); // Remove item
|
|
3253
|
-
* ```
|
|
3470
|
+
* @deprecated Use `smartUpdateCartItem()` instead. Guest carts are now stored on the server.
|
|
3471
|
+
* Update item quantity in local cart. Set quantity to 0 to remove item.
|
|
3254
3472
|
*/
|
|
3255
3473
|
updateLocalCartItem(productId, quantity, variantId) {
|
|
3256
3474
|
const cart = this.getLocalCart();
|
|
@@ -3268,24 +3486,13 @@ var BrainerceClient = class {
|
|
|
3268
3486
|
return cart;
|
|
3269
3487
|
}
|
|
3270
3488
|
/**
|
|
3271
|
-
*
|
|
3272
|
-
*
|
|
3273
|
-
* @example
|
|
3274
|
-
* ```typescript
|
|
3275
|
-
* omni.removeFromLocalCart('prod_123');
|
|
3276
|
-
* omni.removeFromLocalCart('prod_456', 'variant_789');
|
|
3277
|
-
* ```
|
|
3489
|
+
* @deprecated Use `smartRemoveFromCart()` instead. Guest carts are now stored on the server.
|
|
3278
3490
|
*/
|
|
3279
3491
|
removeFromLocalCart(productId, variantId) {
|
|
3280
3492
|
return this.updateLocalCartItem(productId, 0, variantId);
|
|
3281
3493
|
}
|
|
3282
3494
|
/**
|
|
3283
|
-
*
|
|
3284
|
-
*
|
|
3285
|
-
* @example
|
|
3286
|
-
* ```typescript
|
|
3287
|
-
* omni.clearLocalCart();
|
|
3288
|
-
* ```
|
|
3495
|
+
* @deprecated Use `onCheckoutComplete()` instead. Guest carts are now stored on the server.
|
|
3289
3496
|
*/
|
|
3290
3497
|
clearLocalCart() {
|
|
3291
3498
|
const cart = { items: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
@@ -3293,16 +3500,8 @@ var BrainerceClient = class {
|
|
|
3293
3500
|
return cart;
|
|
3294
3501
|
}
|
|
3295
3502
|
/**
|
|
3296
|
-
*
|
|
3297
|
-
*
|
|
3298
|
-
* @example
|
|
3299
|
-
* ```typescript
|
|
3300
|
-
* omni.setLocalCartCustomer({
|
|
3301
|
-
* email: 'john@example.com',
|
|
3302
|
-
* firstName: 'John',
|
|
3303
|
-
* lastName: 'Doe',
|
|
3304
|
-
* });
|
|
3305
|
-
* ```
|
|
3503
|
+
* @deprecated Customer info is now set via checkout address methods.
|
|
3504
|
+
* Still used by `submitGuestOrder()` for backward compatibility.
|
|
3306
3505
|
*/
|
|
3307
3506
|
setLocalCartCustomer(customer) {
|
|
3308
3507
|
const cart = this.getLocalCart();
|
|
@@ -3311,19 +3510,8 @@ var BrainerceClient = class {
|
|
|
3311
3510
|
return cart;
|
|
3312
3511
|
}
|
|
3313
3512
|
/**
|
|
3314
|
-
*
|
|
3315
|
-
*
|
|
3316
|
-
* @example
|
|
3317
|
-
* ```typescript
|
|
3318
|
-
* omni.setLocalCartShippingAddress({
|
|
3319
|
-
* firstName: 'John',
|
|
3320
|
-
* lastName: 'Doe',
|
|
3321
|
-
* line1: '123 Main St',
|
|
3322
|
-
* city: 'Tel Aviv',
|
|
3323
|
-
* postalCode: '6100000',
|
|
3324
|
-
* country: 'IL',
|
|
3325
|
-
* });
|
|
3326
|
-
* ```
|
|
3513
|
+
* @deprecated Address is now set via `updateGuestCheckoutAddress()` after `startGuestCheckout()`.
|
|
3514
|
+
* Still used by `submitGuestOrder()` for backward compatibility.
|
|
3327
3515
|
*/
|
|
3328
3516
|
setLocalCartShippingAddress(address) {
|
|
3329
3517
|
const cart = this.getLocalCart();
|
|
@@ -3332,7 +3520,8 @@ var BrainerceClient = class {
|
|
|
3332
3520
|
return cart;
|
|
3333
3521
|
}
|
|
3334
3522
|
/**
|
|
3335
|
-
*
|
|
3523
|
+
* @deprecated Address is now set via `updateGuestCheckoutAddress()` after `startGuestCheckout()`.
|
|
3524
|
+
* Still used by `submitGuestOrder()` for backward compatibility.
|
|
3336
3525
|
*/
|
|
3337
3526
|
setLocalCartBillingAddress(address) {
|
|
3338
3527
|
const cart = this.getLocalCart();
|
|
@@ -3341,7 +3530,7 @@ var BrainerceClient = class {
|
|
|
3341
3530
|
return cart;
|
|
3342
3531
|
}
|
|
3343
3532
|
/**
|
|
3344
|
-
*
|
|
3533
|
+
* @deprecated Coupons are now applied via `applyCoupon()` on the server cart.
|
|
3345
3534
|
*/
|
|
3346
3535
|
setLocalCartCoupon(couponCode) {
|
|
3347
3536
|
const cart = this.getLocalCart();
|
|
@@ -3350,7 +3539,7 @@ var BrainerceClient = class {
|
|
|
3350
3539
|
return cart;
|
|
3351
3540
|
}
|
|
3352
3541
|
/**
|
|
3353
|
-
*
|
|
3542
|
+
* @deprecated Use `getSmartCartItemCount()` instead.
|
|
3354
3543
|
*/
|
|
3355
3544
|
getLocalCartItemCount() {
|
|
3356
3545
|
const cart = this.getLocalCart();
|
|
@@ -3368,18 +3557,52 @@ var BrainerceClient = class {
|
|
|
3368
3557
|
* @example
|
|
3369
3558
|
* ```typescript
|
|
3370
3559
|
* // Build up the local cart first
|
|
3371
|
-
*
|
|
3372
|
-
*
|
|
3373
|
-
*
|
|
3560
|
+
* client.addToLocalCart({ productId: 'prod_123', quantity: 2 });
|
|
3561
|
+
* client.setLocalCartCustomer({ email: 'john@example.com', firstName: 'John' });
|
|
3562
|
+
* client.setLocalCartShippingAddress({ ... });
|
|
3374
3563
|
*
|
|
3375
3564
|
* // Then submit the order - tracking is automatic if enabled in admin!
|
|
3376
|
-
* const result = await
|
|
3565
|
+
* const result = await client.submitGuestOrder();
|
|
3377
3566
|
* console.log('Order created:', result.orderId);
|
|
3378
3567
|
*
|
|
3379
3568
|
* // Cart is automatically cleared on success
|
|
3380
3569
|
* ```
|
|
3381
3570
|
*/
|
|
3382
3571
|
async submitGuestOrder(options) {
|
|
3572
|
+
if (this.sessionToken) {
|
|
3573
|
+
const serverCart = await this.getOrCreateSessionCart();
|
|
3574
|
+
if (!serverCart.items || serverCart.items.length === 0) {
|
|
3575
|
+
throw new BrainerceError("Cart is empty", 400);
|
|
3576
|
+
}
|
|
3577
|
+
const localCart = this.getLocalCart();
|
|
3578
|
+
if (!localCart.customer?.email) {
|
|
3579
|
+
throw new BrainerceError("Customer email is required. Call setLocalCartCustomer() first.", 400);
|
|
3580
|
+
}
|
|
3581
|
+
if (!localCart.shippingAddress) {
|
|
3582
|
+
throw new BrainerceError("Shipping address is required. Call setLocalCartShippingAddress() first.", 400);
|
|
3583
|
+
}
|
|
3584
|
+
const trackingResult = await this.startGuestCheckout();
|
|
3585
|
+
if (!trackingResult.tracked) {
|
|
3586
|
+
throw new BrainerceError("Failed to create checkout from session cart", 500);
|
|
3587
|
+
}
|
|
3588
|
+
await this.updateGuestCheckoutAddress(trackingResult.checkoutId, {
|
|
3589
|
+
shippingAddress: {
|
|
3590
|
+
...localCart.shippingAddress,
|
|
3591
|
+
email: localCart.customer.email
|
|
3592
|
+
},
|
|
3593
|
+
billingAddress: localCart.billingAddress
|
|
3594
|
+
});
|
|
3595
|
+
const orderResult = await this.completeGuestCheckout(trackingResult.checkoutId, {
|
|
3596
|
+
clearCartOnSuccess: options?.clearCartOnSuccess
|
|
3597
|
+
});
|
|
3598
|
+
return {
|
|
3599
|
+
orderId: orderResult.orderId,
|
|
3600
|
+
orderNumber: orderResult.orderNumber || orderResult.orderId,
|
|
3601
|
+
status: orderResult.status || "pending",
|
|
3602
|
+
total: orderResult.total ?? 0,
|
|
3603
|
+
message: orderResult.message || "Order created successfully"
|
|
3604
|
+
};
|
|
3605
|
+
}
|
|
3383
3606
|
const cart = this.getLocalCart();
|
|
3384
3607
|
if (cart.items.length === 0) {
|
|
3385
3608
|
throw new BrainerceError("Cart is empty", 400);
|
|
@@ -3397,7 +3620,6 @@ var BrainerceClient = class {
|
|
|
3397
3620
|
shippingAddress: {
|
|
3398
3621
|
...cart.shippingAddress,
|
|
3399
3622
|
email: cart.customer.email
|
|
3400
|
-
// Already validated above
|
|
3401
3623
|
},
|
|
3402
3624
|
billingAddress: cart.billingAddress
|
|
3403
3625
|
});
|
|
@@ -3456,14 +3678,14 @@ var BrainerceClient = class {
|
|
|
3456
3678
|
* @example
|
|
3457
3679
|
* ```typescript
|
|
3458
3680
|
* // Full checkout (all items)
|
|
3459
|
-
* const result = await
|
|
3681
|
+
* const result = await client.startGuestCheckout();
|
|
3460
3682
|
*
|
|
3461
3683
|
* // Partial checkout (only items at index 0 and 2)
|
|
3462
|
-
* const result = await
|
|
3684
|
+
* const result = await client.startGuestCheckout({ selectedIndices: [0, 2] });
|
|
3463
3685
|
*
|
|
3464
3686
|
* if (result.tracked) {
|
|
3465
3687
|
* // IMPORTANT: Fetch checkout and use checkout.lineItems for Order Summary!
|
|
3466
|
-
* const checkout = await
|
|
3688
|
+
* const checkout = await client.getCheckout(result.checkoutId);
|
|
3467
3689
|
*
|
|
3468
3690
|
* // Display Order Summary using checkout.lineItems (NOT localCart.items!)
|
|
3469
3691
|
* // checkout.lineItems contains ONLY the selected items
|
|
@@ -3472,19 +3694,47 @@ var BrainerceClient = class {
|
|
|
3472
3694
|
* });
|
|
3473
3695
|
*
|
|
3474
3696
|
* // Update checkout with address
|
|
3475
|
-
* await
|
|
3697
|
+
* await client.updateGuestCheckoutAddress(result.checkoutId, {
|
|
3476
3698
|
* shippingAddress: { ... },
|
|
3477
3699
|
* });
|
|
3478
3700
|
*
|
|
3479
3701
|
* // After payment success, call handlePaymentSuccess() to clear cart
|
|
3480
|
-
*
|
|
3702
|
+
* client.handlePaymentSuccess(result.checkoutId);
|
|
3481
3703
|
* } else {
|
|
3482
3704
|
* // Tracking not enabled, use regular submitGuestOrder
|
|
3483
|
-
* const order = await
|
|
3705
|
+
* const order = await client.submitGuestOrder();
|
|
3484
3706
|
* }
|
|
3485
3707
|
* ```
|
|
3486
3708
|
*/
|
|
3487
3709
|
async startGuestCheckout(options) {
|
|
3710
|
+
if (this.sessionToken) {
|
|
3711
|
+
const serverCart = await this.getOrCreateSessionCart();
|
|
3712
|
+
if (!serverCart.items || serverCart.items.length === 0) {
|
|
3713
|
+
throw new BrainerceError("Cart is empty", 400);
|
|
3714
|
+
}
|
|
3715
|
+
let selectedItemIds;
|
|
3716
|
+
if (options?.selectedIndices?.length) {
|
|
3717
|
+
selectedItemIds = options.selectedIndices.map((i) => serverCart.items[i]?.id).filter((id) => !!id);
|
|
3718
|
+
if (selectedItemIds.length === 0) {
|
|
3719
|
+
throw new BrainerceError("No items selected for checkout", 400);
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
const checkout = await this.createCheckout({
|
|
3723
|
+
cartId: serverCart.id,
|
|
3724
|
+
selectedItemIds
|
|
3725
|
+
});
|
|
3726
|
+
this.saveActiveCheckout({
|
|
3727
|
+
checkoutId: checkout.id,
|
|
3728
|
+
cartId: serverCart.id,
|
|
3729
|
+
selectedIndices: options?.selectedIndices
|
|
3730
|
+
});
|
|
3731
|
+
return {
|
|
3732
|
+
tracked: true,
|
|
3733
|
+
checkoutId: checkout.id,
|
|
3734
|
+
cartId: serverCart.id,
|
|
3735
|
+
message: "Checkout created from session cart"
|
|
3736
|
+
};
|
|
3737
|
+
}
|
|
3488
3738
|
const cart = this.getLocalCart();
|
|
3489
3739
|
if (cart.items.length === 0) {
|
|
3490
3740
|
throw new BrainerceError("Cart is empty", 400);
|
|
@@ -3548,16 +3798,8 @@ var BrainerceClient = class {
|
|
|
3548
3798
|
}
|
|
3549
3799
|
}
|
|
3550
3800
|
/**
|
|
3801
|
+
* @deprecated Partial checkout is now handled server-side via `selectedItemIds`.
|
|
3551
3802
|
* Remove specific items from local cart by their indices.
|
|
3552
|
-
* Use after partial checkout to remove only the purchased items.
|
|
3553
|
-
*
|
|
3554
|
-
* @param indices - Array of item indices to remove
|
|
3555
|
-
*
|
|
3556
|
-
* @example
|
|
3557
|
-
* ```typescript
|
|
3558
|
-
* // After partial checkout success, remove purchased items
|
|
3559
|
-
* omni.removeLocalCartItemsByIndex([0, 2]); // Removes items at index 0 and 2
|
|
3560
|
-
* ```
|
|
3561
3803
|
*/
|
|
3562
3804
|
removeLocalCartItemsByIndex(indices) {
|
|
3563
3805
|
const cart = this.getLocalCart();
|
|
@@ -3612,13 +3854,13 @@ var BrainerceClient = class {
|
|
|
3612
3854
|
*
|
|
3613
3855
|
* @example Full checkout (clears entire cart):
|
|
3614
3856
|
* ```typescript
|
|
3615
|
-
* await
|
|
3857
|
+
* await client.completeGuestCheckout(checkoutId);
|
|
3616
3858
|
* ```
|
|
3617
3859
|
*
|
|
3618
3860
|
* @example Partial checkout (removes only purchased items):
|
|
3619
3861
|
* ```typescript
|
|
3620
3862
|
* // User selected items at indices 0 and 2 for checkout
|
|
3621
|
-
* await
|
|
3863
|
+
* await client.completeGuestCheckout(checkoutId, { selectedIndices: [0, 2] });
|
|
3622
3864
|
* // Items at indices 1, 3, etc. remain in cart
|
|
3623
3865
|
* ```
|
|
3624
3866
|
*/
|
|
@@ -3634,6 +3876,7 @@ var BrainerceClient = class {
|
|
|
3634
3876
|
this.removeLocalCartItemsByIndex(indices);
|
|
3635
3877
|
} else {
|
|
3636
3878
|
this.clearLocalCart();
|
|
3879
|
+
this.clearSessionCart();
|
|
3637
3880
|
}
|
|
3638
3881
|
this.customerCartId = null;
|
|
3639
3882
|
}
|
|
@@ -3648,7 +3891,7 @@ var BrainerceClient = class {
|
|
|
3648
3891
|
*
|
|
3649
3892
|
* @example
|
|
3650
3893
|
* ```typescript
|
|
3651
|
-
* const activeCheckout =
|
|
3894
|
+
* const activeCheckout = client.getActiveGuestCheckout();
|
|
3652
3895
|
* if (activeCheckout) {
|
|
3653
3896
|
* console.log('Active checkout:', activeCheckout.checkoutId);
|
|
3654
3897
|
* console.log('Partial checkout:', activeCheckout.selectedIndices?.length);
|
|
@@ -3689,7 +3932,7 @@ var BrainerceClient = class {
|
|
|
3689
3932
|
*
|
|
3690
3933
|
* if (!error && paymentIntent?.status === 'succeeded') {
|
|
3691
3934
|
* // Clear the cart automatically - handles all scenarios!
|
|
3692
|
-
* const result =
|
|
3935
|
+
* const result = client.handlePaymentSuccess(checkoutId);
|
|
3693
3936
|
* console.log('Cart cleared:', result.cleared);
|
|
3694
3937
|
* console.log('User type:', result.userType); // 'guest' or 'customer'
|
|
3695
3938
|
* }
|
|
@@ -3700,13 +3943,13 @@ var BrainerceClient = class {
|
|
|
3700
3943
|
* // On success page (after redirect)
|
|
3701
3944
|
* const checkoutId = new URLSearchParams(location.search).get('checkout_id');
|
|
3702
3945
|
* if (checkoutId) {
|
|
3703
|
-
*
|
|
3946
|
+
* client.handlePaymentSuccess(checkoutId);
|
|
3704
3947
|
* }
|
|
3705
3948
|
* ```
|
|
3706
3949
|
*/
|
|
3707
3950
|
handlePaymentSuccess(checkoutId) {
|
|
3708
3951
|
const isLoggedIn = this.isCustomerLoggedIn();
|
|
3709
|
-
const handledKey = `
|
|
3952
|
+
const handledKey = `brainerce_payment_handled_${checkoutId || "latest"}`;
|
|
3710
3953
|
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
3711
3954
|
if (sessionStorage.getItem(handledKey)) {
|
|
3712
3955
|
return {
|
|
@@ -3731,6 +3974,7 @@ var BrainerceClient = class {
|
|
|
3731
3974
|
}
|
|
3732
3975
|
if (isLoggedIn) {
|
|
3733
3976
|
this.clearLocalCart();
|
|
3977
|
+
this.clearSessionCart();
|
|
3734
3978
|
return {
|
|
3735
3979
|
cleared: true,
|
|
3736
3980
|
mode: "full",
|
|
@@ -3747,6 +3991,7 @@ var BrainerceClient = class {
|
|
|
3747
3991
|
};
|
|
3748
3992
|
}
|
|
3749
3993
|
this.clearLocalCart();
|
|
3994
|
+
this.clearSessionCart();
|
|
3750
3995
|
return {
|
|
3751
3996
|
cleared: true,
|
|
3752
3997
|
mode: "full",
|
|
@@ -3766,7 +4011,7 @@ var BrainerceClient = class {
|
|
|
3766
4011
|
*
|
|
3767
4012
|
* @example
|
|
3768
4013
|
* ```typescript
|
|
3769
|
-
* const result = await
|
|
4014
|
+
* const result = await client.createGuestOrder({
|
|
3770
4015
|
* items: [{ productId: 'prod_123', quantity: 2 }],
|
|
3771
4016
|
* customer: { email: 'john@example.com' },
|
|
3772
4017
|
* shippingAddress: { firstName: 'John', ... },
|
|
@@ -3784,9 +4029,9 @@ var BrainerceClient = class {
|
|
|
3784
4029
|
*
|
|
3785
4030
|
* @example
|
|
3786
4031
|
* ```typescript
|
|
3787
|
-
* const auth = await
|
|
3788
|
-
*
|
|
3789
|
-
* const profile = await
|
|
4032
|
+
* const auth = await client.loginCustomer('user@example.com', 'password');
|
|
4033
|
+
* client.setCustomerToken(auth.token);
|
|
4034
|
+
* const profile = await client.getMyProfile();
|
|
3790
4035
|
* ```
|
|
3791
4036
|
*/
|
|
3792
4037
|
async getMyProfile() {
|
|
@@ -3814,9 +4059,9 @@ var BrainerceClient = class {
|
|
|
3814
4059
|
*
|
|
3815
4060
|
* @example
|
|
3816
4061
|
* ```typescript
|
|
3817
|
-
*
|
|
4062
|
+
* client.setCustomerToken(auth.token);
|
|
3818
4063
|
*
|
|
3819
|
-
* const prefill = await
|
|
4064
|
+
* const prefill = await client.getCheckoutPrefillData();
|
|
3820
4065
|
*
|
|
3821
4066
|
* if (prefill.shippingAddress) {
|
|
3822
4067
|
* // Pre-fill shipping form with customer's default address
|
|
@@ -3913,7 +4158,7 @@ var BrainerceClient = class {
|
|
|
3913
4158
|
*
|
|
3914
4159
|
* @example
|
|
3915
4160
|
* ```typescript
|
|
3916
|
-
* const links = await
|
|
4161
|
+
* const links = await client.getOrderDownloads('order_123');
|
|
3917
4162
|
* for (const link of links) {
|
|
3918
4163
|
* console.log(`${link.productName}: ${link.downloadUrl}`);
|
|
3919
4164
|
* }
|
|
@@ -4066,7 +4311,7 @@ var BrainerceClient = class {
|
|
|
4066
4311
|
*
|
|
4067
4312
|
* @example
|
|
4068
4313
|
* ```typescript
|
|
4069
|
-
* const integrations = await
|
|
4314
|
+
* const integrations = await client.getCustomApiIntegrations();
|
|
4070
4315
|
* integrations.forEach(api => {
|
|
4071
4316
|
* console.log(`${api.name}: ${api.status}`);
|
|
4072
4317
|
* });
|
|
@@ -4081,7 +4326,7 @@ var BrainerceClient = class {
|
|
|
4081
4326
|
*
|
|
4082
4327
|
* @example
|
|
4083
4328
|
* ```typescript
|
|
4084
|
-
* const api = await
|
|
4329
|
+
* const api = await client.getCustomApiIntegration('api_123');
|
|
4085
4330
|
* console.log(`API: ${api.name}, URL: ${api.baseUrl}`);
|
|
4086
4331
|
* ```
|
|
4087
4332
|
*/
|
|
@@ -4094,7 +4339,7 @@ var BrainerceClient = class {
|
|
|
4094
4339
|
*
|
|
4095
4340
|
* @example
|
|
4096
4341
|
* ```typescript
|
|
4097
|
-
* const api = await
|
|
4342
|
+
* const api = await client.createCustomApiIntegration({
|
|
4098
4343
|
* name: 'My External API',
|
|
4099
4344
|
* baseUrl: 'https://api.example.com',
|
|
4100
4345
|
* authType: 'api_key',
|
|
@@ -4120,7 +4365,7 @@ var BrainerceClient = class {
|
|
|
4120
4365
|
*
|
|
4121
4366
|
* @example
|
|
4122
4367
|
* ```typescript
|
|
4123
|
-
* const api = await
|
|
4368
|
+
* const api = await client.updateCustomApiIntegration('api_123', {
|
|
4124
4369
|
* enabled: false,
|
|
4125
4370
|
* syncConfig: { products: true, orders: false, inventory: true },
|
|
4126
4371
|
* });
|
|
@@ -4139,7 +4384,7 @@ var BrainerceClient = class {
|
|
|
4139
4384
|
*
|
|
4140
4385
|
* @example
|
|
4141
4386
|
* ```typescript
|
|
4142
|
-
* await
|
|
4387
|
+
* await client.deleteCustomApiIntegration('api_123');
|
|
4143
4388
|
* ```
|
|
4144
4389
|
*/
|
|
4145
4390
|
async deleteCustomApiIntegration(integrationId) {
|
|
@@ -4151,7 +4396,7 @@ var BrainerceClient = class {
|
|
|
4151
4396
|
*
|
|
4152
4397
|
* @example
|
|
4153
4398
|
* ```typescript
|
|
4154
|
-
* const result = await
|
|
4399
|
+
* const result = await client.testCustomApiConnection('api_123');
|
|
4155
4400
|
* if (result.success) {
|
|
4156
4401
|
* console.log(`Connection OK, latency: ${result.latency}ms`);
|
|
4157
4402
|
* } else {
|
|
@@ -4179,7 +4424,7 @@ var BrainerceClient = class {
|
|
|
4179
4424
|
*
|
|
4180
4425
|
* @example
|
|
4181
4426
|
* ```typescript
|
|
4182
|
-
* const availability = await
|
|
4427
|
+
* const availability = await client.getAvailability(['prod_123', 'prod_456']);
|
|
4183
4428
|
* availability.forEach(item => {
|
|
4184
4429
|
* if (!item.canPurchase) {
|
|
4185
4430
|
* console.log(`${item.productId}: Cannot purchase`);
|
|
@@ -4213,7 +4458,7 @@ var BrainerceClient = class {
|
|
|
4213
4458
|
* @example
|
|
4214
4459
|
* ```typescript
|
|
4215
4460
|
* // Extend reservation when customer shows activity
|
|
4216
|
-
* const result = await
|
|
4461
|
+
* const result = await client.extendReservation({ checkoutId: 'chk_123' });
|
|
4217
4462
|
* if (result.success) {
|
|
4218
4463
|
* console.log(`Reservation extended until ${result.reservation.expiresAt}`);
|
|
4219
4464
|
* }
|
|
@@ -4243,7 +4488,7 @@ var BrainerceClient = class {
|
|
|
4243
4488
|
* @example
|
|
4244
4489
|
* ```typescript
|
|
4245
4490
|
* // Release reservation when customer abandons checkout
|
|
4246
|
-
* await
|
|
4491
|
+
* await client.releaseReservation({ checkoutId: 'chk_123' });
|
|
4247
4492
|
* ```
|
|
4248
4493
|
*/
|
|
4249
4494
|
async releaseReservation(options) {
|
|
@@ -4266,7 +4511,7 @@ var BrainerceClient = class {
|
|
|
4266
4511
|
*
|
|
4267
4512
|
* @example
|
|
4268
4513
|
* ```typescript
|
|
4269
|
-
* const categories = await
|
|
4514
|
+
* const categories = await client.listCategories({ page: 1, limit: 20 });
|
|
4270
4515
|
* console.log(`Found ${categories.meta.total} categories`);
|
|
4271
4516
|
* ```
|
|
4272
4517
|
*/
|
|
@@ -4291,7 +4536,7 @@ var BrainerceClient = class {
|
|
|
4291
4536
|
*
|
|
4292
4537
|
* @example
|
|
4293
4538
|
* ```typescript
|
|
4294
|
-
* const category = await
|
|
4539
|
+
* const category = await client.createCategory({
|
|
4295
4540
|
* name: 'Electronics',
|
|
4296
4541
|
* slug: 'electronics',
|
|
4297
4542
|
* description: 'Electronic devices and accessories',
|
|
@@ -4337,7 +4582,7 @@ var BrainerceClient = class {
|
|
|
4337
4582
|
*
|
|
4338
4583
|
* @example
|
|
4339
4584
|
* ```typescript
|
|
4340
|
-
* const brand = await
|
|
4585
|
+
* const brand = await client.createBrand({
|
|
4341
4586
|
* name: 'Nike',
|
|
4342
4587
|
* slug: 'nike',
|
|
4343
4588
|
* logoUrl: 'https://example.com/nike-logo.png',
|
|
@@ -4383,7 +4628,7 @@ var BrainerceClient = class {
|
|
|
4383
4628
|
*
|
|
4384
4629
|
* @example
|
|
4385
4630
|
* ```typescript
|
|
4386
|
-
* const tag = await
|
|
4631
|
+
* const tag = await client.createTag({
|
|
4387
4632
|
* name: 'New Arrival',
|
|
4388
4633
|
* slug: 'new-arrival',
|
|
4389
4634
|
* });
|
|
@@ -4433,7 +4678,7 @@ var BrainerceClient = class {
|
|
|
4433
4678
|
*
|
|
4434
4679
|
* @example
|
|
4435
4680
|
* ```typescript
|
|
4436
|
-
* const attribute = await
|
|
4681
|
+
* const attribute = await client.createAttribute({
|
|
4437
4682
|
* name: 'Color',
|
|
4438
4683
|
* slug: 'color',
|
|
4439
4684
|
* source: 'custom',
|
|
@@ -4470,7 +4715,7 @@ var BrainerceClient = class {
|
|
|
4470
4715
|
*
|
|
4471
4716
|
* @example
|
|
4472
4717
|
* ```typescript
|
|
4473
|
-
* const option = await
|
|
4718
|
+
* const option = await client.createAttributeOption('attr_123', {
|
|
4474
4719
|
* value: 'Red',
|
|
4475
4720
|
* slug: 'red',
|
|
4476
4721
|
* sortOrder: 1,
|
|
@@ -4532,7 +4777,7 @@ var BrainerceClient = class {
|
|
|
4532
4777
|
*
|
|
4533
4778
|
* @example
|
|
4534
4779
|
* ```typescript
|
|
4535
|
-
* const zone = await
|
|
4780
|
+
* const zone = await client.createShippingZone({
|
|
4536
4781
|
* name: 'US Domestic',
|
|
4537
4782
|
* countries: ['US'],
|
|
4538
4783
|
* regions: ['CA', 'NY', 'TX'],
|
|
@@ -4569,7 +4814,7 @@ var BrainerceClient = class {
|
|
|
4569
4814
|
*
|
|
4570
4815
|
* @example
|
|
4571
4816
|
* ```typescript
|
|
4572
|
-
* const rate = await
|
|
4817
|
+
* const rate = await client.createZoneShippingRate('zone_123', {
|
|
4573
4818
|
* name: 'Standard Shipping',
|
|
4574
4819
|
* type: 'flat',
|
|
4575
4820
|
* price: 5.99,
|
|
@@ -4625,7 +4870,7 @@ var BrainerceClient = class {
|
|
|
4625
4870
|
*
|
|
4626
4871
|
* @example
|
|
4627
4872
|
* ```typescript
|
|
4628
|
-
* const rate = await
|
|
4873
|
+
* const rate = await client.createTaxRate({
|
|
4629
4874
|
* name: 'California Sales Tax',
|
|
4630
4875
|
* rate: 7.25,
|
|
4631
4876
|
* country: 'US',
|
|
@@ -4711,7 +4956,7 @@ var BrainerceClient = class {
|
|
|
4711
4956
|
*
|
|
4712
4957
|
* @example
|
|
4713
4958
|
* ```typescript
|
|
4714
|
-
* const definition = await
|
|
4959
|
+
* const definition = await client.createMetafieldDefinition({
|
|
4715
4960
|
* name: 'Care Instructions',
|
|
4716
4961
|
* key: 'care_instructions',
|
|
4717
4962
|
* type: 'multi_line_text',
|
|
@@ -4758,7 +5003,7 @@ var BrainerceClient = class {
|
|
|
4758
5003
|
*
|
|
4759
5004
|
* @example
|
|
4760
5005
|
* ```typescript
|
|
4761
|
-
* const metafield = await
|
|
5006
|
+
* const metafield = await client.setProductMetafield('prod_123', 'def_456', {
|
|
4762
5007
|
* value: 'Machine wash cold, tumble dry low',
|
|
4763
5008
|
* });
|
|
4764
5009
|
* ```
|
|
@@ -4835,7 +5080,7 @@ var BrainerceClient = class {
|
|
|
4835
5080
|
*
|
|
4836
5081
|
* @example
|
|
4837
5082
|
* ```typescript
|
|
4838
|
-
* const { members, invitations } = await
|
|
5083
|
+
* const { members, invitations } = await client.getStoreTeam('store_id');
|
|
4839
5084
|
* ```
|
|
4840
5085
|
*/
|
|
4841
5086
|
async getStoreTeam(storeId) {
|
|
@@ -4847,7 +5092,7 @@ var BrainerceClient = class {
|
|
|
4847
5092
|
*
|
|
4848
5093
|
* @example
|
|
4849
5094
|
* ```typescript
|
|
4850
|
-
* const invitation = await
|
|
5095
|
+
* const invitation = await client.inviteStoreMember('store_id', {
|
|
4851
5096
|
* email: 'newmember@example.com',
|
|
4852
5097
|
* role: 'MANAGER', // 'MANAGER' | 'STAFF' | 'VIEWER'
|
|
4853
5098
|
* });
|
|
@@ -4867,10 +5112,10 @@ var BrainerceClient = class {
|
|
|
4867
5112
|
* @example
|
|
4868
5113
|
* ```typescript
|
|
4869
5114
|
* // Update role
|
|
4870
|
-
* await
|
|
5115
|
+
* await client.updateStoreMember('store_id', 'member_id', { role: 'MANAGER' });
|
|
4871
5116
|
*
|
|
4872
5117
|
* // Set custom permissions (overrides role defaults)
|
|
4873
|
-
* await
|
|
5118
|
+
* await client.updateStoreMember('store_id', 'member_id', {
|
|
4874
5119
|
* permissions: ['VIEW_PRODUCTS', 'VIEW_ORDERS', 'FULFILL_ORDERS'],
|
|
4875
5120
|
* });
|
|
4876
5121
|
* ```
|
|
@@ -4929,7 +5174,7 @@ var BrainerceClient = class {
|
|
|
4929
5174
|
*
|
|
4930
5175
|
* @example
|
|
4931
5176
|
* ```typescript
|
|
4932
|
-
* const stores = await
|
|
5177
|
+
* const stores = await client.getMyStores();
|
|
4933
5178
|
* // Returns stores from all accounts where user is owner or team member
|
|
4934
5179
|
* stores.forEach(store => {
|
|
4935
5180
|
* console.log(`${store.name} - ${store.role} (${store.context})`);
|
|
@@ -4945,7 +5190,7 @@ var BrainerceClient = class {
|
|
|
4945
5190
|
*
|
|
4946
5191
|
* @example
|
|
4947
5192
|
* ```typescript
|
|
4948
|
-
* const { role, permissions } = await
|
|
5193
|
+
* const { role, permissions } = await client.getMyStorePermissions('store_id');
|
|
4949
5194
|
* if (permissions.includes('MANAGE_TEAM')) {
|
|
4950
5195
|
* // Show team management UI
|
|
4951
5196
|
* }
|
|
@@ -4993,7 +5238,7 @@ var BrainerceClient = class {
|
|
|
4993
5238
|
*
|
|
4994
5239
|
* @example
|
|
4995
5240
|
* ```typescript
|
|
4996
|
-
* const template = await
|
|
5241
|
+
* const template = await client.createEmailTemplate({
|
|
4997
5242
|
* name: 'Order Confirmation',
|
|
4998
5243
|
* eventType: 'ORDER_CONFIRMATION',
|
|
4999
5244
|
* subject: 'Your order #{{orderNumber}} has been confirmed',
|
|
@@ -5105,7 +5350,7 @@ var BrainerceClient = class {
|
|
|
5105
5350
|
*
|
|
5106
5351
|
* @example
|
|
5107
5352
|
* ```typescript
|
|
5108
|
-
* const config = await
|
|
5353
|
+
* const config = await client.configureOAuthProvider({
|
|
5109
5354
|
* provider: 'GOOGLE',
|
|
5110
5355
|
* clientId: 'your-google-client-id',
|
|
5111
5356
|
* clientSecret: 'your-google-client-secret',
|
|
@@ -5145,6 +5390,7 @@ var BrainerceError = class extends Error {
|
|
|
5145
5390
|
};
|
|
5146
5391
|
|
|
5147
5392
|
// src/webhooks.ts
|
|
5393
|
+
import crypto from "crypto";
|
|
5148
5394
|
function verifyWebhook(payload, signature, secret) {
|
|
5149
5395
|
if (!signature || !secret) {
|
|
5150
5396
|
return false;
|
|
@@ -5154,12 +5400,6 @@ function verifyWebhook(payload, signature, secret) {
|
|
|
5154
5400
|
}
|
|
5155
5401
|
function verifyHmacSignature(payload, signature, secret) {
|
|
5156
5402
|
try {
|
|
5157
|
-
if (typeof globalThis.crypto === "undefined") {
|
|
5158
|
-
const crypto2 = __require("crypto");
|
|
5159
|
-
const expectedSignature2 = crypto2.createHmac("sha256", secret).update(payload).digest("hex");
|
|
5160
|
-
return timingSafeEqual(signature, expectedSignature2);
|
|
5161
|
-
}
|
|
5162
|
-
const crypto = __require("crypto");
|
|
5163
5403
|
const expectedSignature = crypto.createHmac("sha256", secret).update(payload).digest("hex");
|
|
5164
5404
|
return timingSafeEqual(signature, expectedSignature);
|
|
5165
5405
|
} catch (error) {
|
|
@@ -5385,15 +5625,9 @@ function isCouponApplicableToProduct(coupon, productId) {
|
|
|
5385
5625
|
}
|
|
5386
5626
|
return true;
|
|
5387
5627
|
}
|
|
5388
|
-
|
|
5389
|
-
// src/index.ts
|
|
5390
|
-
var OmniSyncClient = BrainerceClient;
|
|
5391
|
-
var OmniSyncError = BrainerceError;
|
|
5392
5628
|
export {
|
|
5393
5629
|
BrainerceClient,
|
|
5394
5630
|
BrainerceError,
|
|
5395
|
-
OmniSyncClient,
|
|
5396
|
-
OmniSyncError,
|
|
5397
5631
|
createWebhookHandler,
|
|
5398
5632
|
enableDevGuards,
|
|
5399
5633
|
formatPrice,
|