@doswiftly/storefront-sdk 17.0.0 → 18.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.
- package/CHANGELOG.md +976 -0
- package/README.md +47 -4
- package/dist/core/auth/auth-client.d.ts +39 -3
- package/dist/core/auth/auth-client.d.ts.map +1 -1
- package/dist/core/auth/auth-client.js +51 -3
- package/dist/core/auth/cookie-config.d.ts +52 -3
- package/dist/core/auth/cookie-config.d.ts.map +1 -1
- package/dist/core/auth/cookie-config.js +60 -6
- package/dist/core/auth/handlers.d.ts +46 -0
- package/dist/core/auth/handlers.d.ts.map +1 -1
- package/dist/core/auth/handlers.js +9 -2
- package/dist/core/auth/session-events.d.ts +38 -0
- package/dist/core/auth/session-events.d.ts.map +1 -0
- package/dist/core/auth/session-events.js +35 -0
- package/dist/core/cart/cart-recovery.d.ts +23 -0
- package/dist/core/cart/cart-recovery.d.ts.map +1 -1
- package/dist/core/cart/cart-recovery.js +20 -3
- package/dist/core/cart/types.d.ts +2 -1
- package/dist/core/cart/types.d.ts.map +1 -1
- package/dist/core/cart/types.js +7 -1
- package/dist/core/client/create-client.d.ts.map +1 -1
- package/dist/core/client/create-client.js +7 -3
- package/dist/core/client/execute.d.ts +29 -3
- package/dist/core/client/execute.d.ts.map +1 -1
- package/dist/core/client/execute.js +174 -3
- package/dist/core/client/types.d.ts +50 -2
- package/dist/core/client/types.d.ts.map +1 -1
- package/dist/core/errors.d.ts +6 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +6 -0
- package/dist/core/generated/operation-types.d.ts +838 -221
- package/dist/core/generated/operation-types.d.ts.map +1 -1
- package/dist/core/generated/operation-types.js +560 -1
- package/dist/core/index.d.ts +6 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +12 -2
- package/dist/core/middleware/session-retry.d.ts +47 -0
- package/dist/core/middleware/session-retry.d.ts.map +1 -0
- package/dist/core/middleware/session-retry.js +71 -0
- package/dist/core/operations/auth.d.ts.map +1 -1
- package/dist/core/operations/auth.js +1 -0
- package/dist/core/operations/cart.d.ts.map +1 -1
- package/dist/core/operations/cart.js +15 -11
- package/dist/react/components/PaymentInstrumentSection.d.ts.map +1 -1
- package/dist/react/components/PaymentInstrumentSection.js +4 -4
- package/dist/react/components/PaymentInstrumentTile.d.ts +7 -7
- package/dist/react/components/PaymentInstrumentTile.d.ts.map +1 -1
- package/dist/react/components/PaymentInstrumentTile.js +4 -3
- package/dist/react/hooks/use-cart-manager.d.ts +133 -13
- package/dist/react/hooks/use-cart-manager.d.ts.map +1 -1
- package/dist/react/hooks/use-cart-manager.js +220 -16
- package/dist/react/hooks/use-login.d.ts.map +1 -1
- package/dist/react/hooks/use-login.js +3 -3
- package/dist/react/hooks/use-refresh-token.d.ts.map +1 -1
- package/dist/react/hooks/use-refresh-token.js +6 -4
- package/dist/react/hooks/use-session-expired.d.ts +16 -0
- package/dist/react/hooks/use-session-expired.d.ts.map +1 -0
- package/dist/react/hooks/use-session-expired.js +26 -0
- package/dist/react/hooks/use-session-refresh.d.ts +32 -0
- package/dist/react/hooks/use-session-refresh.d.ts.map +1 -0
- package/dist/react/hooks/use-session-refresh.js +147 -0
- package/dist/react/index.d.ts +5 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +3 -0
- package/dist/react/providers/cart-manager-provider.d.ts +50 -0
- package/dist/react/providers/cart-manager-provider.d.ts.map +1 -0
- package/dist/react/providers/cart-manager-provider.js +59 -0
- package/dist/react/providers/storefront-client-provider.d.ts +10 -1
- package/dist/react/providers/storefront-client-provider.d.ts.map +1 -1
- package/dist/react/providers/storefront-client-provider.js +38 -3
- package/dist/react/providers/storefront-provider.d.ts +51 -3
- package/dist/react/providers/storefront-provider.d.ts.map +1 -1
- package/dist/react/providers/storefront-provider.js +22 -5
- package/dist/react/server/create-storefront-auth-route.d.ts +63 -0
- package/dist/react/server/create-storefront-auth-route.d.ts.map +1 -0
- package/dist/react/server/create-storefront-auth-route.js +239 -0
- package/dist/react/server/get-initial-auth.d.ts +57 -0
- package/dist/react/server/get-initial-auth.d.ts.map +1 -0
- package/dist/react/server/get-initial-auth.js +55 -0
- package/dist/react/server/index.d.ts +3 -0
- package/dist/react/server/index.d.ts.map +1 -1
- package/dist/react/server/index.js +6 -0
- package/dist/react/stores/auth.store.d.ts +46 -2
- package/dist/react/stores/auth.store.d.ts.map +1 -1
- package/dist/react/stores/auth.store.js +19 -7
- package/package.json +4 -2
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-retry middleware — reactive 401 handling (must be OUTERMOST).
|
|
3
|
+
*
|
|
4
|
+
* When a request fails with HTTP 401 (the access token lapsed between the
|
|
5
|
+
* proactive refresh and this call):
|
|
6
|
+
*
|
|
7
|
+
* - **Read query** — refresh the session once and replay the request (R2.1).
|
|
8
|
+
* Because this middleware is the outermost one, the retry re-runs the auth
|
|
9
|
+
* middleware, which re-reads the freshly-stored token. Concurrent 401s share
|
|
10
|
+
* a single renewal because the injected `refresh` dedupes in-flight calls
|
|
11
|
+
* (R2.2). If the refresh also fails, the session is gone — signal and bail
|
|
12
|
+
* (R2.4).
|
|
13
|
+
*
|
|
14
|
+
* - **Mutation** — never auto-retry (mutations are sacred; client-side
|
|
15
|
+
* idempotency is not guaranteed). Bail and signal the session loss (R2.3).
|
|
16
|
+
*
|
|
17
|
+
* Auth operations (login / signup / refresh / logout) are exempt: they own
|
|
18
|
+
* their own error handling, and retrying the refresh op itself would recurse.
|
|
19
|
+
*
|
|
20
|
+
* 0-deps core: takes the renewal + notification as injected callbacks, so it
|
|
21
|
+
* stays framework-agnostic (the provider wires the React store + emitter).
|
|
22
|
+
*
|
|
23
|
+
* NOTE — this fires only on a genuine HTTP 401. The storefront GraphQL data
|
|
24
|
+
* transport returns HTTP 200 with GraphQL errors / `userErrors` for an expired
|
|
25
|
+
* customer token (not a 401), so on that path the proactive scheduler
|
|
26
|
+
* (`useSessionRefresh`) is the protection and this middleware stays inert. It
|
|
27
|
+
* activates wherever a request really does return 401 — e.g. the same-origin
|
|
28
|
+
* BFF refresh route — keeping reactive recovery forward-compatible with no
|
|
29
|
+
* backend change. Cart-level session loss is handled separately by cart-recovery
|
|
30
|
+
* (`CART_UNAUTHENTICATED`).
|
|
31
|
+
*/
|
|
32
|
+
import type { Middleware } from '../client/types';
|
|
33
|
+
import type { SessionExpiredEvent } from '../auth/session-events';
|
|
34
|
+
export interface SessionRetryOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Renew the session (refresh token → cookie sync → store update). Resolves
|
|
37
|
+
* `true` on success. MUST dedupe concurrent calls so simultaneous 401s share
|
|
38
|
+
* a single renewal (R2.2).
|
|
39
|
+
*/
|
|
40
|
+
refresh: () => Promise<boolean>;
|
|
41
|
+
/** Notify that the session is gone (a mutation 401, or a query whose refresh-retry failed). */
|
|
42
|
+
onSessionExpired: (event: SessionExpiredEvent) => void;
|
|
43
|
+
/** Operation names exempt from 401 handling (default: the auth operations). */
|
|
44
|
+
skipOperations?: string[];
|
|
45
|
+
}
|
|
46
|
+
export declare function sessionRetryMiddleware(options: SessionRetryOptions): Middleware;
|
|
47
|
+
//# sourceMappingURL=session-retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-retry.d.ts","sourceRoot":"","sources":["../../../src/core/middleware/session-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAQlE,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,+FAA+F;IAC/F,gBAAgB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACvD,+EAA+E;IAC/E,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAMD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,mBAAmB,GAAG,UAAU,CAgC/E"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-retry middleware — reactive 401 handling (must be OUTERMOST).
|
|
3
|
+
*
|
|
4
|
+
* When a request fails with HTTP 401 (the access token lapsed between the
|
|
5
|
+
* proactive refresh and this call):
|
|
6
|
+
*
|
|
7
|
+
* - **Read query** — refresh the session once and replay the request (R2.1).
|
|
8
|
+
* Because this middleware is the outermost one, the retry re-runs the auth
|
|
9
|
+
* middleware, which re-reads the freshly-stored token. Concurrent 401s share
|
|
10
|
+
* a single renewal because the injected `refresh` dedupes in-flight calls
|
|
11
|
+
* (R2.2). If the refresh also fails, the session is gone — signal and bail
|
|
12
|
+
* (R2.4).
|
|
13
|
+
*
|
|
14
|
+
* - **Mutation** — never auto-retry (mutations are sacred; client-side
|
|
15
|
+
* idempotency is not guaranteed). Bail and signal the session loss (R2.3).
|
|
16
|
+
*
|
|
17
|
+
* Auth operations (login / signup / refresh / logout) are exempt: they own
|
|
18
|
+
* their own error handling, and retrying the refresh op itself would recurse.
|
|
19
|
+
*
|
|
20
|
+
* 0-deps core: takes the renewal + notification as injected callbacks, so it
|
|
21
|
+
* stays framework-agnostic (the provider wires the React store + emitter).
|
|
22
|
+
*
|
|
23
|
+
* NOTE — this fires only on a genuine HTTP 401. The storefront GraphQL data
|
|
24
|
+
* transport returns HTTP 200 with GraphQL errors / `userErrors` for an expired
|
|
25
|
+
* customer token (not a 401), so on that path the proactive scheduler
|
|
26
|
+
* (`useSessionRefresh`) is the protection and this middleware stays inert. It
|
|
27
|
+
* activates wherever a request really does return 401 — e.g. the same-origin
|
|
28
|
+
* BFF refresh route — keeping reactive recovery forward-compatible with no
|
|
29
|
+
* backend change. Cart-level session loss is handled separately by cart-recovery
|
|
30
|
+
* (`CART_UNAUTHENTICATED`).
|
|
31
|
+
*/
|
|
32
|
+
import { StorefrontError } from '../errors';
|
|
33
|
+
/**
|
|
34
|
+
* Auth operations that must NOT trigger the 401 retry/signal dance — they
|
|
35
|
+
* surface their own errors, and the refresh op would otherwise recurse.
|
|
36
|
+
*/
|
|
37
|
+
const DEFAULT_SKIP_OPERATIONS = ['CustomerLogin', 'CustomerSignup', 'CustomerRefreshToken', 'CustomerLogout'];
|
|
38
|
+
function isUnauthorized(err) {
|
|
39
|
+
return err instanceof StorefrontError && err.status === 401;
|
|
40
|
+
}
|
|
41
|
+
export function sessionRetryMiddleware(options) {
|
|
42
|
+
const { refresh, onSessionExpired } = options;
|
|
43
|
+
const skip = new Set(options.skipOperations ?? DEFAULT_SKIP_OPERATIONS);
|
|
44
|
+
return async (request, next) => {
|
|
45
|
+
if (request.operationName && skip.has(request.operationName)) {
|
|
46
|
+
return next(request);
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
return await next(request);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
if (!isUnauthorized(err))
|
|
53
|
+
throw err;
|
|
54
|
+
if (request.isMutation) {
|
|
55
|
+
// R2.3 — mutations are sacred: bail, never auto-retry.
|
|
56
|
+
onSessionExpired({ reason: 'mutation-unauthorized', cause: err });
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
// R2.1 / R2.2 — read query: refresh once (deduped) and replay.
|
|
60
|
+
const renewed = await refresh();
|
|
61
|
+
if (!renewed) {
|
|
62
|
+
// R2.4 — the refresh also failed; the session is gone.
|
|
63
|
+
onSessionExpired({ reason: 'reactive-refresh-failed', cause: err });
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
// Retry once — this middleware is outermost, so the replay re-runs the
|
|
67
|
+
// auth middleware, which attaches the freshly-stored token.
|
|
68
|
+
return next(request);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/core/operations/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/core/operations/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAqHH,eAAO,MAAM,cAAc,QASzB,CAAC;AAEH,eAAO,MAAM,eAAe,QAS1B,CAAC;AAEH,eAAO,MAAM,sBAAsB,QASjC,CAAC;AAEH,eAAO,MAAM,eAAe,QAW1B,CAAC;AAMH,eAAO,MAAM,cAAc,QAOzB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,QAYnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA2aH,eAAO,MAAM,UAAU,QAOrB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,qCAAqC,QAehD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,QAO1C,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAO/B,CAAC;AAMH,eAAO,MAAM,WAAW,QAWtB,CAAC;AAEH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,gBAAgB,QAW3B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAWjC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAMH,eAAO,MAAM,yBAAyB,QAWpC,CAAC;AAEH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH,eAAO,MAAM,2BAA2B,QAWtC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,oBAAoB,QAW/B,CAAC;AAEH,eAAO,MAAM,qBAAqB,QAWhC,CAAC;AAEH,eAAO,MAAM,+BAA+B,QAW1C,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,QAWxB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAWvC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,QAoBtC,CAAC"}
|
|
@@ -198,12 +198,13 @@ const CART_SELECTED_PAYMENT_METHOD_FRAGMENT = `
|
|
|
198
198
|
name
|
|
199
199
|
provider
|
|
200
200
|
type
|
|
201
|
-
icon
|
|
201
|
+
icon { ...ImageThumbnail }
|
|
202
202
|
description
|
|
203
203
|
isDefault
|
|
204
204
|
supportedCurrencies
|
|
205
205
|
position
|
|
206
206
|
}
|
|
207
|
+
${IMAGE_THUMBNAIL_FRAGMENT}
|
|
207
208
|
`;
|
|
208
209
|
const CART_FRAGMENT = `
|
|
209
210
|
fragment Cart on Cart {
|
|
@@ -227,7 +228,7 @@ const CART_FRAGMENT = `
|
|
|
227
228
|
billingAddress { ...MailingAddress }
|
|
228
229
|
selectedShippingMethod { ...CartShippingMethod }
|
|
229
230
|
selectedPaymentMethod { ...CartSelectedPaymentMethod }
|
|
230
|
-
|
|
231
|
+
selectedPaymentInstrument
|
|
231
232
|
appliedGiftCards { ...CartAppliedGiftCard }
|
|
232
233
|
requiresShipping
|
|
233
234
|
createdAt
|
|
@@ -297,9 +298,10 @@ const SHIPPING_CARRIER_FRAGMENT = `
|
|
|
297
298
|
fragment ShippingCarrier on ShippingCarrier {
|
|
298
299
|
id
|
|
299
300
|
name
|
|
300
|
-
|
|
301
|
+
logo { ...ImageThumbnail }
|
|
301
302
|
serviceCode
|
|
302
303
|
}
|
|
304
|
+
${IMAGE_THUMBNAIL_FRAGMENT}
|
|
303
305
|
`;
|
|
304
306
|
const DELIVERY_ESTIMATE_FRAGMENT = `
|
|
305
307
|
fragment DeliveryEstimate on DeliveryEstimate {
|
|
@@ -337,16 +339,17 @@ const AVAILABLE_SHIPPING_METHOD_FRAGMENT = `
|
|
|
337
339
|
${DELIVERY_ESTIMATE_FRAGMENT}
|
|
338
340
|
${FREE_SHIPPING_PROGRESS_FRAGMENT}
|
|
339
341
|
`;
|
|
340
|
-
const
|
|
341
|
-
fragment
|
|
342
|
-
|
|
343
|
-
|
|
342
|
+
const PAYMENT_INSTRUMENT_FRAGMENT = `
|
|
343
|
+
fragment PaymentInstrument on PaymentInstrument {
|
|
344
|
+
provider
|
|
345
|
+
code
|
|
344
346
|
type
|
|
345
347
|
displayName
|
|
346
348
|
displayHint
|
|
347
|
-
|
|
349
|
+
brandImage { ...ImageThumbnail }
|
|
348
350
|
enabled
|
|
349
351
|
}
|
|
352
|
+
${IMAGE_THUMBNAIL_FRAGMENT}
|
|
350
353
|
`;
|
|
351
354
|
const PAYMENT_METHOD_FRAGMENT = `
|
|
352
355
|
fragment PaymentMethod on PaymentMethod {
|
|
@@ -354,7 +357,7 @@ const PAYMENT_METHOD_FRAGMENT = `
|
|
|
354
357
|
name
|
|
355
358
|
provider
|
|
356
359
|
type
|
|
357
|
-
icon
|
|
360
|
+
icon { ...ImageThumbnail }
|
|
358
361
|
description
|
|
359
362
|
isDefault
|
|
360
363
|
supportedCurrencies
|
|
@@ -364,10 +367,11 @@ const PAYMENT_METHOD_FRAGMENT = `
|
|
|
364
367
|
available
|
|
365
368
|
unavailableReason
|
|
366
369
|
instruments {
|
|
367
|
-
...
|
|
370
|
+
...PaymentInstrument
|
|
368
371
|
}
|
|
369
372
|
}
|
|
370
|
-
${
|
|
373
|
+
${PAYMENT_INSTRUMENT_FRAGMENT}
|
|
374
|
+
${IMAGE_THUMBNAIL_FRAGMENT}
|
|
371
375
|
`;
|
|
372
376
|
const AVAILABLE_PAYMENT_METHODS_FRAGMENT = `
|
|
373
377
|
fragment AvailablePaymentMethods on AvailablePaymentMethods {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentInstrumentSection.d.ts","sourceRoot":"","sources":["../../../src/react/components/PaymentInstrumentSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"PaymentInstrumentSection.d.ts","sourceRoot":"","sources":["../../../src/react/components/PaymentInstrumentSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAqB,MAAM,sCAAsC,CAAC;AAG7F;;;;GAIG;AACH,MAAM,MAAM,8BAA8B,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAEhF,MAAM,WAAW,6BAA6B;IAC5C,mFAAmF;IACnF,MAAM,EAAE,8BAA8B,CAAC;IACvC,iGAAiG;IACjG,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,2GAA2G;IAC3G,kBAAkB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4IAA4I;IAC5I,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,wBAAwB,CAAC,EACvC,MAAM,EACN,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,SAAS,GACV,EAAE,6BAA6B,kDAmF/B"}
|
|
@@ -76,14 +76,14 @@ export function PaymentInstrumentSection({ method, selectedInstrumentCode, onSel
|
|
|
76
76
|
}
|
|
77
77
|
return (_jsx("div", { ref: sectionRef, role: "radiogroup", "aria-label": ariaLabel, onKeyDown: handleKeyDown, className: sectionClassName, children: instruments.map((instrument) => {
|
|
78
78
|
// Cast to tile-projection shape — instruments[] z generated types ma więcej pól
|
|
79
|
-
// niż tile potrzebuje (
|
|
79
|
+
// niż tile potrzebuje (provider, type), tile picks subset jawnie.
|
|
80
80
|
const tileInstrument = {
|
|
81
|
-
|
|
81
|
+
code: instrument.code,
|
|
82
82
|
displayName: instrument.displayName,
|
|
83
83
|
displayHint: instrument.displayHint,
|
|
84
84
|
enabled: instrument.enabled,
|
|
85
|
-
|
|
85
|
+
brandImage: instrument.brandImage ?? undefined,
|
|
86
86
|
};
|
|
87
|
-
return (_jsx(PaymentInstrumentTile, { instrument: tileInstrument, selected: instrument.
|
|
87
|
+
return (_jsx(PaymentInstrumentTile, { instrument: tileInstrument, selected: instrument.code === selectedInstrumentCode, onSelect: () => onSelectInstrument(instrument.code), className: tileClassName, iconClassName: iconClassName, labelClassName: labelClassName }, instrument.code));
|
|
88
88
|
}) }));
|
|
89
89
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* @example
|
|
21
21
|
* ```tsx
|
|
22
22
|
* <PaymentInstrumentTile
|
|
23
|
-
* instrument={{
|
|
23
|
+
* instrument={{ code: 'blik', displayName: 'BLIK', displayHint: 'PROMINENT_BUTTON', enabled: true }}
|
|
24
24
|
* selected={selectedCode === 'blik'}
|
|
25
25
|
* onSelect={() => setSelectedCode('blik')}
|
|
26
26
|
* className="rounded-lg border p-3 hover:bg-gray-50 data-[selected=true]:border-blue-500"
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
*
|
|
31
31
|
* Added by payment-instrument-preselection-advanced sub-sprint Adv-2 Req 9.
|
|
32
32
|
*/
|
|
33
|
-
import type {
|
|
33
|
+
import type { PaymentInstrument } from '../../core/generated/operation-types';
|
|
34
34
|
/**
|
|
35
|
-
* Minimalna projekcja `
|
|
35
|
+
* Minimalna projekcja `PaymentInstrument` używana przez tile. Caller może
|
|
36
36
|
* pass pełny instrument z `availablePaymentMethods` query — extra pola
|
|
37
|
-
* (
|
|
38
|
-
* provider — gateway-agnostic,
|
|
37
|
+
* (provider, type) są ignorowane przez komponent (UI nie branchuje na
|
|
38
|
+
* provider — gateway-agnostic, code + displayHint wystarczą).
|
|
39
39
|
*/
|
|
40
|
-
export type PaymentInstrumentTileInstrument = Pick<
|
|
40
|
+
export type PaymentInstrumentTileInstrument = Pick<PaymentInstrument, 'code' | 'displayName' | 'displayHint' | 'enabled'> & Partial<Pick<PaymentInstrument, 'brandImage'>>;
|
|
41
41
|
export interface PaymentInstrumentTileProps {
|
|
42
42
|
/** Instrument projection — gateway code, label, display hint, enabled state. */
|
|
43
43
|
instrument: PaymentInstrumentTileInstrument;
|
|
@@ -47,7 +47,7 @@ export interface PaymentInstrumentTileProps {
|
|
|
47
47
|
onSelect: () => void;
|
|
48
48
|
/** Optional class for the outer button — header styling, layout, border. */
|
|
49
49
|
className?: string;
|
|
50
|
-
/** Optional class for the brand image (`<img>` element). Only applied when instrument has `
|
|
50
|
+
/** Optional class for the brand image (`<img>` element). Only applied when instrument has `brandImage`. */
|
|
51
51
|
iconClassName?: string;
|
|
52
52
|
/** Optional class for the label span. */
|
|
53
53
|
labelClassName?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentInstrumentTile.d.ts","sourceRoot":"","sources":["../../../src/react/components/PaymentInstrumentTile.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"PaymentInstrumentTile.d.ts","sourceRoot":"","sources":["../../../src/react/components/PaymentInstrumentTile.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,MAAM,+BAA+B,GAAG,IAAI,CAChD,iBAAiB,EACjB,MAAM,GAAG,aAAa,GAAG,aAAa,GAAG,SAAS,CACnD,GACC,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC,CAAC;AAEjD,MAAM,WAAW,0BAA0B;IACzC,gFAAgF;IAChF,UAAU,EAAE,+BAA+B,CAAC;IAC5C,6GAA6G;IAC7G,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2GAA2G;IAC3G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,aAAa,EACb,cAAc,GACf,EAAE,0BAA0B,2CAuB5B"}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* @example
|
|
21
21
|
* ```tsx
|
|
22
22
|
* <PaymentInstrumentTile
|
|
23
|
-
* instrument={{
|
|
23
|
+
* instrument={{ code: 'blik', displayName: 'BLIK', displayHint: 'PROMINENT_BUTTON', enabled: true }}
|
|
24
24
|
* selected={selectedCode === 'blik'}
|
|
25
25
|
* onSelect={() => setSelectedCode('blik')}
|
|
26
26
|
* className="rounded-lg border p-3 hover:bg-gray-50 data-[selected=true]:border-blue-500"
|
|
@@ -33,8 +33,9 @@
|
|
|
33
33
|
'use client';
|
|
34
34
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
35
35
|
export function PaymentInstrumentTile({ instrument, selected, onSelect, className, iconClassName, labelClassName, }) {
|
|
36
|
-
const {
|
|
36
|
+
const { code, displayName, displayHint, brandImage, enabled } = instrument;
|
|
37
|
+
const brandImageUrl = brandImage?.url;
|
|
37
38
|
// PROMINENT_BUTTON hides brand image — instrument jest text-only CTA (BLIK code entry).
|
|
38
39
|
const showImage = displayHint !== 'PROMINENT_BUTTON' && brandImageUrl;
|
|
39
|
-
return (_jsxs("button", { type: "button", role: "radio", "aria-checked": selected, "aria-label": displayName, "data-instrument-code":
|
|
40
|
+
return (_jsxs("button", { type: "button", role: "radio", "aria-checked": selected, "aria-label": displayName, "data-instrument-code": code, "data-display-hint": displayHint, "data-selected": selected, disabled: !enabled, onClick: onSelect, className: className, children: [showImage && _jsx("img", { src: brandImageUrl, alt: brandImage?.altText ?? '', className: iconClassName }), _jsx("span", { className: labelClassName, children: displayName })] }));
|
|
40
41
|
}
|
|
@@ -7,23 +7,53 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Per-operation strategy:
|
|
9
9
|
*
|
|
10
|
-
* | Operation
|
|
11
|
-
* |
|
|
12
|
-
* | `addItem`
|
|
13
|
-
* | `updateBuyerIdentity`
|
|
14
|
-
* | `setShippingAddress`
|
|
15
|
-
* | `updateDiscountCodes`
|
|
16
|
-
* | `updateNote`
|
|
17
|
-
* | `
|
|
18
|
-
* | `
|
|
10
|
+
* | Operation | Strategy | Why |
|
|
11
|
+
* | -------------------------- | ------------------------------------- | --------------------------------------------- |
|
|
12
|
+
* | `addItem` | Auto-replay (atomic `cartCreate`) | Storefront expects "add to cart" always works |
|
|
13
|
+
* | `updateBuyerIdentity` | Auto-replay | User just typed email/phone — keep it |
|
|
14
|
+
* | `setShippingAddress` | Auto-replay | User just typed address — keep it |
|
|
15
|
+
* | `updateDiscountCodes` | Auto-replay | Coupon valid independently of cart |
|
|
16
|
+
* | `updateNote` | Auto-replay | Stateless / idempotent |
|
|
17
|
+
* | `updateAttributes` | Auto-replay | Stateless metadata — atomic re-create OK |
|
|
18
|
+
* | `updateItem` | Bail + `cart-expired` event | `lineId` refers to a line in the dead cart |
|
|
19
|
+
* | `removeItem` | Bail + `cart-expired` event | jw. |
|
|
20
|
+
* | `setBillingAddress` | Bail + `cart-expired` event | Cart must exist (separate from shipping) |
|
|
21
|
+
* | `selectShippingMethod` | Bail + `cart-expired` event | Method tied to cart contents + address |
|
|
22
|
+
* | `selectPaymentMethod` | Bail + `cart-expired` event | Payment selection on existing cart state |
|
|
23
|
+
* | `clearPaymentSelection` | Bail + `cart-expired` event | Operates on existing cart payment fields |
|
|
24
|
+
* | `applyGiftCard` | Bail + `cart-expired` event | Balance allocation tied to cart total |
|
|
25
|
+
* | `removeGiftCard` | Bail + `cart-expired` event | `giftCardId` refers to row on dead cart |
|
|
26
|
+
* | `updateGiftCardRecipient` | Bail + `cart-expired` event | `lineId` refers to a line in the dead cart |
|
|
27
|
+
* | `complete` | Bail + `cart-expired` event | Finalised cart cannot be auto-recreated |
|
|
28
|
+
* | `createPayment` | Out of recovery scope | Operates on `orderId` (post-complete) |
|
|
19
29
|
*
|
|
20
30
|
* On bail the runner clears the cookie and calls every `onExpired` listener
|
|
21
31
|
* with a `CartExpiredEvent`. UI subscribes once globally and shows a toast /
|
|
22
32
|
* banner — caller code never writes `try / catch` per mutation.
|
|
23
33
|
*
|
|
34
|
+
* After `complete` success the hook auto-clears the `cart-id` cookie and
|
|
35
|
+
* resets status to `idle` — buyer returning to `/checkout` (back from the
|
|
36
|
+
* payment gateway, deep link, new tab) gets a fresh empty cart instead of the
|
|
37
|
+
* CONVERTED cart. Manual `clearCart()` remains available as an escape hatch.
|
|
38
|
+
*
|
|
24
39
|
* Auto-creates cart on first add. Cart id persisted in `cart-id` cookie
|
|
25
40
|
* (SSR/edge visible, 30 days, samesite=lax).
|
|
26
41
|
*
|
|
42
|
+
* ### Server-known cart-id (env seed, magic-link, iframe, customer service)
|
|
43
|
+
*
|
|
44
|
+
* Pass `{ initialCartId }` to seed the hook with a cart-id resolved server-side
|
|
45
|
+
* (read from URL params in a Route Handler, env var for dev fixtures, parent
|
|
46
|
+
* `postMessage` for embedded iframe, admin "view this cart" lookup). The hook
|
|
47
|
+
* applies priority `cookie wins → seed → auto-create`. The seed is eagerly
|
|
48
|
+
* written to the cart-id cookie so cross-tab tabs and standard recovery
|
|
49
|
+
* semantics operate on a canonical value. A stale seed goes through the same
|
|
50
|
+
* recovery flow as a stale cookie — `addItem` auto-replays through
|
|
51
|
+
* `cartCreate({ lines })`, state-dependent ops bail with `cart-expired`.
|
|
52
|
+
*
|
|
53
|
+
* Mirrors the `<StorefrontProvider initialAccessToken>` pattern for the
|
|
54
|
+
* cart-id half of the checkout state — both are seeds for the first render
|
|
55
|
+
* when the client cannot read the canonical source itself.
|
|
56
|
+
*
|
|
27
57
|
* @example
|
|
28
58
|
* ```tsx
|
|
29
59
|
* function CartUI() {
|
|
@@ -34,15 +64,35 @@
|
|
|
34
64
|
* return <button onClick={() => addItem([{ variantId, quantity: 1 }])}>Add</button>;
|
|
35
65
|
* }
|
|
36
66
|
* ```
|
|
67
|
+
*
|
|
68
|
+
* @example Server-known cart-id
|
|
69
|
+
* ```tsx
|
|
70
|
+
* // app/checkout/page.tsx — Server Component
|
|
71
|
+
* import { cookies } from 'next/headers';
|
|
72
|
+
* import { CART_COOKIE_NAME } from '@doswiftly/storefront-sdk';
|
|
73
|
+
*
|
|
74
|
+
* export default async function CheckoutPage() {
|
|
75
|
+
* const cookieJar = await cookies();
|
|
76
|
+
* const initialCartId =
|
|
77
|
+
* cookieJar.get(CART_COOKIE_NAME)?.value ?? process.env.NEXT_PUBLIC_DEV_CART_ID ?? null;
|
|
78
|
+
* return <CheckoutClient initialCartId={initialCartId} />;
|
|
79
|
+
* }
|
|
80
|
+
*
|
|
81
|
+
* // CheckoutClient.tsx — 'use client'
|
|
82
|
+
* function CheckoutClient({ initialCartId }: { initialCartId: string | null }) {
|
|
83
|
+
* const { complete, selectPaymentMethod, addItem } = useCartManager({ initialCartId });
|
|
84
|
+
* // ... rest unchanged — hook handles seed → cookie → recovery transparently
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
37
87
|
*/
|
|
38
|
-
import type { Cart, CartLineInput, CartLineUpdateInput, CartBuyerIdentityInput, CartAddressInput } from '../../core/cart/types';
|
|
39
|
-
import type { CartMutationOutcome } from '../../core/cart/cart-client';
|
|
88
|
+
import type { Cart, CartLineInput, CartLineUpdateInput, CartBuyerIdentityInput, CartAddressInput, CartAttributeInput, CartCompleteInput, CartSelectShippingMethodInput, CartSelectPaymentMethodInput, CartClearPaymentSelectionInput, CartApplyGiftCardInput, CartRemoveGiftCardInput, CartUpdateGiftCardRecipientInput, PaymentCreateInput, PaymentSession } from '../../core/cart/types';
|
|
89
|
+
import type { CartMutationOutcome, CartCompleteOutcome } from '../../core/cart/cart-client';
|
|
40
90
|
import { type CartExpiredEvent } from '../../core/cart/cart-recovery';
|
|
41
91
|
/**
|
|
42
92
|
* Names of mutations exposed by the hook — narrows `status.operation` for
|
|
43
93
|
* exhaustive consumer-side switching (e.g. operation-specific spinners).
|
|
44
94
|
*/
|
|
45
|
-
export type CartManagerOperation = 'addItem' | 'updateItem' | 'removeItem' | 'updateBuyerIdentity' | 'setShippingAddress' | 'updateDiscountCodes' | 'updateNote';
|
|
95
|
+
export type CartManagerOperation = 'addItem' | 'updateItem' | 'removeItem' | 'updateBuyerIdentity' | 'setShippingAddress' | 'setBillingAddress' | 'updateDiscountCodes' | 'updateNote' | 'updateAttributes' | 'selectShippingMethod' | 'selectPaymentMethod' | 'clearPaymentSelection' | 'applyGiftCard' | 'removeGiftCard' | 'updateGiftCardRecipient' | 'complete' | 'createPayment';
|
|
46
96
|
/**
|
|
47
97
|
* Tagged union of cart mutation lifecycle states. Lets callers do exhaustive
|
|
48
98
|
* switching without remembering which boolean flag pairs with which:
|
|
@@ -69,6 +119,53 @@ export type CartManagerStatus = {
|
|
|
69
119
|
type: 'success';
|
|
70
120
|
operation: CartManagerOperation;
|
|
71
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* Optional lifecycle callbacks fired around every cart and checkout operation
|
|
124
|
+
* the hook drives. Centralise cross-cutting side-effects — a global loading
|
|
125
|
+
* indicator, a toast on failure, a router refresh on success — in one place
|
|
126
|
+
* instead of wrapping each call site.
|
|
127
|
+
*
|
|
128
|
+
* `onMutationError` fires only for failures you can surface to the buyer: its
|
|
129
|
+
* `error` carries a backend-translated message. Cart expiry and session loss
|
|
130
|
+
* are delivered through their own dedicated channels (`onExpired` and the
|
|
131
|
+
* session-expired event) — they carry SDK-internal messages and do NOT trigger
|
|
132
|
+
* `onMutationError`. A transient missing-cart error that the manager recovers
|
|
133
|
+
* from (by recreating the cart) resolves as success, so it never reaches the
|
|
134
|
+
* error callback either.
|
|
135
|
+
*
|
|
136
|
+
* Callbacks are invoked defensively: a throwing callback never rejects the
|
|
137
|
+
* underlying mutation.
|
|
138
|
+
*/
|
|
139
|
+
export interface CartManagerLifecycleCallbacks {
|
|
140
|
+
/** Fired when an operation starts, before the request is sent. */
|
|
141
|
+
onMutationStart?: (operation: CartManagerOperation) => void;
|
|
142
|
+
/** Fired after an operation resolves successfully. */
|
|
143
|
+
onMutationSuccess?: (operation: CartManagerOperation) => void;
|
|
144
|
+
/**
|
|
145
|
+
* Fired when an operation fails with a buyer-surfaceable error. Cart expiry
|
|
146
|
+
* and session loss are routed to `onExpired` / the session-expired event
|
|
147
|
+
* instead, not here.
|
|
148
|
+
*/
|
|
149
|
+
onMutationError?: (operation: CartManagerOperation, error: Error) => void;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Optional configuration for `useCartManager`. All fields additive — calling
|
|
153
|
+
* the hook with no arguments preserves the original cookie-driven behaviour.
|
|
154
|
+
*/
|
|
155
|
+
export interface UseCartManagerOptions extends CartManagerLifecycleCallbacks {
|
|
156
|
+
/**
|
|
157
|
+
* Server-known cart-id seed used when the `cart-id` cookie is empty on
|
|
158
|
+
* mount. Cookie wins when present; the seed only fills the gap on the
|
|
159
|
+
* first interaction. Eagerly promoted to the cookie store so cross-tab
|
|
160
|
+
* tabs and standard recovery semantics operate on a canonical value.
|
|
161
|
+
*
|
|
162
|
+
* See the hook-level `@example Server-known cart-id` block for the full
|
|
163
|
+
* Server-Component → Client-Component data flow. Use for env seed (dev),
|
|
164
|
+
* magic-link checkout, embedded iframe (parent supplies cart-id),
|
|
165
|
+
* customer service "view this cart", multi-cart B2B selectors.
|
|
166
|
+
*/
|
|
167
|
+
initialCartId?: string | null;
|
|
168
|
+
}
|
|
72
169
|
export interface UseCartManagerResult {
|
|
73
170
|
getCart: () => Promise<Cart | null>;
|
|
74
171
|
getCartId: () => string | null;
|
|
@@ -77,8 +174,31 @@ export interface UseCartManagerResult {
|
|
|
77
174
|
setShippingAddress: (address: CartAddressInput) => Promise<CartMutationOutcome>;
|
|
78
175
|
updateDiscountCodes: (codes: string[]) => Promise<CartMutationOutcome>;
|
|
79
176
|
updateNote: (note: string) => Promise<CartMutationOutcome>;
|
|
177
|
+
updateAttributes: (attributes: CartAttributeInput[]) => Promise<CartMutationOutcome>;
|
|
80
178
|
updateItem: (lines: CartLineUpdateInput[]) => Promise<CartMutationOutcome>;
|
|
81
179
|
removeItem: (lineIds: string[]) => Promise<CartMutationOutcome>;
|
|
180
|
+
setBillingAddress: (address: CartAddressInput) => Promise<CartMutationOutcome>;
|
|
181
|
+
selectShippingMethod: (input: Omit<CartSelectShippingMethodInput, 'cartId'>) => Promise<CartMutationOutcome>;
|
|
182
|
+
selectPaymentMethod: (input: Omit<CartSelectPaymentMethodInput, 'cartId'>) => Promise<CartMutationOutcome>;
|
|
183
|
+
clearPaymentSelection: (input?: Omit<CartClearPaymentSelectionInput, 'cartId'>) => Promise<CartMutationOutcome>;
|
|
184
|
+
applyGiftCard: (input: Omit<CartApplyGiftCardInput, 'cartId'>) => Promise<CartMutationOutcome>;
|
|
185
|
+
removeGiftCard: (input: Omit<CartRemoveGiftCardInput, 'cartId'>) => Promise<CartMutationOutcome>;
|
|
186
|
+
updateGiftCardRecipient: (input: Omit<CartUpdateGiftCardRecipientInput, 'cartId'>) => Promise<CartMutationOutcome>;
|
|
187
|
+
/**
|
|
188
|
+
* Finalise the cart into an Order. On success the `cart-id` cookie is
|
|
189
|
+
* cleared and status resets to `idle` — a follow-up `addItem` auto-creates
|
|
190
|
+
* a fresh cart, matching shop-again UX. The cart itself is NOT returned
|
|
191
|
+
* (CONVERTED/locked after completion); work with `result.order` for
|
|
192
|
+
* post-checkout flows (`order.canCreatePayment`, `order.accessToken`).
|
|
193
|
+
*/
|
|
194
|
+
complete: (input?: Omit<CartCompleteInput, 'cartId'>) => Promise<CartCompleteOutcome>;
|
|
195
|
+
/**
|
|
196
|
+
* Initiate a payment session for an order created by `complete`. NOT a
|
|
197
|
+
* cart operation (works on `orderId`, not `cartId`) — included on the
|
|
198
|
+
* manager for a single checkout-lifecycle API. Throws on
|
|
199
|
+
* `userErrors[].code === 'PAYMENT_*'` — branch on `err.userErrors[0].code`.
|
|
200
|
+
*/
|
|
201
|
+
createPayment: (input: PaymentCreateInput) => Promise<PaymentSession>;
|
|
82
202
|
clearCart: () => void;
|
|
83
203
|
onExpired: (listener: (event: CartExpiredEvent) => void) => () => void;
|
|
84
204
|
status: CartManagerStatus;
|
|
@@ -87,5 +207,5 @@ export interface UseCartManagerResult {
|
|
|
87
207
|
/** Error message when status.type === 'error', otherwise null. */
|
|
88
208
|
error: string | null;
|
|
89
209
|
}
|
|
90
|
-
export declare function useCartManager(): UseCartManagerResult;
|
|
210
|
+
export declare function useCartManager(options?: UseCartManagerOptions): UseCartManagerResult;
|
|
91
211
|
//# sourceMappingURL=use-cart-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-cart-manager.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-cart-manager.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"use-cart-manager.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-cart-manager.ts"],"names":[],"mappings":"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"}
|