@movmo_app/payments 0.2.0 → 0.3.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/index.cjs.js +10 -10
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +156 -6
- package/dist/index.es.js +1308 -930
- package/dist/index.es.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,16 @@ export declare interface CardFieldError {
|
|
|
7
7
|
message: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Focus state of each Spreedly-hosted iframe. The browser's `focus-within`
|
|
12
|
+
* CSS pseudo-class can't see across iframe boundaries, so the consumer needs
|
|
13
|
+
* an explicit signal to render the "active border" on the iframe shell.
|
|
14
|
+
*/
|
|
15
|
+
declare interface CardFieldFocus {
|
|
16
|
+
number: boolean;
|
|
17
|
+
cvv: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
10
20
|
declare interface CardFieldValidity {
|
|
11
21
|
/** True only when the card-number field has a complete, length-valid value. */
|
|
12
22
|
number: boolean;
|
|
@@ -27,12 +37,101 @@ export declare interface CardholderTokenizeData {
|
|
|
27
37
|
zip?: string;
|
|
28
38
|
}
|
|
29
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Builds an auth-aware `fetch` that the payments package (or any other
|
|
42
|
+
* consumer that registers it via `setPaymentsConfig({ fetch })`) can call.
|
|
43
|
+
* See file header for the full contract.
|
|
44
|
+
*/
|
|
45
|
+
export declare const createMovmoAuthFetch: (options: CreateMovmoAuthFetchOptions) => typeof fetch;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Auth-aware `fetch` wrapper for `@movmo_app/payments`. The package's API
|
|
49
|
+
* helpers call through `getPaymentsConfig().fetch`, bypassing whatever axios
|
|
50
|
+
* interceptor stack the consumer wires up. Without this wrapper:
|
|
51
|
+
*
|
|
52
|
+
* - Session cookie expiry → silent 401/403 (no refresh, no logout).
|
|
53
|
+
* - State-mutating endpoints → 403 because the CSRF cookie isn't echoed.
|
|
54
|
+
* - Local-dev / multi-tenant flows → missing per-request headers like
|
|
55
|
+
* `X-Movmo-Proxy-Auth` or `movmo-customer-id`.
|
|
56
|
+
*
|
|
57
|
+
* This factory replaces a ~95-line `paymentsFetch.ts` copy that was
|
|
58
|
+
* duplicated across consumer apps. The contract:
|
|
59
|
+
*
|
|
60
|
+
* 1. CSRF token from `csrfCookieName` is set on every request as
|
|
61
|
+
* `X-CSRF-Token` (matching the axios interceptor's unconditional set).
|
|
62
|
+
* 2. `extraHeaders(input, init)` is invoked per-request to allow dynamic
|
|
63
|
+
* headers (proxy-auth, customer id, etc.). Headers the caller already
|
|
64
|
+
* set on `init.headers` win — `extraHeaders` only fills gaps.
|
|
65
|
+
* 3. `credentials: 'include'` is forced so the session cookie travels.
|
|
66
|
+
* 4. On a 401/403 from a non-auth endpoint, the wrapper calls
|
|
67
|
+
* `refreshSession()` once (concurrent failures share one in-flight
|
|
68
|
+
* promise) and retries the original request. If refresh ITSELF fails,
|
|
69
|
+
* `onRefreshFailed(err)` fires so the consumer can drive a sign-out —
|
|
70
|
+
* silently swallowing here would strand the user on a broken page.
|
|
71
|
+
* Failures on the *retry* fetch are logged and the original response is
|
|
72
|
+
* returned so the SDK still sees a Response to render an error from.
|
|
73
|
+
* 5. The original fetch's network errors (offline, CORS, DNS) propagate.
|
|
74
|
+
* Only retry-path failures are caught; pre-refresh errors are left for
|
|
75
|
+
* the consumer to surface.
|
|
76
|
+
*
|
|
77
|
+
* The duplicated copies that this replaces both silently swallowed refresh
|
|
78
|
+
* failure (see review issue #1 on both PR #47 + PR #180). Making
|
|
79
|
+
* `onRefreshFailed` *required* enforces at the type level that consumers
|
|
80
|
+
* wire up a logout path.
|
|
81
|
+
*/
|
|
82
|
+
export declare interface CreateMovmoAuthFetchOptions {
|
|
83
|
+
/**
|
|
84
|
+
* Refreshes the session cookie. Called once on the first 401/403; concurrent
|
|
85
|
+
* 401/403s share the same in-flight promise. Resolved value is ignored — the
|
|
86
|
+
* wrapper only cares about success vs. rejection. Must rotate the session
|
|
87
|
+
* cookie (and CSRF cookie, if applicable) such that a retry with the same
|
|
88
|
+
* request will succeed.
|
|
89
|
+
*/
|
|
90
|
+
refreshSession: () => Promise<unknown>;
|
|
91
|
+
/**
|
|
92
|
+
* Fired when `refreshSession()` itself rejects. The consumer MUST treat this
|
|
93
|
+
* as a terminal auth failure and trigger a sign-out + redirect — otherwise
|
|
94
|
+
* the user is stranded on a broken page with `authState.isAuthenticated`
|
|
95
|
+
* still true.
|
|
96
|
+
*
|
|
97
|
+
* Receives the underlying rejection so the consumer can log it.
|
|
98
|
+
*/
|
|
99
|
+
onRefreshFailed: (error: unknown) => void;
|
|
100
|
+
/**
|
|
101
|
+
* Cookie name carrying the CSRF token. Defaults to `movmo_csrf_token`.
|
|
102
|
+
*/
|
|
103
|
+
csrfCookieName?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Optional per-request header builder. Evaluated on every call (not cached)
|
|
106
|
+
* so dynamically-changing headers (e.g. `movmo-customer-id` driven by a
|
|
107
|
+
* route param) reflect the current value. Headers the caller already set
|
|
108
|
+
* on `init.headers` always win — `extraHeaders` only fills gaps.
|
|
109
|
+
*/
|
|
110
|
+
extraHeaders?: (input: RequestInfo | URL, init?: RequestInit) => Record<string, string>;
|
|
111
|
+
/**
|
|
112
|
+
* Substring used to detect requests that must NOT trigger the refresh
|
|
113
|
+
* retry — typically the auth-refresh endpoint itself, to avoid an
|
|
114
|
+
* infinite recursion when refresh returns 401. Defaults to `/v1/auth/`.
|
|
115
|
+
*/
|
|
116
|
+
authPathFragment?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Underlying fetch impl. Defaults to `globalThis.fetch.bind(globalThis)`.
|
|
119
|
+
* Override only for tests or non-browser environments.
|
|
120
|
+
*/
|
|
121
|
+
baseFetch?: typeof fetch;
|
|
122
|
+
/**
|
|
123
|
+
* Cookie reader. Defaults to reading `document.cookie`. Override only in
|
|
124
|
+
* non-browser test environments — the default works in jsdom.
|
|
125
|
+
*/
|
|
126
|
+
readCookie?: (name: string) => string | null;
|
|
127
|
+
}
|
|
128
|
+
|
|
30
129
|
export declare const getPaymentsConfig: () => InternalPaymentsConfig;
|
|
31
130
|
|
|
32
131
|
/* Excluded from this release type: InternalPaymentsConfig */
|
|
33
132
|
|
|
34
133
|
export declare const MovmoCardForm: {
|
|
35
|
-
({ userId, onSuccess, onError, isDefault, className, defaultCardholderName, defaultCardholderFirstName, defaultCardholderLastName, autoSave, formId, hideInternalSaveButton, onCanSubmitChange, }: MovmoCardFormProps): JSX_2.Element;
|
|
134
|
+
({ userId, onSuccess, onError, isDefault, className, defaultCardholderName, defaultCardholderFirstName, defaultCardholderLastName, autoSave, formId, hideInternalSaveButton, onCanSubmitChange, onSavingChange, autoFocus, }: MovmoCardFormProps): JSX_2.Element;
|
|
36
135
|
displayName: string;
|
|
37
136
|
};
|
|
38
137
|
|
|
@@ -77,15 +176,32 @@ export declare interface MovmoCardFormProps {
|
|
|
77
176
|
* not in flight). Use to enable / disable an external Save button.
|
|
78
177
|
*/
|
|
79
178
|
onCanSubmitChange?: (canSubmit: boolean) => void;
|
|
179
|
+
/**
|
|
180
|
+
* Fires whenever the form transitions in / out of the "saving" state
|
|
181
|
+
* (tokenize call or save POST in flight). A parent rendering its own
|
|
182
|
+
* Save button (e.g. a modal footer) uses this to swap the button label
|
|
183
|
+
* for a spinner. The hook's loading state is internal and not surfaced
|
|
184
|
+
* directly — this callback is the single source of truth.
|
|
185
|
+
*/
|
|
186
|
+
onSavingChange?: (isSaving: boolean) => void;
|
|
187
|
+
/**
|
|
188
|
+
* When set, the named Spreedly hosted-fields iframe receives keyboard
|
|
189
|
+
* focus the moment the field becomes ready. Use `"number"` for the
|
|
190
|
+
* accounts-ui add-card modal so the user can start typing immediately.
|
|
191
|
+
*/
|
|
192
|
+
autoFocus?: 'number' | 'cvv';
|
|
80
193
|
}
|
|
81
194
|
|
|
82
195
|
/**
|
|
83
|
-
* Compact preview of a single saved card: brand icon +
|
|
84
|
-
*
|
|
85
|
-
*
|
|
196
|
+
* Compact preview of a single saved card: brand icon + label. Used by
|
|
197
|
+
* consumers (e.g. flights-ui's collapsed checkout drawer) to show the
|
|
198
|
+
* currently-selected card outside the full `<PaymentMethodsManager />`
|
|
86
199
|
* list view. Keeps the brand-icon styling consistent with the expanded list.
|
|
200
|
+
*
|
|
201
|
+
* Brand icon is sized to match flights-ui main's `w-[34px]` collapsed view.
|
|
202
|
+
* No vertical padding — the parent controls spacing.
|
|
87
203
|
*/
|
|
88
|
-
export declare const PaymentMethodPreview: ({ method, trailing, onClick, className, }: PaymentMethodPreviewProps) => JSX_2.Element;
|
|
204
|
+
export declare const PaymentMethodPreview: ({ method, trailing, onClick, cardLabelFormat, className, }: PaymentMethodPreviewProps) => JSX_2.Element;
|
|
89
205
|
|
|
90
206
|
export declare interface PaymentMethodPreviewProps {
|
|
91
207
|
/**
|
|
@@ -98,11 +214,17 @@ export declare interface PaymentMethodPreviewProps {
|
|
|
98
214
|
trailing?: React.ReactNode;
|
|
99
215
|
/** Whole-row click handler — typically toggles the drawer open. */
|
|
100
216
|
onClick?: () => void;
|
|
217
|
+
/**
|
|
218
|
+
* Controls how the card label is rendered.
|
|
219
|
+
* - `'branded'` (default): "Visa 4242" — brand name + last4
|
|
220
|
+
* - `'masked'`: "•••• 4242" — masked bullets + last4 (flights-ui collapsed-drawer style)
|
|
221
|
+
*/
|
|
222
|
+
cardLabelFormat?: 'masked' | 'branded';
|
|
101
223
|
className?: string;
|
|
102
224
|
}
|
|
103
225
|
|
|
104
226
|
export declare const PaymentMethodsManager: {
|
|
105
|
-
({ userId, defaultCardholderName, defaultCardholderFirstName, defaultCardholderLastName, selectedId, onSelect, onChange, paymentTypeSelector, autoSaveFirstCard, selectionSetsDefault, showDefaultBadge, className, }: PaymentMethodsManagerProps): JSX_2.Element;
|
|
227
|
+
({ userId, defaultCardholderName, defaultCardholderFirstName, defaultCardholderLastName, selectedId, onSelect, onChange, paymentTypeSelector, autoSaveFirstCard, selectionSetsDefault, showDefaultBadge, collapsible, cardLabelFormat, className, }: PaymentMethodsManagerProps): JSX_2.Element;
|
|
106
228
|
displayName: string;
|
|
107
229
|
};
|
|
108
230
|
|
|
@@ -151,6 +273,19 @@ export declare interface PaymentMethodsManagerProps {
|
|
|
151
273
|
* Defaults to `true`.
|
|
152
274
|
*/
|
|
153
275
|
showDefaultBadge?: boolean;
|
|
276
|
+
/**
|
|
277
|
+
* When `true` AND the user has at least one saved card, the list collapses
|
|
278
|
+
* into a compact preview row with a chevron-down toggle. Expanding shows the
|
|
279
|
+
* full list + Add button. Defaults to `false` (accounts-ui behaviour).
|
|
280
|
+
* flights-ui passes `true`.
|
|
281
|
+
*/
|
|
282
|
+
collapsible?: boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Controls the card label format inside rows.
|
|
285
|
+
* - `'branded'` (default): "Visa 4242" — brand name + last4
|
|
286
|
+
* - `'masked'`: "•••• 4242" — masked bullets + last4 (flights-ui style)
|
|
287
|
+
*/
|
|
288
|
+
cardLabelFormat?: 'masked' | 'branded';
|
|
154
289
|
className?: string;
|
|
155
290
|
}
|
|
156
291
|
|
|
@@ -171,6 +306,15 @@ export declare interface PaymentsConfig {
|
|
|
171
306
|
* consumers should override at boot once a prod CDN is set up.
|
|
172
307
|
*/
|
|
173
308
|
iconCdnBaseUrl?: string;
|
|
309
|
+
/**
|
|
310
|
+
* Custom `fetch` impl used by every API call in this package. Defaults to
|
|
311
|
+
* `globalThis.fetch`. Consumers that need auth-token refresh, CSRF-token
|
|
312
|
+
* injection, or any other request-shaping logic should provide their own
|
|
313
|
+
* wrapper here (e.g. one that retries on 401/403 after refreshing the
|
|
314
|
+
* session cookie). The package never adds business headers — that's the
|
|
315
|
+
* consumer's responsibility.
|
|
316
|
+
*/
|
|
317
|
+
fetch?: typeof fetch;
|
|
174
318
|
}
|
|
175
319
|
|
|
176
320
|
export declare const setPaymentsConfig: (config: Partial<PaymentsConfig>) => void;
|
|
@@ -231,6 +375,12 @@ export declare interface UseMovmoCardFieldsResult {
|
|
|
231
375
|
validity: CardFieldValidity;
|
|
232
376
|
/** Latest detected brand (or null if unknown). */
|
|
233
377
|
brand: string | null;
|
|
378
|
+
/**
|
|
379
|
+
* Live focus state for each iframe. True while the user is editing that
|
|
380
|
+
* field. Consumers use this to apply an "active" border on the iframe shell
|
|
381
|
+
* (the browser's `:focus-within` CSS doesn't propagate across iframes).
|
|
382
|
+
*/
|
|
383
|
+
focused: CardFieldFocus;
|
|
234
384
|
/**
|
|
235
385
|
* Programmatically move keyboard focus into one of the Spreedly iframes.
|
|
236
386
|
* No-op when the hook is not in the `'ready'` state. Used to auto-advance
|