@viu/emporix-sdk-react 2.7.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hooks.cjs CHANGED
@@ -56,6 +56,36 @@ async function bootstrapCart(opts) {
56
56
  });
57
57
  }
58
58
 
59
+ // src/hooks/internal/customer-session-store.ts
60
+ var stores = /* @__PURE__ */ new WeakMap();
61
+ function getCustomerSessionStore(storage) {
62
+ const existing = stores.get(storage);
63
+ if (existing) return existing;
64
+ let state = {
65
+ token: storage.getCustomerToken(),
66
+ refreshToken: null,
67
+ saasToken: null
68
+ };
69
+ const listeners = /* @__PURE__ */ new Set();
70
+ const store = {
71
+ getSnapshot: () => state,
72
+ setState: (next) => {
73
+ const resolved = typeof next === "function" ? next(state) : next;
74
+ if (resolved === state) return;
75
+ state = resolved;
76
+ for (const listener of listeners) listener();
77
+ },
78
+ subscribe: (listener) => {
79
+ listeners.add(listener);
80
+ return () => {
81
+ listeners.delete(listener);
82
+ };
83
+ }
84
+ };
85
+ stores.set(storage, store);
86
+ return store;
87
+ }
88
+
59
89
  // src/hooks/use-customer-session.ts
60
90
  var EMPTY_SESSION = {
61
91
  token: null,
@@ -66,14 +96,12 @@ function useCustomerSession() {
66
96
  const { client, storage } = useEmporix();
67
97
  const qc = reactQuery.useQueryClient();
68
98
  const siteCtx = react.useContext(EmporixSiteContext);
69
- const [session, setSession] = react.useState(() => ({
70
- token: storage.getCustomerToken(),
71
- refreshToken: null,
72
- saasToken: null
73
- }));
99
+ const store = react.useMemo(() => getCustomerSessionStore(storage), [storage]);
100
+ const session = react.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
101
+ const setSession = store.setState;
74
102
  react.useEffect(() => {
75
103
  return storage.subscribe?.((t) => setSession((s) => ({ ...s, token: t })));
76
- }, [storage]);
104
+ }, [storage, setSession]);
77
105
  const meQuery = reactQuery.useQuery({
78
106
  queryKey: ["emporix", "customer", "me", { tenant: client.tenant, hasToken: session.token !== null }],
79
107
  enabled: session.token !== null,
@@ -107,7 +135,7 @@ function useCustomerSession() {
107
135
  await qc.invalidateQueries({ queryKey: ["emporix", "customer"], refetchType: "none" });
108
136
  await qc.invalidateQueries({ queryKey: ["emporix", "cart"], refetchType: "none" });
109
137
  },
110
- [client, storage, qc, siteCtx]
138
+ [client, storage, qc, siteCtx, setSession]
111
139
  );
112
140
  const signup = react.useCallback(
113
141
  async (input) => {
@@ -139,7 +167,7 @@ function useCustomerSession() {
139
167
  await qc.invalidateQueries({ queryKey: ["emporix", "customer"], refetchType: "none" });
140
168
  await qc.invalidateQueries({ queryKey: ["emporix", "cart"], refetchType: "none" });
141
169
  },
142
- [client, storage, qc, siteCtx]
170
+ [client, storage, qc, siteCtx, setSession]
143
171
  );
144
172
  const socialLogin = react.useCallback(
145
173
  async (input) => {
@@ -163,10 +191,11 @@ function useCustomerSession() {
163
191
  storage.setCustomerToken(null);
164
192
  storage.setRefreshToken(null);
165
193
  storage.setActiveLegalEntityId(null);
194
+ storage.setCartId(null);
166
195
  setSession(EMPTY_SESSION);
167
196
  qc.removeQueries({ queryKey: ["emporix", "customer"] });
168
197
  qc.removeQueries({ queryKey: ["emporix", "cart"] });
169
- }, [client, session.token, storage, qc]);
198
+ }, [client, session.token, storage, qc, setSession]);
170
199
  const refresh = react.useCallback(async () => {
171
200
  await meQuery.refetch();
172
201
  }, [meQuery]);
@@ -185,10 +214,11 @@ function useCustomerSession() {
185
214
  }));
186
215
  await qc.invalidateQueries({ queryKey: ["emporix", "customer"] });
187
216
  await qc.invalidateQueries({ queryKey: ["emporix", "cart"] });
188
- }, [client, storage, qc, session.refreshToken, session.saasToken]);
217
+ }, [client, storage, qc, session.refreshToken, session.saasToken, setSession]);
189
218
  return {
190
219
  customerToken: session.token,
191
220
  refreshToken: session.refreshToken,
221
+ saasToken: session.saasToken,
192
222
  customer: meQuery.data ?? null,
193
223
  isAuthenticated: session.token !== null,
194
224
  isLoading: meQuery.isLoading && session.token !== null,
@@ -345,6 +375,17 @@ function useProductSearch(query, params = {}, options = {}) {
345
375
  staleTime: PRODUCTS_STALE_TIME
346
376
  });
347
377
  }
378
+ function useProductNameSearch(term, params = {}, options = {}) {
379
+ const { client } = useEmporix();
380
+ const { ctx } = useReadAuth(options.auth);
381
+ const { siteCode } = useReadSite();
382
+ return reactQuery.useQuery({
383
+ queryKey: emporixKey("product-name-search", [term, params], { tenant: client.tenant, authKind: ctx.kind, siteCode }),
384
+ enabled: typeof term === "string" && term.trim() !== "",
385
+ queryFn: () => client.products.searchByName(term, params, ctx),
386
+ staleTime: PRODUCTS_STALE_TIME
387
+ });
388
+ }
348
389
  function useProductsByCodes(codes, options = {}) {
349
390
  const { client } = useEmporix();
350
391
  const { ctx } = useReadAuth(options.auth);
@@ -573,7 +614,12 @@ function useCartMutations(cartId) {
573
614
  if (c) qc.setQueryData(c.key, c.previous);
574
615
  },
575
616
  onSuccess: (cart, _v, c) => {
576
- if (c) qc.setQueryData(c.key, cart);
617
+ if (!c) return;
618
+ if (cart && Array.isArray(cart.items)) {
619
+ qc.setQueryData(c.key, cart);
620
+ } else {
621
+ void qc.invalidateQueries({ queryKey: c.key });
622
+ }
577
623
  }
578
624
  });
579
625
  }
@@ -592,7 +638,9 @@ function useCartMutations(cartId) {
592
638
  ]
593
639
  } : prev
594
640
  ),
595
- updateItem: make((id, v) => client.carts.updateItem(id, v.itemId, v.patch, ctx)),
641
+ updateItem: make(
642
+ (id, v) => client.carts.updateItem(id, v.itemId, v.patch, ctx, v.partial ? { partial: true } : {})
643
+ ),
596
644
  removeItem: make(
597
645
  (id, v) => client.carts.removeItem(id, v.itemId, ctx),
598
646
  (prev, v) => prev ? { ...prev, items: (prev.items ?? []).filter((i) => i.id !== v.itemId) } : prev
@@ -627,6 +675,14 @@ function useActiveCart(opts) {
627
675
  const { activeCompany } = useActiveCompany();
628
676
  const [cartId, setCartId] = react.useState(() => storage.getCartId());
629
677
  const effectiveLegalEntityId = opts?.legalEntityId ?? activeCompany?.id;
678
+ react.useEffect(() => {
679
+ if (!storage.subscribeAll) return;
680
+ return storage.subscribeAll((key) => {
681
+ if (key !== "cartId") return;
682
+ const next = storage.getCartId();
683
+ setCartId((prev) => prev === next ? prev : next);
684
+ });
685
+ }, [storage]);
630
686
  react.useEffect(() => {
631
687
  if (cartId !== null) return;
632
688
  if (!opts?.create) return;
@@ -1093,6 +1149,24 @@ function useDeleteLocation() {
1093
1149
  onSuccess: () => qc.invalidateQueries({ predicate: (q) => q.queryKey.includes("locations") })
1094
1150
  });
1095
1151
  }
1152
+ function useAddGroupMember() {
1153
+ const { client } = useEmporix();
1154
+ const resolveAuth = useCustomerAuthResolver();
1155
+ const qc = reactQuery.useQueryClient();
1156
+ return reactQuery.useMutation({
1157
+ mutationFn: ({ groupId, member }) => client.customerGroups.addMember(groupId, member, resolveAuth()),
1158
+ onSuccess: () => qc.invalidateQueries({ predicate: (q) => q.queryKey.includes("groups") })
1159
+ });
1160
+ }
1161
+ function useRemoveGroupMember() {
1162
+ const { client } = useEmporix();
1163
+ const resolveAuth = useCustomerAuthResolver();
1164
+ const qc = reactQuery.useQueryClient();
1165
+ return reactQuery.useMutation({
1166
+ mutationFn: ({ groupId, userId }) => client.customerGroups.removeMember(groupId, userId, resolveAuth()),
1167
+ onSuccess: () => qc.invalidateQueries({ predicate: (q) => q.queryKey.includes("groups") })
1168
+ });
1169
+ }
1096
1170
  function useCompanySwitcher() {
1097
1171
  const ctx = useActiveCompany();
1098
1172
  const switchFn = react.useCallback(
@@ -1228,11 +1302,23 @@ function useReorder() {
1228
1302
  });
1229
1303
  const cartId = storage.getCartId();
1230
1304
  if (!cartId) throw new Error("useReorder: no active cart id in storage");
1231
- if (order.items.length === 0) return { added: 0, errors: [] };
1232
- const batchBody = order.items.map((item) => ({
1233
- product: { id: item.productId },
1234
- quantity: item.quantity
1235
- }));
1305
+ const batchBody = (order.entries ?? []).map((entry) => {
1306
+ const p = entry.price;
1307
+ if (!entry.itemYrn || !p?.priceId || p.originalAmount === void 0 || p.effectiveAmount === void 0 || !p.currency) {
1308
+ return null;
1309
+ }
1310
+ return {
1311
+ itemYrn: entry.itemYrn,
1312
+ quantity: entry.orderedAmount ?? entry.amount,
1313
+ price: {
1314
+ priceId: p.priceId,
1315
+ originalAmount: p.originalAmount,
1316
+ effectiveAmount: p.effectiveAmount,
1317
+ currency: p.currency
1318
+ }
1319
+ };
1320
+ }).filter((x) => x !== null);
1321
+ if (batchBody.length === 0) return { added: 0, errors: [] };
1236
1322
  const res = await client.carts.addItemsBatch(cartId, batchBody, ctx);
1237
1323
  let added = 0;
1238
1324
  const errors = [];
@@ -1458,6 +1544,7 @@ function useUpdateApproval() {
1458
1544
  }
1459
1545
 
1460
1546
  exports.useActiveCart = useActiveCart;
1547
+ exports.useAddGroupMember = useAddGroupMember;
1461
1548
  exports.useAddToShoppingList = useAddToShoppingList;
1462
1549
  exports.useAddressMutations = useAddressMutations;
1463
1550
  exports.useApproval = useApproval;
@@ -1513,6 +1600,7 @@ exports.usePaymentModes = usePaymentModes;
1513
1600
  exports.useProduct = useProduct;
1514
1601
  exports.useProductByCode = useProductByCode;
1515
1602
  exports.useProductMedia = useProductMedia;
1603
+ exports.useProductNameSearch = useProductNameSearch;
1516
1604
  exports.useProductSearch = useProductSearch;
1517
1605
  exports.useProducts = useProducts;
1518
1606
  exports.useProductsByCodes = useProductsByCodes;
@@ -1523,6 +1611,7 @@ exports.useRedeemCoupon = useRedeemCoupon;
1523
1611
  exports.useRedeemOptions = useRedeemOptions;
1524
1612
  exports.useRedeemRewardPoints = useRedeemRewardPoints;
1525
1613
  exports.useRemoveFromShoppingList = useRemoveFromShoppingList;
1614
+ exports.useRemoveGroupMember = useRemoveGroupMember;
1526
1615
  exports.useReorder = useReorder;
1527
1616
  exports.useReturn = useReturn;
1528
1617
  exports.useSalesOrder = useSalesOrder;