@laconius/cart 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +24 -0
  3. package/lib/module/adapter.js +167 -0
  4. package/lib/module/adapter.js.map +1 -0
  5. package/lib/module/components.js +212 -0
  6. package/lib/module/components.js.map +1 -0
  7. package/lib/module/config.js +53 -0
  8. package/lib/module/config.js.map +1 -0
  9. package/lib/module/defaults.js +57 -0
  10. package/lib/module/defaults.js.map +1 -0
  11. package/lib/module/index.js +11 -0
  12. package/lib/module/index.js.map +1 -0
  13. package/lib/module/models.js +4 -0
  14. package/lib/module/models.js.map +1 -0
  15. package/lib/module/normalizer.js +36 -0
  16. package/lib/module/normalizer.js.map +1 -0
  17. package/lib/module/package.json +1 -0
  18. package/lib/module/queries.js +287 -0
  19. package/lib/module/queries.js.map +1 -0
  20. package/lib/module/store.js +42 -0
  21. package/lib/module/store.js.map +1 -0
  22. package/lib/module/translations.js +31 -0
  23. package/lib/module/translations.js.map +1 -0
  24. package/lib/typescript/package.json +1 -0
  25. package/lib/typescript/src/adapter.d.ts +25 -0
  26. package/lib/typescript/src/adapter.d.ts.map +1 -0
  27. package/lib/typescript/src/components.d.ts +49 -0
  28. package/lib/typescript/src/components.d.ts.map +1 -0
  29. package/lib/typescript/src/config.d.ts +57 -0
  30. package/lib/typescript/src/config.d.ts.map +1 -0
  31. package/lib/typescript/src/defaults.d.ts +16 -0
  32. package/lib/typescript/src/defaults.d.ts.map +1 -0
  33. package/lib/typescript/src/index.d.ts +10 -0
  34. package/lib/typescript/src/index.d.ts.map +1 -0
  35. package/lib/typescript/src/models.d.ts +122 -0
  36. package/lib/typescript/src/models.d.ts.map +1 -0
  37. package/lib/typescript/src/normalizer.d.ts +24 -0
  38. package/lib/typescript/src/normalizer.d.ts.map +1 -0
  39. package/lib/typescript/src/queries.d.ts +47 -0
  40. package/lib/typescript/src/queries.d.ts.map +1 -0
  41. package/lib/typescript/src/store.d.ts +25 -0
  42. package/lib/typescript/src/store.d.ts.map +1 -0
  43. package/lib/typescript/src/translations.d.ts +29 -0
  44. package/lib/typescript/src/translations.d.ts.map +1 -0
  45. package/package.json +78 -0
  46. package/src/adapter.ts +187 -0
  47. package/src/components.tsx +237 -0
  48. package/src/config.ts +81 -0
  49. package/src/defaults.tsx +53 -0
  50. package/src/index.ts +61 -0
  51. package/src/models.ts +142 -0
  52. package/src/normalizer.ts +39 -0
  53. package/src/queries.ts +288 -0
  54. package/src/store.ts +46 -0
  55. package/src/translations.ts +28 -0
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["models.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ import { normalizeImages } from '@laconius/core';
4
+
5
+ /** An entry as OCC answers it: the product's images are still a flat list. */
6
+
7
+ /**
8
+ * Reshapes every entry product's flat image list through core's `normalizeImages` — the same
9
+ * mechanism the product adapter uses ([chapter 08](../../../docs/spec/08-media.md)). URLs are
10
+ * not absolutised here: converters are pure, so the adapter absolutises the whole payload
11
+ * afterwards.
12
+ */
13
+ export function normalizeCartImages(source, target) {
14
+ const cart = target ?? {
15
+ ...source
16
+ };
17
+ if (source.entries) {
18
+ cart.entries = source.entries.map(entry => entry.product?.images ? {
19
+ ...entry,
20
+ product: {
21
+ ...entry.product,
22
+ images: normalizeImages(entry.product.images)
23
+ }
24
+ } : entry);
25
+ }
26
+ return cart;
27
+ }
28
+
29
+ /**
30
+ * Ported from `feature-libs/cart/base/core/utils/utils.ts`: an anonymous cart is addressed by
31
+ * its `guid`, a logged-in user's cart by its `code`.
32
+ */
33
+ export function getCartId(cart, userId) {
34
+ return (userId === 'anonymous' ? cart?.guid : cart?.code) ?? '';
35
+ }
36
+ //# sourceMappingURL=normalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["normalizeImages","normalizeCartImages","source","target","cart","entries","map","entry","product","images","getCartId","userId","guid","code"],"sourceRoot":"../../src","sources":["normalizer.ts"],"mappings":";;AAAA,SAASA,eAAe,QAAkC,gBAAgB;;AAI1E;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,mBAAmBA,CAACC,MAAe,EAAEC,MAAa,EAAQ;EACxE,MAAMC,IAAI,GAAGD,MAAM,IAAK;IAAE,GAAGD;EAAO,CAAqB;EACzD,IAAIA,MAAM,CAACG,OAAO,EAAE;IAClBD,IAAI,CAACC,OAAO,GAAGH,MAAM,CAACG,OAAO,CAACC,GAAG,CAAEC,KAAK,IACtCA,KAAK,CAACC,OAAO,EAAEC,MAAM,GAChB;MACC,GAAGF,KAAK;MACRC,OAAO,EAAE;QAAE,GAAGD,KAAK,CAACC,OAAO;QAAEC,MAAM,EAAET,eAAe,CAACO,KAAK,CAACC,OAAO,CAACC,MAAM;MAAE;IAC7E,CAAC,GACAF,KACP,CAAC;EACH;EACA,OAAOH,IAAI;AACb;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASM,SAASA,CAACN,IAAsB,EAAEO,MAAc,EAAU;EACxE,OAAO,CAACA,MAAM,KAAK,WAAW,GAAGP,IAAI,EAAEQ,IAAI,GAAGR,IAAI,EAAES,IAAI,KAAK,EAAE;AACjE","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+
3
+ import { LaconiusHttpError, getRuntime, laconiusQueryKey, useIsLoggedIn } from '@laconius/core';
4
+ import { queryOptions, useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
5
+ import { cartAdapter } from "./adapter.js";
6
+ import { getCartId } from "./normalizer.js";
7
+ import { useActiveCartIdStore } from "./store.js";
8
+
9
+ /**
10
+ * `queryOptions` factory, so an app can `prefetchQuery` the cart without forking the library.
11
+ * The key is `['laconius','cart',{ctx},cartId]` — the context object carries the user, which is
12
+ * what keeps an anonymous cart and a user cart apart in the cache.
13
+ */
14
+ export const cartQueries = {
15
+ detail: cartId => queryOptions({
16
+ queryKey: laconiusQueryKey('cart', cartId),
17
+ /** Prices and stock go stale the moment someone else buys ([chapter 04](../../../docs/spec/04-state.md)). */
18
+ staleTime: 0,
19
+ queryFn: async () => {
20
+ const runtime = getRuntime();
21
+ try {
22
+ const cart = await cartAdapter(runtime).load(runtime, cartId);
23
+ // `current` resolves to a real id; keep the store on it so mutations address it.
24
+ const id = getCartId(cart, runtime.auth.getUserId());
25
+ const store = useActiveCartIdStore.getState();
26
+ if (id && id !== store.cartId) store.setCartId(id);
27
+ return cart;
28
+ } catch (error) {
29
+ // A dead persisted id silently resets to an empty cart; retry already skips 4xx.
30
+ if (error instanceof LaconiusHttpError && error.status === 404) {
31
+ useActiveCartIdStore.getState().clearCartId();
32
+ return {};
33
+ }
34
+ throw error;
35
+ }
36
+ }
37
+ })
38
+ };
39
+
40
+ /**
41
+ * The active cart. Empty (no request) until an add creates one — the anonymous cart is lazy —
42
+ * except for a logged-in user with no stored id, whose latest cart OCC addresses as the literal
43
+ * `current`.
44
+ */
45
+ export function useActiveCart() {
46
+ const storedId = useActiveCartIdStore(state => state.cartId);
47
+ const loggedIn = useIsLoggedIn();
48
+ const cartId = storedId ?? (loggedIn ? 'current' : undefined);
49
+ return useQuery({
50
+ ...cartQueries.detail(cartId ?? ''),
51
+ enabled: Boolean(cartId)
52
+ });
53
+ }
54
+
55
+ /** Writes the returned cart under the returned id — never the closed-over one. */
56
+ function writeCart(queryClient, result) {
57
+ queryClient.setQueryData(laconiusQueryKey('cart', result.cartId), result.cart);
58
+ }
59
+ function requireCartId() {
60
+ const cartId = useActiveCartIdStore.getState().cartId;
61
+ if (!cartId) {
62
+ throw new Error('[laconius] No active cart. Add an item before mutating entries.');
63
+ }
64
+ return cartId;
65
+ }
66
+
67
+ /**
68
+ * Not optimistic: stock and price come from the server, and rolling back a `lowStock` result is
69
+ * ugly ([chapter 04](../../../docs/spec/04-state.md)). OCC answers the POST with a
70
+ * `CartModification`, so one follow-up read is what lets `setQueryData` replace invalidation.
71
+ */
72
+ export function useAddToCart() {
73
+ const queryClient = useQueryClient();
74
+ return useMutation({
75
+ mutationFn: async ({
76
+ productCode,
77
+ quantity = 1
78
+ }) => {
79
+ const runtime = getRuntime();
80
+ const adapter = cartAdapter(runtime);
81
+ let cartId = useActiveCartIdStore.getState().cartId;
82
+ if (!cartId) {
83
+ // Lazy: created inside the first add, never eagerly at mount.
84
+ const created = await adapter.create(runtime);
85
+ cartId = getCartId(created, runtime.auth.getUserId());
86
+ useActiveCartIdStore.getState().setCartId(cartId);
87
+ }
88
+ const modification = await adapter.addEntry(runtime, cartId, productCode, quantity);
89
+ const cart = await adapter.load(runtime, cartId);
90
+ return {
91
+ cart,
92
+ cartId,
93
+ modification
94
+ };
95
+ },
96
+ onSuccess: result => writeCart(queryClient, result)
97
+ });
98
+ }
99
+ async function snapshotEntries(queryClient, mutate) {
100
+ const cartId = useActiveCartIdStore.getState().cartId;
101
+ if (!cartId) return {};
102
+ const queryKey = laconiusQueryKey('cart', cartId);
103
+ await queryClient.cancelQueries({
104
+ queryKey
105
+ });
106
+ const previous = queryClient.getQueryData(queryKey);
107
+ if (previous?.entries) {
108
+ queryClient.setQueryData(queryKey, {
109
+ ...previous,
110
+ entries: mutate(previous.entries)
111
+ });
112
+ }
113
+ return {
114
+ previous,
115
+ queryKey
116
+ };
117
+ }
118
+ function rollback(queryClient, snapshot) {
119
+ if (snapshot?.previous && snapshot.queryKey) {
120
+ queryClient.setQueryData(snapshot.queryKey, snapshot.previous);
121
+ }
122
+ }
123
+
124
+ /** Optimistic: the quantity flips immediately, the totals arrive with the response. */
125
+ export function useUpdateCartEntry() {
126
+ const queryClient = useQueryClient();
127
+ return useMutation({
128
+ mutationFn: async ({
129
+ entryNumber,
130
+ quantity
131
+ }) => {
132
+ const runtime = getRuntime();
133
+ const adapter = cartAdapter(runtime);
134
+ const cartId = requireCartId();
135
+ const modification = await adapter.updateEntry(runtime, cartId, entryNumber, quantity);
136
+ const cart = await adapter.load(runtime, cartId);
137
+ return {
138
+ cart,
139
+ cartId,
140
+ modification
141
+ };
142
+ },
143
+ onMutate: ({
144
+ entryNumber,
145
+ quantity
146
+ }) => snapshotEntries(queryClient, entries => entries.map(entry => entry.entryNumber === entryNumber ? {
147
+ ...entry,
148
+ quantity
149
+ } : entry)),
150
+ onError: (_error, _input, snapshot) => rollback(queryClient, snapshot),
151
+ onSuccess: result => writeCart(queryClient, result)
152
+ });
153
+ }
154
+
155
+ /** Optimistic: the row disappears immediately, the totals arrive with the response. */
156
+ export function useRemoveCartEntry() {
157
+ const queryClient = useQueryClient();
158
+ return useMutation({
159
+ mutationFn: async ({
160
+ entryNumber
161
+ }) => {
162
+ const runtime = getRuntime();
163
+ const adapter = cartAdapter(runtime);
164
+ const cartId = requireCartId();
165
+ await adapter.removeEntry(runtime, cartId, entryNumber);
166
+ const cart = await adapter.load(runtime, cartId);
167
+ return {
168
+ cart,
169
+ cartId
170
+ };
171
+ },
172
+ onMutate: ({
173
+ entryNumber
174
+ }) => snapshotEntries(queryClient, entries => entries.filter(entry => entry.entryNumber !== entryNumber)),
175
+ onError: (_error, _input, snapshot) => rollback(queryClient, snapshot),
176
+ onSuccess: result => writeCart(queryClient, result)
177
+ });
178
+ }
179
+ export function useApplyVoucher() {
180
+ const queryClient = useQueryClient();
181
+ return useMutation({
182
+ mutationFn: async voucherId => {
183
+ const runtime = getRuntime();
184
+ const adapter = cartAdapter(runtime);
185
+ const cartId = requireCartId();
186
+ await adapter.applyVoucher(runtime, cartId, voucherId);
187
+ const cart = await adapter.load(runtime, cartId);
188
+ return {
189
+ cart,
190
+ cartId
191
+ };
192
+ },
193
+ onSuccess: result => writeCart(queryClient, result)
194
+ });
195
+ }
196
+ export function useRemoveVoucher() {
197
+ const queryClient = useQueryClient();
198
+ return useMutation({
199
+ mutationFn: async voucherId => {
200
+ const runtime = getRuntime();
201
+ const adapter = cartAdapter(runtime);
202
+ const cartId = requireCartId();
203
+ await adapter.removeVoucher(runtime, cartId, voucherId);
204
+ const cart = await adapter.load(runtime, cartId);
205
+ return {
206
+ cart,
207
+ cartId
208
+ };
209
+ },
210
+ onSuccess: result => writeCart(queryClient, result)
211
+ });
212
+ }
213
+
214
+ /**
215
+ * The anonymous cart cannot be fetched once the `Authorization` header exists, so the entries
216
+ * come from the cache snapshot — the "read before starting the flow" of
217
+ * [chapter 05](../../../docs/spec/05-auth-session.md). The query key's context object carries
218
+ * the user, which is what keeps that snapshot addressable after login.
219
+ */
220
+ function findAnonymousCart(queryClient) {
221
+ for (const [key, data] of queryClient.getQueriesData({
222
+ queryKey: ['laconius', 'cart']
223
+ })) {
224
+ const context = key[2];
225
+ if (context?.user === 'anonymous' && data?.entries?.length) return data;
226
+ }
227
+ return undefined;
228
+ }
229
+
230
+ /**
231
+ * Persist-then-replay, never the native merge — the backend rejects a native merge after a
232
+ * redirect login, and every React Native login is one
233
+ * ([chapter 05](../../../docs/spec/05-auth-session.md)). Call it after a successful login;
234
+ * `useLogin()` takes an `onLoggedIn` callback and the template joins them.
235
+ */
236
+ export function useMergeAnonymousCart() {
237
+ const queryClient = useQueryClient();
238
+ return useMutation({
239
+ mutationFn: async () => {
240
+ const runtime = getRuntime();
241
+ const adapter = cartAdapter(runtime);
242
+ const entries = findAnonymousCart(queryClient)?.entries ?? [];
243
+
244
+ // The anonymous id belonged to the previous session.
245
+ const store = useActiveCartIdStore.getState();
246
+ store.clearCartId();
247
+ if (entries.length === 0) return {
248
+ replayed: [],
249
+ failed: []
250
+ };
251
+ let cart;
252
+ try {
253
+ cart = await adapter.load(runtime, 'current');
254
+ } catch {
255
+ cart = await adapter.create(runtime);
256
+ }
257
+ const cartId = getCartId(cart, runtime.auth.getUserId());
258
+ store.setCartId(cartId);
259
+ const replayed = [];
260
+ const failed = [];
261
+ for (const entry of entries) {
262
+ const productCode = entry.product?.code;
263
+ if (!productCode) continue;
264
+ try {
265
+ await adapter.addEntry(runtime, cartId, productCode, entry.quantity ?? 1);
266
+ replayed.push(entry);
267
+ } catch (error) {
268
+ failed.push({
269
+ entry,
270
+ error
271
+ });
272
+ }
273
+ }
274
+ return {
275
+ replayed,
276
+ failed
277
+ };
278
+ },
279
+ // Login invalidates everything: customer-group pricing depends on the user.
280
+ onSuccess: () => {
281
+ void queryClient.invalidateQueries({
282
+ queryKey: ['laconius']
283
+ });
284
+ }
285
+ });
286
+ }
287
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["LaconiusHttpError","getRuntime","laconiusQueryKey","useIsLoggedIn","queryOptions","useMutation","useQuery","useQueryClient","cartAdapter","getCartId","useActiveCartIdStore","cartQueries","detail","cartId","queryKey","staleTime","queryFn","runtime","cart","load","id","auth","getUserId","store","getState","setCartId","error","status","clearCartId","useActiveCart","storedId","state","loggedIn","undefined","enabled","Boolean","writeCart","queryClient","result","setQueryData","requireCartId","Error","useAddToCart","mutationFn","productCode","quantity","adapter","created","create","modification","addEntry","onSuccess","snapshotEntries","mutate","cancelQueries","previous","getQueryData","entries","rollback","snapshot","useUpdateCartEntry","entryNumber","updateEntry","onMutate","map","entry","onError","_error","_input","useRemoveCartEntry","removeEntry","filter","useApplyVoucher","voucherId","applyVoucher","useRemoveVoucher","removeVoucher","findAnonymousCart","key","data","getQueriesData","context","user","length","useMergeAnonymousCart","replayed","failed","product","code","push","invalidateQueries"],"sourceRoot":"../../src","sources":["queries.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ import { useSessionStore } from '@laconius/core';
4
+ import AsyncStorage from 'expo-sqlite/kv-store';
5
+ import { create } from 'zustand';
6
+ import { createJSONStorage, persist } from 'zustand/middleware';
7
+ /**
8
+ * The only client-side cart state: the entity itself is server state in TanStack Query
9
+ * ([chapter 04](../../../docs/spec/04-state.md)). Persisted, so the id survives a restart and
10
+ * OCC reprices; a dead id resets itself through the 404 path in the query.
11
+ */
12
+ export const useActiveCartIdStore = create()(persist(set => ({
13
+ setCartId: cartId => set({
14
+ cartId
15
+ }),
16
+ clearCartId: () => set({
17
+ cartId: undefined
18
+ })
19
+ }), {
20
+ name: 'laconius.activeCartId',
21
+ storage: createJSONStorage(() => AsyncStorage),
22
+ partialize: state => ({
23
+ cartId: state.cartId
24
+ })
25
+ }));
26
+
27
+ /**
28
+ * Logout drops the id — it belonged to the previous session ([chapter 04](../../../docs/spec/04-state.md)).
29
+ * Core cannot do it (no `core -> cart` edge exists), so the store watches the session: an access
30
+ * token disappearing is a session ending, whoever caused it. Login is the other direction and is
31
+ * handled by `useMergeAnonymousCart`.
32
+ *
33
+ * This runs at import time, which is why `package.json` lists this module under `sideEffects`
34
+ * rather than declaring the package side-effect-free: without that entry a bundler may drop the
35
+ * module when a consumer imports nothing from it, and the id would outlive the session.
36
+ */
37
+ useSessionStore.subscribe((state, previous) => {
38
+ if (previous.accessToken && !state.accessToken) {
39
+ useActiveCartIdStore.getState().clearCartId();
40
+ }
41
+ });
42
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useSessionStore","AsyncStorage","create","createJSONStorage","persist","useActiveCartIdStore","set","setCartId","cartId","clearCartId","undefined","name","storage","partialize","state","subscribe","previous","accessToken","getState"],"sourceRoot":"../../src","sources":["store.ts"],"mappings":";;AAAA,SAASA,eAAe,QAAQ,gBAAgB;AAChD,OAAOC,YAAY,MAAM,sBAAsB;AAC/C,SAASC,MAAM,QAAQ,SAAS;AAChC,SAASC,iBAAiB,EAAEC,OAAO,QAAQ,oBAAoB;AAS/D;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,oBAAoB,GAAGH,MAAM,CAAkB,CAAC,CAC3DE,OAAO,CACJE,GAAG,KAAM;EACRC,SAAS,EAAGC,MAAM,IAAKF,GAAG,CAAC;IAAEE;EAAO,CAAC,CAAC;EACtCC,WAAW,EAAEA,CAAA,KAAMH,GAAG,CAAC;IAAEE,MAAM,EAAEE;EAAU,CAAC;AAC9C,CAAC,CAAC,EACF;EACEC,IAAI,EAAE,uBAAuB;EAC7BC,OAAO,EAAET,iBAAiB,CAAC,MAAMF,YAAY,CAAC;EAC9CY,UAAU,EAAGC,KAAK,KAAM;IAAEN,MAAM,EAAEM,KAAK,CAACN;EAAO,CAAC;AAClD,CACF,CACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACAR,eAAe,CAACe,SAAS,CAAC,CAACD,KAAK,EAAEE,QAAQ,KAAK;EAC7C,IAAIA,QAAQ,CAACC,WAAW,IAAI,CAACH,KAAK,CAACG,WAAW,EAAE;IAC9CZ,oBAAoB,CAACa,QAAQ,CAAC,CAAC,CAACT,WAAW,CAAC,CAAC;EAC/C;AACF,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ /** English strings for the defaults in this package. Other languages are the app's. */
4
+ export const defaultCartTranslations = {
5
+ en: {
6
+ cart: {
7
+ title: 'Cart',
8
+ addToCart: 'Add to cart',
9
+ itemAdded: 'Added to cart.',
10
+ itemRemoved: 'Removed from cart.',
11
+ quantityUpdated: 'Quantity updated.',
12
+ remove: 'Remove',
13
+ removeItem: 'Remove {{name}} from cart',
14
+ empty: 'Your cart is empty.',
15
+ entryCount_one: '{{count}} item',
16
+ entryCount_other: '{{count}} items',
17
+ subtotal: 'Subtotal',
18
+ discounts: 'Discounts',
19
+ delivery: 'Delivery',
20
+ tax: 'Tax',
21
+ total: 'Total',
22
+ voucher: {
23
+ placeholder: 'Voucher code',
24
+ apply: 'Apply',
25
+ applied: 'Applied vouchers',
26
+ remove: 'Remove voucher {{code}}'
27
+ }
28
+ }
29
+ }
30
+ };
31
+ //# sourceMappingURL=translations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["defaultCartTranslations","en","cart","title","addToCart","itemAdded","itemRemoved","quantityUpdated","remove","removeItem","empty","entryCount_one","entryCount_other","subtotal","discounts","delivery","tax","total","voucher","placeholder","apply","applied"],"sourceRoot":"../../src","sources":["translations.ts"],"mappings":";;AAAA;AACA,OAAO,MAAMA,uBAAuB,GAAG;EACrCC,EAAE,EAAE;IACFC,IAAI,EAAE;MACJC,KAAK,EAAE,MAAM;MACbC,SAAS,EAAE,aAAa;MACxBC,SAAS,EAAE,gBAAgB;MAC3BC,WAAW,EAAE,oBAAoB;MACjCC,eAAe,EAAE,mBAAmB;MACpCC,MAAM,EAAE,QAAQ;MAChBC,UAAU,EAAE,2BAA2B;MACvCC,KAAK,EAAE,qBAAqB;MAC5BC,cAAc,EAAE,gBAAgB;MAChCC,gBAAgB,EAAE,iBAAiB;MACnCC,QAAQ,EAAE,UAAU;MACpBC,SAAS,EAAE,WAAW;MACtBC,QAAQ,EAAE,UAAU;MACpBC,GAAG,EAAE,KAAK;MACVC,KAAK,EAAE,OAAO;MACdC,OAAO,EAAE;QACPC,WAAW,EAAE,cAAc;QAC3BC,KAAK,EAAE,OAAO;QACdC,OAAO,EAAE,kBAAkB;QAC3Bb,MAAM,EAAE;MACV;IACF;EACF;AACF,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,25 @@
1
+ import { type Converter, type LaconiusRuntime } from '@laconius/core';
2
+ import type { Cart, CartModification, CartModificationList } from './models.js';
3
+ import { type OccCart } from './normalizer.js';
4
+ export type CartAdapter = {
5
+ load(runtime: LaconiusRuntime, cartId: string): Promise<Cart>;
6
+ loadAll(runtime: LaconiusRuntime): Promise<Cart[]>;
7
+ create(runtime: LaconiusRuntime, options?: {
8
+ oldCartId?: string;
9
+ toMergeCartGuid?: string;
10
+ }): Promise<Cart>;
11
+ remove(runtime: LaconiusRuntime, cartId: string): Promise<void>;
12
+ addEntry(runtime: LaconiusRuntime, cartId: string, productCode: string, quantity: number): Promise<CartModification>;
13
+ updateEntry(runtime: LaconiusRuntime, cartId: string, entryNumber: number, quantity: number): Promise<CartModification>;
14
+ removeEntry(runtime: LaconiusRuntime, cartId: string, entryNumber: number): Promise<void>;
15
+ applyVoucher(runtime: LaconiusRuntime, cartId: string, voucherId: string): Promise<void>;
16
+ removeVoucher(runtime: LaconiusRuntime, cartId: string, voucherId: string): Promise<void>;
17
+ validate(runtime: LaconiusRuntime, cartId: string): Promise<CartModificationList>;
18
+ };
19
+ export declare const defaultCartAdapter: CartAdapter;
20
+ export declare function cartAdapter(runtime: LaconiusRuntime): CartAdapter;
21
+ export declare const defaultCartConverters: {
22
+ cart: Converter<OccCart, Cart>[];
23
+ cartModification: Converter<unknown, CartModification>[];
24
+ };
25
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAU,CAAC;AAC7E,OAAO,EAAuB,KAAK,OAAO,EAAE,MAAM,iBAAc,CAAC;AAEjE,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,CACJ,OAAO,EAAE,eAAe,EACxB,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,GACzD,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,QAAQ,CACN,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7B,WAAW,CACT,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7B,WAAW,CACT,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,YAAY,CACV,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,aAAa,CACX,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACnF,CAAC;AAeF,eAAO,MAAM,kBAAkB,EAAE,WAoHhC,CAAC;AAEF,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,WAAW,CAEjE;AAED,eAAO,MAAM,qBAAqB;UACD,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;sBACjC,SAAS,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE;CAC/D,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { type ImageStyle, type StyleProp, type TextStyle, type ViewStyle } from 'react-native';
2
+ import type { Cart, OrderEntry } from './models.js';
3
+ export type AddToCartButtonProps = {
4
+ productCode: string;
5
+ quantity?: number;
6
+ disabled?: boolean;
7
+ /** Root style. */
8
+ style?: StyleProp<ViewStyle>;
9
+ /** Named inner parts — public, versioned API. */
10
+ styles?: {
11
+ container?: StyleProp<ViewStyle>;
12
+ error?: StyleProp<TextStyle>;
13
+ };
14
+ };
15
+ /**
16
+ * The one component with no UI hook: its logic *is* the mutation
17
+ * ([chapter 07](../../../docs/spec/07-ui-kit.md)). An OCC business error — out of stock, most
18
+ * likely — reaches the user as a translated sentence, per hook, with no message bus.
19
+ */
20
+ export declare function AddToCartButton({ productCode, quantity, disabled, style, styles: parts, }: AddToCartButtonProps): import("react").JSX.Element;
21
+ export type CartEntryRowProps = {
22
+ entry: OrderEntry;
23
+ /** Root style. */
24
+ style?: StyleProp<ViewStyle>;
25
+ styles?: {
26
+ container?: StyleProp<ViewStyle>;
27
+ media?: StyleProp<ImageStyle>;
28
+ info?: StyleProp<ViewStyle>;
29
+ title?: StyleProp<TextStyle>;
30
+ price?: StyleProp<TextStyle>;
31
+ error?: StyleProp<TextStyle>;
32
+ };
33
+ };
34
+ /** Quantity and remove, one mutation hook each so each keeps its own `isPending` and `error`. */
35
+ export declare function CartEntryRow({ entry, style, styles: parts }: CartEntryRowProps): import("react").JSX.Element;
36
+ export type CartTotalsProps = {
37
+ cart?: Cart;
38
+ /** Root style. */
39
+ style?: StyleProp<ViewStyle>;
40
+ styles?: {
41
+ container?: StyleProp<ViewStyle>;
42
+ row?: StyleProp<ViewStyle>;
43
+ label?: StyleProp<TextStyle>;
44
+ value?: StyleProp<TextStyle>;
45
+ };
46
+ };
47
+ /** Pure component: the cart arrives as a prop, exactly like `Price` ([chapter 07](../../../docs/spec/07-ui-kit.md)). */
48
+ export declare function CartTotals({ cart, style, styles: parts }: CartTotalsProps): import("react").JSX.Element | null;
49
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/components.tsx"],"names":[],"mappings":"AAYA,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,aAAU,CAAC;AAGjD,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,iDAAiD;IACjD,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QACjC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,WAAW,EACX,QAAY,EACZ,QAAgB,EAChB,KAAK,EACL,MAAM,EAAE,KAAK,GACd,EAAE,oBAAoB,+BAgCtB;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,UAAU,CAAC;IAClB,kBAAkB;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QACjC,KAAK,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC5B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,iBAAiB,+BAiE9E;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,kBAAkB;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QACjC,GAAG,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC3B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF,wHAAwH;AACxH,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe,sCAsCzE"}
@@ -0,0 +1,57 @@
1
+ import type { LaconiusConfigChunk } from '@laconius/core';
2
+ import type { CmsComponentMapping } from '@laconius/cms';
3
+ import { type CartAdapter } from './adapter.js';
4
+ declare module '@laconius/ui' {
5
+ /** The cart components, replaceable through the typed UI registry. */
6
+ interface LaconiusUiComponents {
7
+ AddToCartButton: unknown;
8
+ CartEntryRow: unknown;
9
+ CartTotals: unknown;
10
+ }
11
+ }
12
+ declare module '@laconius/core' {
13
+ interface LaconiusEndpoints {
14
+ carts: string | Record<string, string>;
15
+ cart: string | Record<string, string>;
16
+ createCart: string | Record<string, string>;
17
+ deleteCart: string | Record<string, string>;
18
+ addEntries: string | Record<string, string>;
19
+ updateEntries: string | Record<string, string>;
20
+ removeEntries: string | Record<string, string>;
21
+ cartApplyVoucher: string | Record<string, string>;
22
+ cartRemoveVoucher: string | Record<string, string>;
23
+ cartVoucher: string | Record<string, string>;
24
+ validate: string | Record<string, string>;
25
+ }
26
+ interface LaconiusConverters {
27
+ cart: unknown;
28
+ cartModification: unknown;
29
+ }
30
+ interface LaconiusAdapters {
31
+ cart: CartAdapter;
32
+ }
33
+ }
34
+ export declare const defaultCartEndpoints: {
35
+ carts: string;
36
+ cart: string;
37
+ createCart: string;
38
+ deleteCart: string;
39
+ addEntries: string;
40
+ updateEntries: string;
41
+ removeEntries: string;
42
+ cartApplyVoucher: string;
43
+ cartRemoveVoucher: string;
44
+ /** The legacy pair, used when `capabilities.jsonVouchers` is off. */
45
+ cartVoucher: {
46
+ default: string;
47
+ delete: string;
48
+ };
49
+ validate: string;
50
+ };
51
+ /**
52
+ * The content types that read cart data ship here rather than in `@laconius/cms`, which keeps
53
+ * the dependency arrow `cart -> cms` ([chapter 01](../../../docs/spec/01-packages.md)).
54
+ */
55
+ export declare const defaultCartCmsComponents: Record<string, CmsComponentMapping>;
56
+ export declare const defaultCartConfig: LaconiusConfigChunk;
57
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAyB,KAAK,WAAW,EAAE,MAAM,cAAW,CAAC;AAIpE,OAAO,QAAQ,cAAc,CAAC;IAC5B,sEAAsE;IACtE,UAAU,oBAAoB;QAC5B,eAAe,EAAE,OAAO,CAAC;QACzB,YAAY,EAAE,OAAO,CAAC;QACtB,UAAU,EAAE,OAAO,CAAC;KACrB;CACF;AAED,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,iBAAiB;QACzB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACvC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5C,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5C,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5C,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/C,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/C,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClD,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnD,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7C,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC3C;IAED,UAAU,kBAAkB;QAC1B,IAAI,EAAE,OAAO,CAAC;QACd,gBAAgB,EAAE,OAAO,CAAC;KAC3B;IAED,UAAU,gBAAgB;QACxB,IAAI,EAAE,WAAW,CAAC;KACnB;CACF;AAUD,eAAO,MAAM,oBAAoB;;;;;;;;;;IAU/B,qEAAqE;;;;;;CAMtE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAExE,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,mBAK/B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type CmsComponent } from '@laconius/cms';
2
+ /** Spartacus' `CmsMiniCartComponent` fields; the lightbox banner is web furniture and dropped. */
3
+ export interface CmsMiniCartData extends CmsComponent {
4
+ title?: string;
5
+ shownProductCount?: string;
6
+ /** `TOTAL` or `SUBTOTAL`. */
7
+ totalDisplay?: string;
8
+ }
9
+ /**
10
+ * Item count and total. It ships here rather than in `@laconius/cms` because it reads cart data,
11
+ * which is what keeps the dependency arrow `cart -> cms`
12
+ * ([chapter 01](../../../docs/spec/01-packages.md)) — the same reason Spartacus ships
13
+ * `MiniCartComponent` from `feature-libs/cart/base/components/mini-cart/`.
14
+ */
15
+ export declare function CmsMiniCart(): import("react").JSX.Element;
16
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../src/defaults.tsx"],"names":[],"mappings":"AACA,OAAO,EAAuC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAMvF,kGAAkG;AAClG,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,gCAqB1B"}
@@ -0,0 +1,10 @@
1
+ export type { AddToCartInput, Cart, CartMergeFailure, CartMergeResult, CartModification, CartModificationList, CartMutationResult, CartValidationStatusCode, DeliveryMode, OrderEntry, PromotionOrderEntryConsumed, PromotionResult, Voucher, } from './models.js';
2
+ export { getCartId, normalizeCartImages, type OccCart, type OccOrderEntry, } from './normalizer.js';
3
+ export { cartAdapter, defaultCartAdapter, defaultCartConverters, type CartAdapter, } from './adapter.js';
4
+ export { cartQueries, useActiveCart, useAddToCart, useApplyVoucher, useMergeAnonymousCart, useRemoveCartEntry, useRemoveVoucher, useUpdateCartEntry, } from './queries.js';
5
+ export { useActiveCartIdStore, type ActiveCartState } from './store.js';
6
+ export { AddToCartButton, CartEntryRow, CartTotals, type AddToCartButtonProps, type CartEntryRowProps, type CartTotalsProps, } from './components.js';
7
+ export { CmsMiniCart, type CmsMiniCartData } from './defaults.js';
8
+ export { defaultCartCmsComponents, defaultCartConfig, defaultCartEndpoints, } from './config.js';
9
+ export { defaultCartTranslations } from './translations.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,IAAI,EACJ,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,YAAY,EACZ,UAAU,EACV,2BAA2B,EAC3B,eAAe,EACf,OAAO,GACR,MAAM,aAAU,CAAC;AAElB,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,KAAK,OAAO,EACZ,KAAK,aAAa,GACnB,MAAM,iBAAc,CAAC;AAEtB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,WAAW,GACjB,MAAM,cAAW,CAAC;AAEnB,OAAO,EACL,WAAW,EACX,aAAa,EACb,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,cAAW,CAAC;AAEnB,OAAO,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAS,CAAC;AAErE,OAAO,EACL,eAAe,EACf,YAAY,EACZ,UAAU,EACV,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,iBAAc,CAAC;AAEtB,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,eAAY,CAAC;AAE/D,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,aAAU,CAAC;AAElB,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAgB,CAAC"}