@openrails/billing-ui 0.248.1 → 0.250.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 +37 -0
- package/README.md +40 -35
- package/dist/account/account-billing.d.ts +2 -2
- package/dist/account/cancel-dialog.d.ts +2 -2
- package/dist/account/change-card-dialog.d.ts +2 -2
- package/dist/account/payment-history.d.ts +2 -2
- package/dist/account/payment-methods-panel.d.ts +2 -2
- package/dist/account/section.d.ts +2 -2
- package/dist/account/subscriptions-panel.d.ts +2 -2
- package/dist/admin/context.d.ts +2 -2
- package/dist/admin/lib/queries.d.ts +1 -1
- package/dist/admin/messages.d.ts +3 -3
- package/dist/admin/pages/catalog/psp-links.d.ts +1 -1
- package/dist/admin/theme.d.ts +2 -2
- package/dist/admin/types.d.ts +2 -2
- package/dist/{admin-attempts-lAoW-Urd.js → admin-attempts-DxRHTODq.js} +8 -8
- package/dist/{admin-attempts-lAoW-Urd.js.map → admin-attempts-DxRHTODq.js.map} +1 -1
- package/dist/{admin-auth-DQGHtt0j.js → admin-auth-CiuZ-Hlm.js} +2 -2
- package/dist/{admin-auth-DQGHtt0j.js.map → admin-auth-CiuZ-Hlm.js.map} +1 -1
- package/dist/{admin-badge-DR5-1qd8.js → admin-badge-VCGbnfiN.js} +2 -2
- package/dist/{admin-badge-DR5-1qd8.js.map → admin-badge-VCGbnfiN.js.map} +1 -1
- package/dist/{admin-button-CTL3DgOt.js → admin-button-Oip73Plq.js} +2 -2
- package/dist/{admin-button-CTL3DgOt.js.map → admin-button-Oip73Plq.js.map} +1 -1
- package/dist/{admin-capabilities-BuigAgtm.js → admin-capabilities-BGv7oG8v.js} +2 -2
- package/dist/{admin-capabilities-BuigAgtm.js.map → admin-capabilities-BGv7oG8v.js.map} +1 -1
- package/dist/{admin-card-bzAks3-3.js → admin-card-DGbi6ZHZ.js} +2 -2
- package/dist/{admin-card-bzAks3-3.js.map → admin-card-DGbi6ZHZ.js.map} +1 -1
- package/dist/{admin-catalog-CK6CM9I2.js → admin-catalog-3pPEAuDY.js} +19 -19
- package/dist/{admin-catalog-CK6CM9I2.js.map → admin-catalog-3pPEAuDY.js.map} +1 -1
- package/dist/{admin-customers-D8u5gq3M.js → admin-customers-cnKMEV4q.js} +6 -6
- package/dist/{admin-customers-D8u5gq3M.js.map → admin-customers-cnKMEV4q.js.map} +1 -1
- package/dist/{admin-dashboard-DqqFjOzq.js → admin-dashboard-DfSsUyo-.js} +14 -14
- package/dist/{admin-dashboard-DqqFjOzq.js.map → admin-dashboard-DfSsUyo-.js.map} +1 -1
- package/dist/{admin-data-table-qfXLOFmN.js → admin-data-table-CgeWv__T.js} +6 -6
- package/dist/{admin-data-table-qfXLOFmN.js.map → admin-data-table-CgeWv__T.js.map} +1 -1
- package/dist/{admin-detail-X82kR2f7.js → admin-detail-BATuJjVs.js} +12 -12
- package/dist/{admin-detail-X82kR2f7.js.map → admin-detail-BATuJjVs.js.map} +1 -1
- package/dist/{admin-detail-DUAJQg8G.js → admin-detail-Cq59e14B.js} +15 -15
- package/dist/{admin-detail-DUAJQg8G.js.map → admin-detail-Cq59e14B.js.map} +1 -1
- package/dist/{admin-detail-BHe51ma9.js → admin-detail-DG-YaHhS.js} +11 -11
- package/dist/{admin-detail-BHe51ma9.js.map → admin-detail-DG-YaHhS.js.map} +1 -1
- package/dist/{admin-detail-CGOyqs7s.js → admin-detail-Dc7rU4mM.js} +15 -15
- package/dist/{admin-detail-CGOyqs7s.js.map → admin-detail-Dc7rU4mM.js.map} +1 -1
- package/dist/{admin-dialog-BjuKI5Hp.js → admin-dialog-Ffx95AIT.js} +3 -3
- package/dist/{admin-dialog-BjuKI5Hp.js.map → admin-dialog-Ffx95AIT.js.map} +1 -1
- package/dist/{admin-dom-uMmZzRvU.js → admin-dom-lnNSQ7ke.js} +4 -4
- package/dist/{admin-dom-uMmZzRvU.js.map → admin-dom-lnNSQ7ke.js.map} +1 -1
- package/dist/{admin-dropdown-menu-BW1D_h6s.js → admin-dropdown-menu-CCiW4-oz.js} +2 -2
- package/dist/{admin-dropdown-menu-BW1D_h6s.js.map → admin-dropdown-menu-CCiW4-oz.js.map} +1 -1
- package/dist/{admin-fact-card-DO_fHosg.js → admin-fact-card-D6mZgxpN.js} +2 -2
- package/dist/{admin-fact-card-DO_fHosg.js.map → admin-fact-card-D6mZgxpN.js.map} +1 -1
- package/dist/{admin-health-B4jN2LwR.js → admin-health-CvJX9prw.js} +13 -13
- package/dist/{admin-health-B4jN2LwR.js.map → admin-health-CvJX9prw.js.map} +1 -1
- package/dist/{admin-input-CcfQfJFN.js → admin-input-DO5lvCLL.js} +2 -2
- package/dist/{admin-input-CcfQfJFN.js.map → admin-input-DO5lvCLL.js.map} +1 -1
- package/dist/{admin-label-BiEN5cjb.js → admin-label-BzJpr3lg.js} +2 -2
- package/dist/{admin-label-BiEN5cjb.js.map → admin-label-BzJpr3lg.js.map} +1 -1
- package/dist/{admin-linked-table-row-BsaUruCN.js → admin-linked-table-row-5vFb6rXY.js} +4 -4
- package/dist/{admin-linked-table-row-BsaUruCN.js.map → admin-linked-table-row-5vFb6rXY.js.map} +1 -1
- package/dist/{admin-metering-COFcSPQy.js → admin-metering-BksTFRRP.js} +14 -14
- package/dist/{admin-metering-COFcSPQy.js.map → admin-metering-BksTFRRP.js.map} +1 -1
- package/dist/{admin-ops-B3mcr76u.js → admin-ops-Ch2-BmUp.js} +11 -11
- package/dist/{admin-ops-B3mcr76u.js.map → admin-ops-Ch2-BmUp.js.map} +1 -1
- package/dist/{admin-orders-dxC99Idl.js → admin-orders-8XzHf7b-.js} +8 -8
- package/dist/{admin-orders-dxC99Idl.js.map → admin-orders-8XzHf7b-.js.map} +1 -1
- package/dist/{admin-payments-Bs7HSfP0.js → admin-payments-pNLNIU0X.js} +9 -9
- package/dist/{admin-payments-Bs7HSfP0.js.map → admin-payments-pNLNIU0X.js.map} +1 -1
- package/dist/{admin-price-detail-DRquxpA9.js → admin-price-detail-BeGDPxKX.js} +11 -11
- package/dist/admin-price-detail-BeGDPxKX.js.map +1 -0
- package/dist/{admin-price-wizard-CI7K-2Nz.js → admin-price-wizard-ferZSTfO.js} +7 -7
- package/dist/{admin-price-wizard-CI7K-2Nz.js.map → admin-price-wizard-ferZSTfO.js.map} +1 -1
- package/dist/{admin-range-picker-Dr2M1EZr.js → admin-range-picker-DaIvC1oC.js} +5 -5
- package/dist/{admin-range-picker-Dr2M1EZr.js.map → admin-range-picker-DaIvC1oC.js.map} +1 -1
- package/dist/{admin-reports-CywKLiSA.js → admin-reports-CA-cnNur.js} +8 -8
- package/dist/{admin-reports-CywKLiSA.js.map → admin-reports-CA-cnNur.js.map} +1 -1
- package/dist/{admin-select-DBgprVW6.js → admin-select-CUXvh6j1.js} +2 -2
- package/dist/{admin-select-DBgprVW6.js.map → admin-select-CUXvh6j1.js.map} +1 -1
- package/dist/{admin-settings-Bmoy95uO.js → admin-settings-C6eWFkDn.js} +16 -16
- package/dist/{admin-settings-Bmoy95uO.js.map → admin-settings-C6eWFkDn.js.map} +1 -1
- package/dist/{admin-skeleton-DsM7crYi.js → admin-skeleton-DEY3Q8Dg.js} +2 -2
- package/dist/{admin-skeleton-DsM7crYi.js.map → admin-skeleton-DEY3Q8Dg.js.map} +1 -1
- package/dist/{admin-status-badge-BFPgo71d.js → admin-status-badge-CwqIU8tK.js} +2 -2
- package/dist/{admin-status-badge-BFPgo71d.js.map → admin-status-badge-CwqIU8tK.js.map} +1 -1
- package/dist/{admin-subscriptions-CLYc_HEV.js → admin-subscriptions-lJG_EzMe.js} +9 -9
- package/dist/{admin-subscriptions-CLYc_HEV.js.map → admin-subscriptions-lJG_EzMe.js.map} +1 -1
- package/dist/{admin-switch-BJUxLCsa.js → admin-switch-S4g_ppaU.js} +2 -2
- package/dist/{admin-switch-BJUxLCsa.js.map → admin-switch-S4g_ppaU.js.map} +1 -1
- package/dist/{admin-table-CH9TrXJf.js → admin-table-CWhiCb9d.js} +2 -2
- package/dist/{admin-table-CH9TrXJf.js.map → admin-table-CWhiCb9d.js.map} +1 -1
- package/dist/{admin-tabs-528FJMjt.js → admin-tabs-Cjm5a6UJ.js} +2 -2
- package/dist/{admin-tabs-528FJMjt.js.map → admin-tabs-Cjm5a6UJ.js.map} +1 -1
- package/dist/{admin-textarea-DEz38RaI.js → admin-textarea-DK1Fq31x.js} +2 -2
- package/dist/{admin-textarea-DEz38RaI.js.map → admin-textarea-DK1Fq31x.js.map} +1 -1
- package/dist/{admin-typed-confirm-dialog-DU7m9-O7.js → admin-typed-confirm-dialog-BloZvFPA.js} +6 -6
- package/dist/{admin-typed-confirm-dialog-DU7m9-O7.js.map → admin-typed-confirm-dialog-BloZvFPA.js.map} +1 -1
- package/dist/{admin-utils-BK4Vh1o_.js → admin-utils-DnVY5fYd.js} +3 -3
- package/dist/admin-utils-DnVY5fYd.js.map +1 -0
- package/dist/{admin-widget-viz-Da48c-Zf.js → admin-widget-viz-RCkxUspL.js} +8 -8
- package/dist/{admin-widget-viz-Da48c-Zf.js.map → admin-widget-viz-RCkxUspL.js.map} +1 -1
- package/dist/admin.js +31 -31
- package/dist/admin.js.map +1 -1
- package/dist/appearance.d.ts +7 -7
- package/dist/buy-button.d.ts +12 -18
- package/dist/cart.d.ts +4 -4
- package/dist/client/client.d.ts +12 -20
- package/dist/client/generated/error-codes.d.ts +1 -1
- package/dist/client/generated/routes.d.ts +10 -24
- package/dist/client/generated/wire.d.ts +75 -37
- package/dist/client/index.d.ts +1 -1
- package/dist/client/types.d.ts +17 -18
- package/dist/{client-DoRYitD3.js → client-HWr09qpX.js} +216 -233
- package/dist/client-HWr09qpX.js.map +1 -0
- package/dist/client.js +1 -1
- package/dist/embedded-payment.d.ts +25 -0
- package/dist/{hooks-DCSelDIZ.js → hooks-D9MR20BY.js} +7 -20
- package/dist/hooks-D9MR20BY.js.map +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +284 -272
- package/dist/index.js.map +1 -1
- package/dist/locales/de.js +1 -1
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/en.d.ts +1 -1
- package/dist/locales/en.js +1 -1
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +1 -1
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/ja.js +1 -1
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +1 -1
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +1 -1
- package/dist/locales/zh.js.map +1 -1
- package/dist/modal.d.ts +12 -3
- package/dist/{order-checkout.d.ts → order-payment.d.ts} +4 -4
- package/dist/product-list.d.ts +10 -16
- package/dist/psp.d.ts +2 -2
- package/dist/react/hooks.d.ts +2 -15
- package/dist/react/index.d.ts +1 -1
- package/dist/react/provider.d.ts +3 -3
- package/dist/react.js +2 -2
- package/dist/save-payment-method.d.ts +2 -2
- package/dist/scope-context.d.ts +4 -4
- package/dist/scope.d.ts +2 -2
- package/dist/tokenized-card-form.d.ts +2 -2
- package/docs/payment-form-contract.md +3 -3
- package/package.json +2 -2
- package/dist/admin-price-detail-DRquxpA9.js.map +0 -1
- package/dist/admin-utils-BK4Vh1o_.js.map +0 -1
- package/dist/client-DoRYitD3.js.map +0 -1
- package/dist/embedded-checkout.d.ts +0 -22
- package/dist/hooks-DCSelDIZ.js.map +0 -1
package/dist/react/provider.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { BillingAppearance } from '../appearance';
|
|
3
3
|
import { BillingClient } from '../client/client';
|
|
4
4
|
import { BillingUiMessageBundle, BillingUiTranslate } from '../i18n/messages';
|
|
5
5
|
import { Navigate } from '../scope-context';
|
|
@@ -7,13 +7,13 @@ import { BillingChange } from './context';
|
|
|
7
7
|
export interface BillingProviderProps {
|
|
8
8
|
/**
|
|
9
9
|
* The customer's client: hooks and the account panels read it, and a
|
|
10
|
-
*
|
|
10
|
+
* purchase saves a new card to the customer first. Leave it out where no
|
|
11
11
|
* customer is signed in, such as the shared payment page.
|
|
12
12
|
*/
|
|
13
13
|
client?: BillingClient;
|
|
14
14
|
/** Fires after each successful mutation: the host's cache-invalidation hook. */
|
|
15
15
|
onChange?: (change: BillingChange) => void;
|
|
16
|
-
appearance?:
|
|
16
|
+
appearance?: BillingAppearance;
|
|
17
17
|
/** Locale bundle(s) layered over English; later entries win. */
|
|
18
18
|
messages?: BillingUiMessageBundle | readonly BillingUiMessageBundle[];
|
|
19
19
|
/** Host translation hook, consulted before the bundles. */
|
package/dist/react.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, c as t, d as n,
|
|
2
|
-
export {
|
|
1
|
+
import { a as e, c as t, d as n, i as r, n as i, o as a, r as o, s, t as c, u as l } from "./hooks-D9MR20BY.js";
|
|
2
|
+
export { r as BillingProvider, t as useBillingClient, l as useBillingRefresh, e as useConfig, a as useCurrencyScales, s as useCustomerConfig, n as useOptionalBillingContext, c as usePaymentMethods, i as usePayments, o as useSubscriptions };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BillingAppearance } from './appearance';
|
|
2
2
|
import { PspConfig } from './psp';
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
export interface SavePaymentMethodProps {
|
|
@@ -8,7 +8,7 @@ export interface SavePaymentMethodProps {
|
|
|
8
8
|
/** Billing country to preselect; default: the browser locale's region. */
|
|
9
9
|
defaultCountry?: string;
|
|
10
10
|
submitLabel?: string;
|
|
11
|
-
appearance?:
|
|
11
|
+
appearance?: BillingAppearance;
|
|
12
12
|
className?: string;
|
|
13
13
|
}
|
|
14
14
|
/**
|
package/dist/scope-context.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CSSProperties } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { BillingAppearance, BillingTheme } from './appearance';
|
|
3
3
|
export type Navigate = (to: string) => void;
|
|
4
4
|
export interface UiSettings {
|
|
5
|
-
appearance?:
|
|
5
|
+
appearance?: BillingAppearance;
|
|
6
6
|
locale?: string;
|
|
7
7
|
navigate?: Navigate;
|
|
8
8
|
}
|
|
@@ -10,8 +10,8 @@ export declare const UiContext: import('react').Context<UiSettings>;
|
|
|
10
10
|
export declare const useUiSettings: () => UiSettings;
|
|
11
11
|
export interface ScopeProps {
|
|
12
12
|
className: string;
|
|
13
|
-
"data-orck-theme":
|
|
13
|
+
"data-orck-theme": BillingTheme;
|
|
14
14
|
style?: CSSProperties;
|
|
15
15
|
}
|
|
16
16
|
/** Props that make an element a styling root; portals carry them too. */
|
|
17
|
-
export declare function useScopeProps(appearance?:
|
|
17
|
+
export declare function useScopeProps(appearance?: BillingAppearance): ScopeProps;
|
package/dist/scope.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComponentProps } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { BillingAppearance } from './appearance';
|
|
3
3
|
/** Styling root for in-page billing surfaces. */
|
|
4
4
|
export declare function BillingUiRoot({ appearance, className, style, ...props }: ComponentProps<"div"> & {
|
|
5
|
-
appearance?:
|
|
5
|
+
appearance?: BillingAppearance;
|
|
6
6
|
}): import("react").JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BillingAppearance } from './appearance';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
export interface TokenizedCardData {
|
|
4
4
|
payment_token: string;
|
|
@@ -22,7 +22,7 @@ export interface TokenizedCardFormProps {
|
|
|
22
22
|
disabled?: boolean;
|
|
23
23
|
/** Billing country to preselect; default: the browser locale's region. */
|
|
24
24
|
defaultCountry?: string;
|
|
25
|
-
appearance?:
|
|
25
|
+
appearance?: BillingAppearance;
|
|
26
26
|
className?: string;
|
|
27
27
|
}
|
|
28
28
|
export declare function TokenizedCardForm({ tokenizationKey, tokenizationURL, onTokenized, submitLabel, disabled, defaultCountry, appearance, className, }: TokenizedCardFormProps): React.JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Payment form contract
|
|
2
2
|
|
|
3
|
-
`
|
|
3
|
+
`OrderPayment` renders one real `<form autocomplete="on">` and submits through
|
|
4
4
|
its native submit event. Every host-owned billing field has a stable `id`,
|
|
5
5
|
`name`, label, and standards-based autocomplete token.
|
|
6
6
|
|
|
@@ -42,7 +42,7 @@ autofill against the real gateway in each supported browser because a DOM unit
|
|
|
42
42
|
test cannot inspect or control the cross-origin fields.
|
|
43
43
|
|
|
44
44
|
A PSP that takes cards on OpenRails itself (`card_entry: server`) takes no
|
|
45
|
-
card on an order: `
|
|
45
|
+
card on an order: `OrderPayment` offers it for saved cards only, and the card
|
|
46
46
|
is saved first (`SavePaymentMethod`).
|
|
47
47
|
|
|
48
48
|
A new-card payment sends the one-time `token` and its `psp_id` plus
|
|
@@ -82,7 +82,7 @@ message, and the next pay is a new attempt under a new key.
|
|
|
82
82
|
`name_on_card`, `country` and `zip` to its async `onTokenized` callback. The host
|
|
83
83
|
provides explicit save-card consent and uses the callback to invoke its native
|
|
84
84
|
authenticated save-card endpoint. Set `disabled` until consent is given. The
|
|
85
|
-
form never creates a zero-dollar
|
|
85
|
+
form never creates a zero-dollar purchase or announces a completed payment.
|
|
86
86
|
After token submission it locks the form; a failed/unknown save must be checked
|
|
87
87
|
against the host's saved-method state before mounting a new attempt.
|
|
88
88
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openrails/billing-ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Embeddable OpenRails
|
|
3
|
+
"version": "0.250.0",
|
|
4
|
+
"description": "Embeddable OpenRails purchase and account-billing UI: client, React hooks and styled components.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"admin-price-detail-DRquxpA9.js","names":[],"sources":["../src/admin/pages/catalog/psp-links.tsx","../src/admin/pages/catalog/price-detail.tsx"],"sourcesContent":["import { AdminMessage } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { useQuery } from \"@tanstack/react-query\"\n\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport type { PSPRoutingSkip } from \"#orck/admin/lib/api/types\"\nimport type { PSPLinkState, Price } from \"#orck/client/generated/wire\"\n\n// The catalog is declarative: the provider adapter pushes prices and the\n// read-back reconciliation is alert-only, so this surface displays a price's\n// psp_links and never edits them. It answers two different questions:\n// - Link state (`price.providers`): does OpenRails hold a link for this PSP,\n// and does the remote object still match?\n// - Checkout readiness (the routing preview): would a real checkout land\n// here now? A linked price can still be unroutable (PSP unarmed,\n// credentials missing).\n\n// SKIP_LABELS renders the routing skip vocabulary for operators. Keep the keys\n// in lockstep with internal/db/models/checkout_attempt.go.\nconst SKIP_LABELS: Record<PSPRoutingSkip, string> = {\n unknown_selector: \"That name matches no provider you have set up.\",\n ambiguous_selector:\n \"More than one provider on this rail is set up. Name the provider rather than the rail.\",\n not_armed: \"This provider is not set up here, or it was archived.\",\n credentials_missing:\n \"The provider is set up, but the credentials it needs are missing.\",\n link_missing: \"This price has not been sent to the provider yet.\",\n mode_unsupported:\n \"This provider cannot take this kind of payment (one-off or recurring).\",\n posture_disarmed:\n \"The provider's credentials failed their test-mode check, so it is switched off.\",\n service_unavailable: \"The connection to this provider is not running.\",\n resolve_failed: \"The provider could not be worked out at the time of asking.\",\n}\n\n// The engine names each outcome for its own logs. These are the same outcomes\n// as a sentence you can act on.\nconst SKIP_HEADLINES: Record<PSPRoutingSkip, string> = {\n unknown_selector: \"unknown provider\",\n ambiguous_selector: \"more than one match\",\n not_armed: \"not set up\",\n credentials_missing: \"credentials missing\",\n link_missing: \"not sent to provider\",\n mode_unsupported: \"cannot take this payment\",\n posture_disarmed: \"credentials failed check\",\n service_unavailable: \"connection not running\",\n resolve_failed: \"could not be worked out\",\n}\n\nfunction skipHeadline(skip?: string | null): string {\n if (!skip) return \"ready\"\n return SKIP_HEADLINES[skip as PSPRoutingSkip] ?? skip\n}\n\nfunction skipLabel(skip?: string | null) {\n if (!skip) return \"\"\n return SKIP_LABELS[skip as PSPRoutingSkip] ?? skip\n}\n\nconst OK_BADGE = \"bg-settled-surface text-settled\"\nconst WARN_BADGE = \"bg-held-surface text-held\"\nconst BAD_BADGE = \"bg-failed-surface text-failed\"\n\nfunction linkStatusClass(status: PSPLinkState[\"status\"]) {\n if (status === \"linked\") return OK_BADGE\n if (status === \"error\") return BAD_BADGE\n return WARN_BADGE\n}\n\n// syncStatusClass leaves \"unknown\" neutral, not a warning: nobody has checked\n// yet.\nfunction syncStatusClass(sync?: string) {\n switch (sync) {\n case \"in_sync\":\n return OK_BADGE\n case \"drifted\":\n case \"missing\":\n return BAD_BADGE\n case \"never_synced\":\n case \"sync_disabled\":\n return WARN_BADGE\n default:\n return \"\"\n }\n}\n\n// LINK_ID_ORDER puts the identifying fields first; anything else the adapter\n// stored follows in sorted order. `rail` is pulled out into its own column.\nconst LINK_ID_ORDER = [\n \"price_id\",\n \"product_id\",\n \"plan_id\",\n \"form_name\",\n \"flex_id\",\n \"recurring_billing_option_id\",\n \"lookup_key\",\n \"provider\",\n]\n\nfunction linkEntries(ids?: Record<string, string> | null) {\n const rest = Object.entries(ids ?? {}).filter(\n ([k, v]) => k !== \"rail\" && v !== \"\"\n )\n rest.sort(([a], [b]) => {\n const ia = LINK_ID_ORDER.indexOf(a)\n const ib = LINK_ID_ORDER.indexOf(b)\n if (ia !== ib)\n return (\n (ia < 0 ? LINK_ID_ORDER.length : ia) -\n (ib < 0 ? LINK_ID_ORDER.length : ib)\n )\n return a.localeCompare(b)\n })\n return rest\n}\n\nexport function PSPLinksCard({\n price,\n verifying,\n verified,\n onVerify,\n}: {\n price: Price\n verifying: boolean\n verified: boolean\n onVerify: () => void\n}) {\n const links = Object.entries(price.psps ?? {}).sort(([a], [b]) =>\n a.localeCompare(b)\n )\n return (\n <Card>\n <CardHeader className=\"flex flex-row items-start justify-between gap-2\">\n <div className=\"grid gap-1\">\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Payment providers\"} />\n </CardTitle>\n <CardDescription>\n <AdminMessage\n id={\n \"Which providers this price has been sent to, and whether their copy still matches yours. Publishing the catalog is what sends it; this page only reports. Verify asks each provider what it currently holds, and changes nothing.\"\n }\n />\n </CardDescription>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={verifying || !links.length}\n onClick={onVerify}\n >\n {verifying ? \"Verifying…\" : \"Verify\"}\n </Button>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-3\">\n {!links.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage\n id={\n \"This price has not been sent to any provider, so nobody can be charged for it yet.\"\n }\n />\n </p>\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Provider\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Rail\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Sent\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Still matches\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Their reference\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {links.map(([psp, state]) => (\n <TableRow key={psp}>\n <TableCell className=\"font-mono text-xs\">{psp}</TableCell>\n <TableCell className=\"text-xs\">\n {state.ids?.rail ?? \"—\"}\n </TableCell>\n <TableCell>\n <Badge\n variant=\"secondary\"\n className={linkStatusClass(state.status)}\n >\n {state.status}\n </Badge>\n {state.message && (\n <p className=\"mt-1 max-w-xs text-xs text-muted-foreground\">\n {state.message}\n </p>\n )}\n </TableCell>\n <TableCell>\n <Badge\n variant=\"secondary\"\n className={syncStatusClass(state.sync_status)}\n >\n {state.sync_status ?? \"unknown\"}\n </Badge>\n {state.drift?.map((d) => (\n <p\n key={d.field}\n className=\"mt-1 text-xs text-muted-foreground\"\n >\n {d.field}\n <AdminMessage id={\": yours \"} />\n {d.openrails_value}\n <AdminMessage id={\" · theirs\"} /> {d.remote_value}\n </p>\n ))}\n </TableCell>\n <TableCell className=\"font-mono text-xs\">\n {linkEntries(state.ids).length ? (\n <div className=\"grid gap-0.5\">\n {linkEntries(state.ids).map(([k, v]) => (\n <span key={k}>\n {k}={v}\n </span>\n ))}\n </div>\n ) : (\n \"—\"\n )}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n {!!price.pending_manual_actions?.length && (\n <div className=\"border-held/40 rounded-md border p-3 text-xs\">\n {price.pending_manual_actions.map((a) => (\n <p key={`${a.psp}-${a.action}`}>\n <span className=\"font-mono\">{a.psp}</span>: {a.hint || a.action}\n </p>\n ))}\n </div>\n )}\n {!verified && !!links.length && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n \"Nothing is claimed about the providers' copies until you press Verify.\"\n }\n />\n </p>\n )}\n </CardContent>\n </Card>\n )\n}\n\n// CheckoutReadinessCard answers \"can someone buy this right now, and if not,\n// why?\" with the routing preview, so the console and checkout never disagree.\nexport function CheckoutReadinessCard({ price }: { price: Price }) {\n const { adminQueries } = useAdminServices()\n\n const {\n data: decision,\n isFetching: busy,\n refetch: reload,\n } = useQuery(adminQueries.checkoutRouting(price.id))\n\n const eligible = decision?.candidates.filter((c) => !c.skip) ?? []\n\n return (\n <Card>\n <CardHeader className=\"flex flex-row items-start justify-between gap-2\">\n <div className=\"grid gap-1\">\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Can this be bought?\"} />\n </CardTitle>\n <CardDescription>\n <AdminMessage\n id={\n \"Which provider would take the money if someone bought this right now, and why the others were passed over. This asks the same question a real checkout asks, without starting one.\"\n }\n />\n </CardDescription>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n onClick={() => void reload()}\n >\n {busy ? \"Checking…\" : \"Re-check\"}\n </Button>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-3\">\n {!decision ? (\n <p className=\"text-sm text-muted-foreground\">\n {busy ? \"Checking…\" : \"This check could not be run.\"}\n </p>\n ) : (\n <>\n <p className=\"text-sm\">\n {decision.psp ? (\n <>\n <AdminMessage id={\"Money for this price would go to\"} />{\" \"}\n <span className=\"font-medium\">{decision.psp}</span>\n {decision.rail && (\n <>\n <AdminMessage id={\" on \"} />\n {decision.rail}\n </>\n )}\n .\n </>\n ) : (\n <span className=\"text-held\">\n <AdminMessage\n id={\n \"No provider can take this payment, so nobody can buy this price yet.\"\n }\n />\n </span>\n )}\n </p>\n {!decision.candidates.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"There were no providers to consider.\"} />\n </p>\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Provider\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Rail\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Outcome\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Why\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {decision.candidates.map((c) => (\n <TableRow key={c.psp}>\n <TableCell className=\"font-mono text-xs\">\n {c.psp}\n {c.psp === decision.psp && (\n <Badge\n variant=\"secondary\"\n className={`ml-2 ${OK_BADGE}`}\n >\n <AdminMessage id={\"selected\"} />\n </Badge>\n )}\n </TableCell>\n <TableCell className=\"text-xs\">\n {c.rail || \"—\"}\n </TableCell>\n <TableCell>\n <Badge\n variant=\"secondary\"\n className={c.skip ? WARN_BADGE : OK_BADGE}\n >\n {skipHeadline(c.skip)}\n </Badge>\n </TableCell>\n <TableCell className=\"text-xs text-muted-foreground\">\n {skipLabel(c.skip)}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n {!!decision.candidates.length && eligible.length === 0 && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n '\"Not sent to provider\" is fixed by publishing the catalog. Everything else is fixed under Settings, Payment providers.'\n }\n />\n </p>\n )}\n </>\n )}\n </CardContent>\n </Card>\n )\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport { ArrowLeft01Icon } from \"@hugeicons/core-free-icons\"\nimport * as React from \"react\"\nimport { Link, useLocation, useNavigate } from \"#orck/admin/router\"\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Fact } from \"#orck/admin/components/fact-card\"\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { useConfirm } from \"#orck/admin/lib/confirm\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport { formatDate, shortId } from \"#orck/admin/lib/format\"\n\nimport {\n priceAmountLabel,\n priceIntervalLabel,\n} from \"#orck/admin/pages/catalog/price-format\"\nimport { PriceChangeWizard } from \"#orck/admin/pages/catalog/price-wizard\"\nimport {\n CheckoutReadinessCard,\n PSPLinksCard,\n} from \"#orck/admin/pages/catalog/psp-links\"\nimport { useCatalogWrites } from \"#orck/admin/lib/capabilities\"\n\n// A price ID can contain its own percent-encoded key bytes. Router params\n// decode an inner %2F again; decode the original URL segment exactly once.\nfunction priceIDFromPath(pathname: string): string {\n const segment = pathname.replace(/\\/+$/, \"\").split(\"/\").at(-1) ?? \"\"\n try {\n return decodeURIComponent(segment)\n } catch {\n return \"\"\n }\n}\n\n// PriceDetailPage (#777): the version chain (from the #774 pointer-movement\n// log, with dates) and any pending scheduled migration (progress + cancel)\n// for one price key — the wizard's Step 1 entry point (\"Change price\") also\n// lives here alongside the catalog list row.\nexport function PriceDetailPage() {\n const { text: adminText } = useAdminUI()\n\n const { adminQueries } = useAdminServices()\n\n const id = priceIDFromPath(useLocation().pathname)\n const writesAllowed = useCatalogWrites()\n const navigate = useNavigate()\n // verify (or#812) is opt-in: it makes GET price perform a live retrieve\n // against every attached provider, which is a network round trip per PSP.\n const [verify, setVerify] = React.useState(false)\n const {\n data: price,\n isPending: loading,\n isFetching,\n refetch: reload,\n } = useQuery(adminQueries.price(id, { verify, errorAction: \"Load price\" }))\n const { data: product } = useQuery(adminQueries.product(price?.product_id))\n const { data: history } = useQuery(adminQueries.priceHistory(price?.id))\n const { data: migrations } = useQuery(\n adminQueries.priceMigrations(product?.key, price?.key)\n )\n const latestBatch = migrations?.data?.[0]\n\n if (!id)\n return (\n <p role=\"alert\" className=\"text-sm text-muted-foreground\">\n Invalid price URL.\n </p>\n )\n\n // Only the FIRST load blanks the page; a verify refetch keeps the rendered\n // price in place so the button can show its own in-flight state.\n if (!price)\n return (\n <p className=\"text-sm text-muted-foreground\">\n {loading ? \"Loading…\" : \"Price not found.\"}\n </p>\n )\n\n const isPending = !!latestBatch && latestBatch.scheduled > 0\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => navigate(-1)}\n aria-label={adminText(\"Back\")}\n >\n <HugeiconsIcon icon={ArrowLeft01Icon} className=\"size-4\" />\n </Button>\n <div>\n <h2 className=\"flex items-center gap-2 text-sm\">\n {price.id}\n {price.archived && (\n <Badge variant=\"secondary\">\n <AdminMessage id={\"archived\"} />\n </Badge>\n )}\n </h2>\n <p className=\"text-xs text-muted-foreground\">\n {product?.display_name}\n </p>\n </div>\n <div className=\"ml-auto\">\n {writesAllowed && (\n <PriceChangeWizard\n price={price}\n productName={product?.display_name ?? \"…\"}\n productKey={product?.key}\n />\n )}\n </div>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <Fact label={adminText(\"Product\")}>\n <Link className=\"underline-offset-2 hover:underline\" to={`/catalog`}>\n {product?.display_name ?? shortId(price.product_id, 13)}\n </Link>\n </Fact>\n <Fact label={adminText(\"Amount\")}>{priceAmountLabel(price)}</Fact>\n <Fact label={adminText(\"Renews\")}>\n {price.currency.toUpperCase()} · {priceIntervalLabel(price)}\n </Fact>\n <Fact label={adminText(\"Created\")}>{formatDate(price.created_at)}</Fact>\n </div>\n\n <PSPLinksCard\n price={price}\n verifying={verify && isFetching}\n verified={verify}\n onVerify={() => (verify ? void reload() : setVerify(true))}\n />\n\n <CheckoutReadinessCard price={price} />\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Price history\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {!history?.data?.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"No history yet.\"} />\n </p>\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Amount\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Since\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"State\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Price\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {history.data.map((entry) => (\n <TableRow key={`${entry.price.id}-${entry.effective_at}`}>\n <TableCell>{priceAmountLabel(entry.price)}</TableCell>\n <TableCell>{formatDate(entry.effective_at)}</TableCell>\n <TableCell>\n {entry.archived ? (\n <Badge variant=\"secondary\">\n <AdminMessage id={\"retired\"} />\n </Badge>\n ) : (\n <Badge className=\"bg-settled-surface text-settled\">\n <AdminMessage id={\"offered\"} />\n </Badge>\n )}\n </TableCell>\n <TableCell>\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/catalog/prices/${encodeURIComponent(entry.price.id)}`}\n title={entry.price.id}\n >\n {entry.price.id}\n </Link>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </CardContent>\n </Card>\n\n {latestBatch && (\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between gap-2\">\n <CardTitle className=\"text-sm\">\n {isPending\n ? \"Moving customers to the new price\"\n : \"Last move to a new price\"}\n </CardTitle>\n {isPending && (\n <CancelMigrationButton migrationId={latestBatch.id} />\n )}\n </CardHeader>\n <CardContent className=\"flex flex-col gap-2 text-sm\">\n <p>\n {latestBatch.applied}\n <AdminMessage id={\" of\"} />{\" \"}\n {latestBatch.applied +\n latestBatch.scheduled +\n latestBatch.canceled}{\" \"}\n <AdminMessage id={\"moved\"} />\n {latestBatch.scheduled > 0 &&\n ` · ${latestBatch.scheduled} still scheduled`}\n {\" · effective\"}\n {formatDate(latestBatch.effective_at)}\n </p>\n {latestBatch.skipped > 0 && (\n <p className=\"text-xs text-muted-foreground\">\n {latestBatch.skipped}\n <AdminMessage id={\" subscription\"} />\n {latestBatch.skipped === 1 ? \" was\" : \"s were\"}\n <AdminMessage\n id={\n \" left alone because another change was already scheduled for them.\"\n }\n />\n </p>\n )}\n </CardContent>\n </Card>\n )}\n </div>\n )\n}\n\nfunction CancelMigrationButton({ migrationId }: { migrationId: string }) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const queryClient = useQueryClient()\n const cancelBatch = useMutation(\n adminMutations.cancelPriceMigration(queryClient)\n )\n const confirm = useConfirm()\n return (\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={cancelBatch.isPending}\n onClick={async () => {\n const canceling = await confirm({\n title: \"Cancel this migration?\",\n description:\n \"Subscribers not yet moved stay on their current price. Those already moved stay moved.\",\n confirmLabel: \"Cancel migration\",\n cancelLabel: \"Keep migrating\",\n tone: \"destructive\",\n })\n if (!canceling) return\n try {\n const result = await cancelBatch.mutateAsync(migrationId)\n toast.success(\n `Canceled ${result.canceled} pending move${result.canceled === 1 ? \"\" : \"s\"}. Already-migrated subscribers stay migrated.`\n )\n const release = result.rail_release_required.length\n if (release > 0)\n toast.warning(\n `${release} Stripe subscription${release === 1 ? \" still carries\" : \"s still carry\"} the move as a Stripe subscription schedule: release it in Stripe, or the price changes at period end.`\n )\n } catch (err) {\n toastApiError(err, \"Cancel migration\")\n }\n }}\n >\n {cancelBatch.isPending ? \"Canceling…\" : \"Cancel migration\"}\n </Button>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"admin-utils-BK4Vh1o_.js","names":[],"sources":["../src/admin/ui-context.tsx","../src/admin/lib/api/client.ts","../src/admin/lib/api/endpoints.ts","../src/admin/lib/api/metrics.ts","../src/admin/lib/api/copilot.ts","../src/admin/lib/api/credit-endpoints.ts","../src/admin/lib/api/order-endpoints.ts","../src/admin/lib/api/invoice-profile-endpoints.ts","../src/admin/lib/api/index.ts","../src/admin/lib/toast.ts","../src/admin/lib/queries.ts","../src/admin/lib/mutations.ts","../src/admin/lib/credit-queries.ts","../src/admin/lib/order-queries.ts","../src/admin/context.tsx","../src/admin/router.tsx","../src/admin/lib/utils.ts"],"sourcesContent":["import { createContext, useContext } from \"react\"\n\nexport const AdminUIContext = createContext<{\n namespace: string\n messages?: Record<string, string>\n}>({ namespace: \"\" })\n\nexport function useAdminUI() {\n const context = useContext(AdminUIContext)\n function id(value: string): string\n function id(value: string | undefined): string | undefined\n function id(value: string | undefined) {\n return value === undefined ? undefined : `${context.namespace}${value}`\n }\n return {\n text: (message: string) => context.messages?.[message] ?? message,\n id,\n }\n}\n\nexport function AdminMessage({ id }: { id: string }) {\n return useAdminUI().text(id)\n}\n","import type { BillingAdminAuth, BillingAdminResource } from \"../../types\"\nimport type { OpenRailsErrorCode } from \"../../../client/generated/error-codes\"\nimport type { ListPage } from \"../../../client/generated/wire\"\n\n// Stripe-shaped error envelope (internal/api); codes are billing.ErrorCodes.\nexport interface ApiErrorBody {\n error?: {\n type?: string\n code?: OpenRailsErrorCode\n message?: string\n param?: string\n metadata?: Record<string, unknown>\n }\n}\n\nexport class ApiError extends Error {\n status: number\n type?: string\n code?: OpenRailsErrorCode\n param?: string\n metadata?: Record<string, unknown>\n\n constructor(status: number, body: ApiErrorBody | null, fallback: string) {\n super(body?.error?.message || fallback)\n this.status = status\n this.type = body?.error?.type\n this.code = body?.error?.code\n this.param = body?.error?.param\n this.metadata = body?.error?.metadata\n }\n\n get isPermissionDenied() {\n return this.status === 403\n }\n\n // The object changed since the revision the request named.\n get revisionMismatch() {\n return this.status === 409 && this.code === \"revision_mismatch\"\n }\n\n // The merchant's configuration is read from a file: no edit applies.\n get merchantConfigReadOnly() {\n return this.status === 409 && this.code === \"merchant_config_read_only\"\n }\n}\n\nasync function parseError(res: Response): Promise<ApiError> {\n let body: ApiErrorBody | null = null\n try {\n body = (await res.json()) as ApiErrorBody\n } catch {\n // non-JSON error body\n }\n return new ApiError(res.status, body, `request failed (${res.status})`)\n}\n\nexport interface RequestOptions {\n method?: string\n body?: unknown\n // Preserve catalog JSON/YAML bytes and exact monetary literals.\n rawBody?: string\n headers?: Record<string, string>\n query?: Record<string, string | number | boolean | undefined>\n signal?: AbortSignal\n}\n\nfunction buildURL(base: string, path: string, query?: RequestOptions[\"query\"]) {\n let url = base + path\n if (query) {\n const params = new URLSearchParams()\n for (const [k, v] of Object.entries(query)) {\n if (v !== undefined && v !== \"\") params.set(k, String(v))\n }\n const qs = params.toString()\n if (qs) url += `?${qs}`\n }\n return url\n}\n\nexport interface ApiResponse<T> {\n status: number\n body: T\n}\n\n// One cursor page request: cursor is the previous page's next_cursor.\nexport interface PageRequest {\n limit?: number\n cursor?: string\n}\n\n// collectCursorPages walks a cursor list to its end.\nexport async function collectCursorPages<T>(\n loadPage: (cursor?: string) => Promise<ListPage<T>>,\n signal?: AbortSignal\n): Promise<T[]> {\n const rows: T[] = []\n let cursor: string | undefined\n for (;;) {\n signal?.throwIfAborted()\n const page = await loadPage(cursor)\n rows.push(...page.data)\n if (!page.next_cursor) return rows\n if (page.next_cursor === cursor)\n throw new Error(\"List paging stopped before all records were loaded\")\n cursor = page.next_cursor\n }\n}\n\n// The cursor list envelope: next_cursor is null on the last page.\nexport interface CursorEnvelope<T> {\n data: T[]\n next_cursor: string | null\n}\n\nexport interface AdminClientOptions {\n namespace?: string\n isCurrent?: () => boolean\n baseUrl: string\n auth: BillingAdminAuth\n merchant?: { id: string; slug: string }\n exchange?: Omit<BillingAdminResource, \"group\">\n}\n\n/** One immutable transport per component and selected merchant. */\nexport function createAdminClient(options: AdminClientOptions) {\n const baseUrl = options.baseUrl.replace(/\\/$/, \"\")\n const selectedMerchant = () =>\n options.isCurrent && !options.isCurrent()\n ? undefined\n : options.merchant?.slug\n async function send<T>(\n path: string,\n opts: RequestOptions\n ): Promise<ApiResponse<T>> {\n const headers: Record<string, string> = { ...opts.headers }\n if (opts.body !== undefined) headers[\"Content-Type\"] = \"application/json\"\n const init: RequestInit = {\n method: opts.method ?? \"GET\",\n headers,\n signal: opts.signal,\n body:\n opts.rawBody ??\n (opts.body !== undefined ? JSON.stringify(opts.body) : undefined),\n }\n const url = buildURL(baseUrl, path, opts.query)\n let res: Response\n if (options.exchange) {\n if (!options.merchant?.id || !options.auth.resourceFetch)\n throw new Error(\n \"Merchant token exchange needs a merchant id and resourceFetch transport\"\n )\n try {\n res = await options.auth.resourceFetch(url, {\n ...init,\n ...options.exchange,\n group: options.merchant.id,\n })\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"error\" in error &&\n error.error === \"invalid_target\"\n )\n throw new ApiError(\n 403,\n {\n error: {\n code: \"merchant_unresolved\",\n message: \"You hold no role at this merchant.\",\n },\n },\n \"Merchant refused\"\n )\n throw error\n }\n } else {\n res = await options.auth.authFetch(url, init)\n }\n if (!res.ok) throw await parseError(res)\n return {\n status: res.status,\n body: (res.status === 204 ? undefined : await res.json()) as T,\n }\n }\n async function apiResponse<T>(\n path: string,\n opts: RequestOptions = {}\n ): Promise<ApiResponse<T>> {\n return send<T>(path, opts)\n }\n const api = async <T>(path: string, opts: RequestOptions = {}) =>\n (await apiResponse<T>(path, opts)).body\n const queryRoot = (requested?: string) => {\n const merchant =\n requested !== undefined &&\n requested !== options.merchant?.slug &&\n requested !== options.merchant?.id\n ? requested\n : options.merchant?.id || options.merchant?.slug || \"unselected\"\n return [\n ...(options.namespace ? [\"billing-admin\", options.namespace] : []),\n \"merchant\",\n merchant,\n ] as const\n }\n return {\n namespace: options.namespace,\n api,\n apiResponse,\n selectedMerchant,\n queryRoot,\n }\n}\nexport type AdminClient = ReturnType<typeof createAdminClient>\n","import type { AdminClient } from \"./client\"\nimport { type CursorEnvelope, type PageRequest } from \"./client\"\n\nimport type {\n AdminAccess,\n AlertWebhook,\n Allowance,\n CatalogApplicationReceipt,\n CreateAlertWebhookParams,\n CreatePSPParams,\n PSPRefresh,\n CreatePriceParams,\n Customer,\n ListPage,\n MerchantConfigurationState,\n Meter,\n PSP,\n Payment,\n PaymentAttempt,\n PaymentMethod,\n Price,\n PriceKeyMovement,\n Product,\n PublicConfig,\n RatePrice,\n Renewal,\n RefundPaymentParams,\n UpdateAlertWebhookParams,\n UpdateCustomerParams,\n UpdateMerchantConfigurationParams,\n UpdatePSPParams,\n UpdatePriceParams,\n UpdateProductParams,\n} from \"#orck/client/generated/wire\"\n\nimport type {\n AdminSubscription,\n CustomerEntitlement,\n Finding,\n PSPRoutingPreview,\n RawProductAccessGrant,\n PriceMigration,\n PriceMigrationCancel,\n PriceMigrationPreview,\n ChangeSubscriptionParams,\n SubscriptionChange,\n SubscriptionChangePreview,\n} from \"./types\"\n\nexport interface ProductGrant {\n productId: string\n hours?: number\n endsAt?: string\n reason?: \"comp\" | \"staff\"\n note?: string\n}\n\n// --- Subscriptions ---\n\nexport interface SubscriptionFilters {\n status?: string\n // dunning \"true\" keeps the subscriptions past_due or awaiting_method.\n dunning?: string\n rail?: string\n customer_id?: string\n price_id?: string\n // UTC dates (YYYY-MM-DD).\n expires_before?: string\n canceled_after?: string\n // created_at (newest first), current_period_ends_at (soonest first) or\n // canceled_at (latest first).\n sort?: string\n}\n\n// --- Payments ---\n\n// Payments are listed newest first.\nexport interface PaymentFilters {\n customer_id?: string\n subscription_id?: string\n order_id?: string\n status?: Payment[\"status\"]\n rail?: string\n kind?: Payment[\"kind\"]\n transaction_id?: string\n}\n\n// --- Payment attempts and renewals (#1116) ---\n// Filters are the API's query parameters verbatim; a text filter is one value\n// or a comma-separated list, so a console URL carries them unchanged.\n\nexport type AttemptFilters = Partial<\n Record<(typeof ATTEMPT_FILTERS)[number], string>\n>\n\nexport const ATTEMPT_FILTERS = [\n \"kind\",\n \"owner\",\n \"category\",\n \"reason\",\n \"response_code\",\n \"card_entry\",\n \"source\",\n \"observed_via\",\n \"avs_result\",\n \"cvv_result\",\n \"psp_id\",\n \"customer_id\",\n \"payment_id\",\n \"order_id\",\n \"subscription_id\",\n \"cycle_id\",\n \"since\",\n \"until\",\n] as const\n\nexport type CycleFilters = Partial<\n Record<(typeof CYCLE_FILTERS)[number], string>\n>\n\nexport const CYCLE_FILTERS = [\n \"owner\",\n \"first_outcome\",\n \"miss_reason\",\n \"outcome\",\n \"psp_id\",\n \"subscription_id\",\n \"due_since\",\n \"due_until\",\n] as const\n\n// filtersFrom reads the named filters from a console URL.\nexport function filtersFrom<K extends string>(\n params: URLSearchParams,\n keys: readonly K[]\n): Partial<Record<K, string>> {\n const out: Partial<Record<K, string>> = {}\n for (const key of keys) {\n const v = params.get(key)?.trim()\n if (v) out[key] = v\n }\n return out\n}\n\n// Rails whose refunds route through a provider API today (admin_payments.go);\n// off-rail payments are refunded where they were taken.\nexport const REFUNDABLE_RAILS = [\"nmi\", \"stripe\"]\n\n// --- Catalog ---\n\n// PAGE_MAX is the largest page a list route serves.\nexport const PAGE_MAX = 500\n\nexport interface ProductRequest {\n key: string\n display_name: string\n description: string\n tier_group?: string\n tier_rank?: number\n entitlements?: string[]\n}\n\nexport interface UsageMeterRequest {\n event_type: string\n value_property: string\n aggregation: \"sum\" | \"count\"\n unit?: string\n group_by: Record<string, string>\n // Omitted keeps the meter's rate card; null removes it.\n rate_card?: DefaultUsageRateCardRequest | null\n // The meter's revision this edit read; 0 for a new meter.\n expected_revision?: number\n}\n\nexport interface DefaultUsageRateCardRequest {\n product_id: string\n filter: Record<string, string[]>\n price: RatePrice\n allowance?: Allowance\n}\n\nexport type { CatalogApplicationReceipt } from \"#orck/client/generated/wire\"\nexport function createEndpoints(client: AdminClient) {\n const { api } = client\n\n // --- Customers ---\n\n const listCustomers = (\n search: string,\n limit: number,\n cursor: string,\n signal?: AbortSignal\n ) =>\n api<ListPage<Customer>>(\"/admin/customers\", {\n query: { search, limit, cursor },\n signal,\n })\n\n // getCustomer is one customer: settings, and per currency its balance,\n // arrears and collection card. Its lists are their own routes.\n const getCustomer = (customerId: string, signal?: AbortSignal) =>\n api<Customer>(`/admin/customers/${customerId}`, { signal })\n\n const listCustomerEntitlements = (\n customerId: string,\n page: PageRequest,\n signal?: AbortSignal\n ) =>\n api<ListPage<CustomerEntitlement>>(\"/admin/entitlements\", {\n query: { customer_id: customerId, ...page },\n signal,\n })\n\n const listCustomerProductAccess = (\n customerId: string,\n page: PageRequest,\n signal?: AbortSignal\n ) =>\n api<ListPage<RawProductAccessGrant>>(\"/admin/product-access\", {\n query: { customer_id: customerId, ...page },\n signal,\n })\n\n const listCustomerPaymentMethods = (\n customerId: string,\n page: PageRequest,\n signal?: AbortSignal\n ) =>\n api<ListPage<PaymentMethod>>(\n `/admin/customers/${customerId}/payment-methods`,\n { query: { ...page }, signal }\n )\n\n // grantProductAccess grants one product free; the customer holds its keys\n // while the grant is live.\n const grantProductAccess = (customerId: string, grant: ProductGrant) =>\n api<{ items: RawProductAccessGrant[] }>(`/admin/product-access`, {\n method: \"POST\",\n body: {\n items: [\n {\n customer_id: customerId,\n product_id: grant.productId,\n ...(grant.hours ? { hours: grant.hours } : {}),\n ...(grant.endsAt ? { ends_at: grant.endsAt } : {}),\n ...(grant.reason ? { reason: grant.reason } : {}),\n ...(grant.note ? { note: grant.note } : {}),\n },\n ],\n },\n })\n\n // revokeProductAccess takes a product back; the window keeps its row and the\n // reason.\n const revokeProductAccess = (grantId: string, reason: string) =>\n api<void>(`/admin/product-access/${grantId}/revoke`, {\n method: \"POST\",\n body: { reason },\n })\n\n const listSubscriptions = (\n filters: SubscriptionFilters,\n limit: number,\n cursor?: string,\n signal?: AbortSignal\n ) =>\n api<CursorEnvelope<AdminSubscription>>(\"/admin/subscriptions\", {\n query: { ...filters, limit, ...(cursor ? { cursor } : {}) },\n signal,\n })\n\n const getSubscription = (id: string, signal?: AbortSignal) =>\n api<AdminSubscription>(`/admin/subscriptions/${id}`, { signal })\n\n const cancelSubscription = (\n id: string,\n reason: string,\n revokeAccess: boolean\n ) =>\n api<AdminSubscription>(`/admin/subscriptions/${id}/cancel`, {\n method: \"POST\",\n body: { reason, revoke_access: revokeAccess },\n })\n\n const resumeSubscription = (id: string) =>\n api<AdminSubscription>(`/admin/subscriptions/${id}/resume`, {\n method: \"POST\",\n })\n\n // null makes the subscription follow the customer's default card.\n const changeSubscriptionPaymentMethod = (\n id: string,\n paymentMethodId: string | null\n ) =>\n api<AdminSubscription>(`/admin/subscriptions/${id}/payment-method`, {\n method: \"PUT\",\n body: { payment_method_id: paymentMethodId },\n })\n\n const previewSubscriptionChange = (\n id: string,\n change: ChangeSubscriptionParams\n ) =>\n api<SubscriptionChangePreview>(\n `/admin/subscriptions/${id}/change/preview`,\n {\n method: \"POST\",\n body: change,\n }\n )\n\n // A change is a durable operation keyed by this header: the same key replays\n // its result, so a retry must reuse the key of the reviewed change.\n const changeSubscription = (\n id: string,\n change: ChangeSubscriptionParams,\n idempotencyKey: string\n ) =>\n api<SubscriptionChange>(`/admin/subscriptions/${id}/change`, {\n method: \"POST\",\n headers: { \"Idempotency-Key\": idempotencyKey },\n body: change,\n })\n\n const listPayments = (\n filters: PaymentFilters,\n page: PageRequest,\n signal?: AbortSignal\n ) =>\n api<ListPage<Payment>>(\"/admin/payments\", {\n query: { ...filters, ...page },\n signal,\n })\n\n const getPayment = (id: string, signal?: AbortSignal) =>\n api<Payment>(`/admin/payments/${id}`, { signal })\n\n // refundPayment answers the refund: succeeded, or pending (202) while the\n // rail settles it.\n const refundPayment = (\n id: string,\n amount: string,\n reason: string,\n revokeAccess: boolean\n ) => {\n const body: RefundPaymentParams = {\n amount,\n reason: reason || undefined,\n revoke_access: revokeAccess,\n }\n return api<Payment>(`/admin/payments/${id}/refunds`, {\n method: \"POST\",\n headers: { \"Idempotency-Key\": crypto.randomUUID() },\n body,\n })\n }\n\n const listPaymentAttempts = (\n filters: AttemptFilters,\n page: PageRequest,\n signal?: AbortSignal\n ) =>\n api<ListPage<PaymentAttempt>>(\"/admin/payment-attempts\", {\n query: { ...filters, ...page },\n signal,\n })\n\n const getPaymentAttempt = (id: string, signal?: AbortSignal) =>\n api<PaymentAttempt>(`/admin/payment-attempts/${id}`, { signal })\n\n const listRenewals = (\n filters: CycleFilters,\n page: PageRequest,\n signal?: AbortSignal\n ) =>\n api<ListPage<Renewal>>(\"/admin/renewals\", {\n query: { ...filters, ...page },\n signal,\n })\n\n const getRenewal = (id: string, signal?: AbortSignal) =>\n api<Renewal>(`/admin/renewals/${id}`, { signal })\n\n // archived: false lists live products, true archived ones, undefined both.\n // Each product carries its current prices.\n const listProducts = (\n limit: number,\n cursor?: string,\n archived?: boolean,\n signal?: AbortSignal\n ) =>\n api<ListPage<Product>>(\"/catalog/products\", {\n query: { limit, cursor, archived },\n signal,\n })\n\n const getProduct = (id: string, signal?: AbortSignal) =>\n api<Product>(`/catalog/products/${id}`, { signal })\n\n const createProduct = (body: ProductRequest) =>\n api<Product>(\"/catalog/products\", { method: \"POST\", body })\n\n // updateProduct is a merge patch: omitted fields stay, null clears\n // description and tier_group; entitlements: [] clears the granted keys.\n const updateProduct = (id: string, body: UpdateProductParams) =>\n api<Product>(`/catalog/products/${id}`, {\n method: \"PATCH\",\n body,\n })\n\n const listUsageMeters = (\n limit = PAGE_MAX,\n cursor?: string,\n signal?: AbortSignal\n ) =>\n api<ListPage<Meter>>(\"/catalog/meters\", {\n query: { limit, cursor },\n signal,\n })\n\n const getUsageMeter = (key: string, signal?: AbortSignal) =>\n api<Meter>(`/catalog/meters/${encodeURIComponent(key)}`, {\n signal,\n })\n\n const putUsageMeter = (key: string, body: UsageMeterRequest) =>\n api<Meter>(`/catalog/meters/${encodeURIComponent(key)}`, {\n method: \"PUT\",\n body,\n })\n\n // putUsageMeterRateCard sets a meter's rate card, or removes it with null.\n // The rate card is a field of the meter, so the meter is restated with it.\n const putUsageMeterRateCard = (\n meter: Meter,\n rateCard: DefaultUsageRateCardRequest | null\n ) =>\n putUsageMeter(meter.key, {\n event_type: meter.event_type,\n value_property: meter.value_property,\n aggregation: meter.aggregation as UsageMeterRequest[\"aggregation\"],\n unit: meter.unit,\n group_by: meter.group_by ?? {},\n rate_card: rateCard,\n expected_revision: meter.revision,\n })\n\n const listPrices = (\n limit: number,\n cursor?: string,\n productId?: string,\n signal?: AbortSignal\n ) =>\n api<ListPage<Price>>(\"/catalog/prices\", {\n query: { limit, cursor, product_id: productId },\n signal,\n })\n\n // A price that declares the key of a live price with other terms becomes\n // its new version and archives the old one.\n const createPrice = (body: CreatePriceParams) =>\n api<Price>(\"/catalog/prices\", { method: \"POST\", body })\n\n // getPrice returns the price with its state on each linked PSP. verify=true\n // also reads every PSP's copy and reports its drift: a read, never a write,\n // and slow enough that it stays opt-in.\n const getPrice = (id: string, verify = false, signal?: AbortSignal) =>\n api<Price>(`/catalog/prices/${encodeURIComponent(id)}`, {\n query: verify ? { verify: true } : undefined,\n signal,\n })\n\n // getProductByKey reads the product a key names, with its current prices:\n // a products list filtered by key.\n const getProductByKey = async (productKey: string) => {\n const page = await api<ListPage<Product>>(\"/catalog/products\", {\n query: { keys: productKey },\n })\n const product = page.data[0]\n if (!product) throw new Error(`No product ${productKey}`)\n return product\n }\n\n // updatePrice archives or restores a price, or changes its PSP links\n // (a PSP set to null is unlinked).\n const updatePrice = (id: string, body: UpdatePriceParams) =>\n api<Price>(`/catalog/prices/${encodeURIComponent(id)}`, { method: \"PATCH\", body })\n\n // getPriceHistory returns the history of a price's key, most recent first:\n // when the key moved to which price.\n const getPriceHistory = (priceId: string, signal?: AbortSignal) =>\n api<ListPage<PriceKeyMovement>>(`/catalog/prices/${encodeURIComponent(priceId)}/history`, {\n query: { limit: PAGE_MAX },\n signal,\n })\n\n // --- Price migrations ---\n\n // previewPriceMigration is the wizard's affected-count dry run, called\n // before the price edit lands: by key with no target it counts every\n // version's subscribers. It never writes.\n const previewPriceMigration = (productKey: string, priceKey: string) =>\n api<PriceMigrationPreview>(\"/catalog/price-migrations/preview\", {\n method: \"POST\",\n body: { product_key: productKey, price_key: priceKey },\n })\n\n // createPriceMigration moves the subscribers of every version of priceKey\n // but toPriceId to it, each at its first renewal on or after effectiveAt.\n const createPriceMigration = (\n productKey: string,\n priceKey: string,\n toPriceId: string,\n effectiveAt: string\n ) =>\n api<PriceMigration>(\"/catalog/price-migrations\", {\n method: \"POST\",\n body: {\n product_key: productKey,\n price_key: priceKey,\n to_price_id: toPriceId,\n effective_at: effectiveAt,\n },\n })\n\n // listPriceMigrations lists a price key's migrations, newest first.\n const listPriceMigrations = (\n productKey: string,\n priceKey: string,\n limit = 20,\n signal?: AbortSignal\n ) =>\n api<CursorEnvelope<PriceMigration>>(\"/catalog/price-migrations\", {\n query: { product_key: productKey, price_key: priceKey, limit },\n signal,\n })\n\n const cancelPriceMigration = (id: string) =>\n api<PriceMigrationCancel>(`/catalog/price-migrations/${id}/cancel`, {\n method: \"POST\",\n })\n\n // JSON is valid YAML too. Keep the reviewed document byte-for-byte unchanged\n // instead of parsing/re-encoding money in the browser. The server deduplicates\n // batches by their canonical content. force overwrites what edits set.\n const applyCatalog = (document: string, force = false) =>\n api<CatalogApplicationReceipt>(\"/catalog/apply\", {\n method: \"POST\",\n rawBody: document,\n headers: { \"Content-Type\": \"application/yaml\" },\n ...(force ? { query: { force: \"true\" } } : {}),\n })\n\n // refreshPSPs re-reads every PSP now, its catalog drift included; the pass\n // runs in the background.\n const refreshPSPs = () =>\n api<PSPRefresh>(\"/merchant/psps/refresh\", { method: \"POST\" })\n\n // --- Ops ---\n\n // listFindings reads the findings queue; type is one finding type or a prefix\n // ending in \".*\" (catalog.*: catalog drift).\n const listFindings = (\n filters: { status?: string; severity?: string; type?: string },\n limit: number,\n signal?: AbortSignal\n ) =>\n api<ListPage<Finding>>(\"/merchant/findings\", {\n query: { ...filters, limit },\n signal,\n })\n\n const getFinding = (id: string) => api<Finding>(`/merchant/findings/${id}`)\n\n const resolveFinding = (\n id: string,\n outcome: \"approve\" | \"ignore\",\n notes: string\n ) =>\n api<{ finding: Finding; execution?: Record<string, unknown> }>(\n `/merchant/findings/${id}/resolve`,\n { method: \"POST\", body: { outcome, notes } }\n )\n\n // --- Settings ---\n\n const getMerchantConfiguration = (signal?: AbortSignal) =>\n api<MerchantConfigurationState>(\"/merchant/configuration\", { signal })\n\n // Merges the fields it names. expected_revision is the revision the form\n // read; a configuration changed since is refused with revision_mismatch.\n const updateMerchantConfiguration = (\n body: UpdateMerchantConfigurationParams\n ) =>\n api<MerchantConfigurationState>(\"/merchant/configuration\", {\n method: \"PATCH\",\n body,\n })\n\n // A merchant has a handful of PSPs: one page holds them all.\n const listPSPs = (signal?: AbortSignal) =>\n api<ListPage<PSP>>(\"/merchant/psps?limit=500\", { signal })\n\n // The rail registry is static per build: it arrives with the configuration.\n const listRails = async (signal?: AbortSignal) =>\n (await getConfig(signal)).rails\n\n // Credentials are write-only and checked with the provider before anything\n // is stored.\n const createPSP = (body: CreatePSPParams) =>\n api<PSP>(\"/merchant/psps\", { method: \"POST\", body })\n\n // Changes settings, rotates credentials (omitted ones keep their values) or\n // archives the PSP: the rail's last active PSP needs allow_last\n // (409 psp_last_active). expected_revision refuses a PSP changed since.\n const updatePSP = (id: string, body: UpdatePSPParams) =>\n api<PSP>(`/merchant/psps/${encodeURIComponent(id)}`, {\n method: \"PATCH\",\n body,\n })\n\n // previewPSPRouting (or#288) explains which PSP a checkout for this price\n // would use and why each other PSP was passed over. Read-only: it runs the\n // production decision path without creating a session.\n const previewPSPRouting = (\n body: { price_id: string; country?: string; psp?: string },\n signal?: AbortSignal\n ) =>\n api<PSPRoutingPreview>(\"/merchant/psps/routing-preview\", {\n method: \"POST\",\n body,\n signal,\n })\n\n // The public configuration: what the deployment serves, the currency\n // registry and the payment setup.\n const getConfig = (signal?: AbortSignal) =>\n api<PublicConfig>(\"/config\", { signal })\n\n // getAdminAccess is what the signed-in staff member may use of each staff\n // route group that is mounted: the console's areas.\n const getAdminAccess = (signal?: AbortSignal) =>\n api<AdminAccess>(\"/admin/access\", { signal })\n\n // updateCustomer changes only the settings params names and answers the\n // customer.\n const updateCustomer = (customerId: string, params: UpdateCustomerParams) =>\n api<Customer>(`/admin/customers/${customerId}`, {\n method: \"PATCH\",\n body: params,\n })\n\n // --- Alerting: webhooks (#736) ---\n\n const listWebhooks = (signal?: AbortSignal) =>\n api<ListPage<AlertWebhook>>(\"/merchant/alert-webhooks\", { signal })\n\n const createWebhook = (body: CreateAlertWebhookParams) =>\n api<AlertWebhook>(\"/merchant/alert-webhooks\", { method: \"POST\", body })\n\n // Omitted fields keep their values; the URL is write-only.\n const updateWebhook = (id: string, body: UpdateAlertWebhookParams) =>\n api<AlertWebhook>(`/merchant/alert-webhooks/${id}`, {\n method: \"PATCH\",\n body,\n })\n\n const deleteWebhook = (id: string) =>\n api<void>(`/merchant/alert-webhooks/${id}`, { method: \"DELETE\" })\n return {\n listCustomers,\n getCustomer,\n listCustomerEntitlements,\n listCustomerProductAccess,\n listCustomerPaymentMethods,\n grantProductAccess,\n revokeProductAccess,\n listSubscriptions,\n getSubscription,\n cancelSubscription,\n resumeSubscription,\n changeSubscriptionPaymentMethod,\n previewSubscriptionChange,\n changeSubscription,\n listPayments,\n getPayment,\n refundPayment,\n listPaymentAttempts,\n getPaymentAttempt,\n listRenewals,\n getRenewal,\n listProducts,\n getProduct,\n createProduct,\n updateProduct,\n listUsageMeters,\n getUsageMeter,\n putUsageMeter,\n putUsageMeterRateCard,\n listPrices,\n createPrice,\n getPrice,\n getProductByKey,\n updatePrice,\n getPriceHistory,\n previewPriceMigration,\n createPriceMigration,\n listPriceMigrations,\n cancelPriceMigration,\n applyCatalog,\n refreshPSPs,\n listFindings,\n getFinding,\n resolveFinding,\n getMerchantConfiguration,\n updateMerchantConfiguration,\n listPSPs,\n listRails,\n createPSP,\n updatePSP,\n previewPSPRouting,\n getConfig,\n getAdminAccess,\n updateCustomer,\n listWebhooks,\n createWebhook,\n updateWebhook,\n deleteWebhook,\n }\n}\n","// Metrics and dashboard API; types mirror the Go handlers.\nimport type { AdminClient } from \"./client\"\n\nexport interface MetricsRange {\n from?: string\n to?: string\n // Relative trailing window ending today (\"7d\", \"12w\", \"6m\", \"1y\") —\n // mutually exclusive with from/to; saved widgets prefer it.\n last?: string\n}\n\nexport interface OrderTerm {\n measure?: string\n dimension?: string\n dir?: \"asc\" | \"desc\"\n}\n\nexport interface MetricsQuery {\n measures: string[]\n by?: string[]\n grain?: string\n range: MetricsRange\n filters?: Record<string, string[]>\n order?: OrderTerm[]\n limit?: number\n compare?: \"previous_period\"\n}\n\nexport interface MetricsColumn {\n name: string\n kind: \"time\" | \"dimension\" | \"measure\"\n unit?: string\n}\n\nexport type MetricsCell = string | number | null\n\nexport interface MetricsResult {\n grain?: string\n range: { from: string; to: string }\n columns: MetricsColumn[]\n rows: MetricsCell[][]\n compare_range?: { from: string; to: string }\n compare_rows?: MetricsCell[][]\n}\n\nexport type WidgetViz = \"stat\" | \"line\" | \"area\" | \"bar\" | \"donut\" | \"table\"\n\nexport const WIDGET_VIZ: WidgetViz[] = [\n \"stat\",\n \"line\",\n \"area\",\n \"bar\",\n \"donut\",\n \"table\",\n]\n\nexport interface WidgetGrid {\n x: number\n y: number\n w: number\n h: number\n}\n\nexport interface Widget {\n id: string\n title: string\n viz: WidgetViz\n query: MetricsQuery\n grid: WidgetGrid\n // fixed_range keeps the query's own range; other widgets follow the\n // dashboard's range picker.\n fixed_range: boolean\n}\n\nexport interface Dashboard {\n widgets: Widget[]\n is_default: boolean\n updated_at?: string\n updated_by?: string\n}\n\nexport function createMetrics(client: AdminClient) {\n const { api } = client\n const metricsQuery = (query: MetricsQuery, signal?: AbortSignal) =>\n api<MetricsResult>(\"/metrics/query\", {\n method: \"POST\",\n body: query,\n signal,\n })\n\n const getDashboard = (signal?: AbortSignal) =>\n api<Dashboard>(\"/metrics/dashboard\", { signal })\n\n const putDashboard = (widgets: Widget[]) =>\n api<Dashboard>(\"/merchant/dashboard\", { method: \"PUT\", body: { widgets } })\n\n return { metricsQuery, getDashboard, putDashboard }\n}\n","import type { AdminClient } from \"./client\"\n\nimport type {\n AskCatalogParams,\n CatalogAnswer,\n} from \"#orck/client/generated/wire\"\n\nexport type {\n CatalogAnswer,\n CatalogDraft,\n NewPriceDraft,\n PriceChangeDraft,\n} from \"#orck/client/generated/wire\"\nexport function createCopilot(client: AdminClient) {\n const { api } = client\n\n // askCatalog is not mounted unless the deployment enables the assistant.\n const askCatalog = (question: string) =>\n api<CatalogAnswer>(\"/console/catalog/ask\", {\n method: \"POST\",\n body: { question } satisfies AskCatalogParams,\n })\n return { askCatalog }\n}\n","import type { AdminClient } from \"./client\"\n\nimport type {\n CreditGrant,\n CreditGrantInput,\n BalanceTransaction,\n ListPage,\n} from \"./credit-types\"\n\nconst customerPath = (id: string) =>\n `/admin/customers/${encodeURIComponent(id)}`\nexport function createCreditEndpoints(client: AdminClient) {\n const { api } = client\n\n const listCreditGrants = (\n customer: string,\n currency: string,\n limit: number,\n cursor: string,\n signal?: AbortSignal\n ) =>\n api<ListPage<CreditGrant>>(\"/admin/credit-grants\", {\n query: { customer_id: customer, currency, limit, cursor },\n signal,\n })\n\n // A grant is a batch of one; the batch route is all or none.\n const createCreditGrant = async (\n customer: string,\n body: CreditGrantInput\n ) => {\n const out = await api<{ items: CreditGrant[] }>(\"/admin/credit-grants\", {\n method: \"POST\",\n body: { items: [{ customer_id: customer, ...body }] },\n })\n return out.items[0]\n }\n\n const revokeCreditGrant = (grant: string, reason: string) =>\n api<CreditGrant>(\n `/admin/credit-grants/${encodeURIComponent(grant)}/revoke`,\n { method: \"POST\", body: { reason } }\n )\n\n const listBalanceTransactions = (\n customer: string,\n currency: string,\n limit: number,\n cursor: string,\n signal?: AbortSignal\n ) =>\n api<ListPage<BalanceTransaction>>(\n `${customerPath(customer)}/balance/transactions`,\n {\n query: { currency, limit, cursor },\n signal,\n }\n )\n return {\n listCreditGrants,\n createCreditGrant,\n revokeCreditGrant,\n listBalanceTransactions,\n }\n}\n","import type { AdminClient } from \"./client\"\nimport { type PageRequest } from \"./client\"\n\nimport type {\n RecordExternalPaymentParams,\n ListPage,\n Order,\n Payment,\n} from \"#orck/client/generated/wire\"\n\n// Orders are listed newest first.\nexport interface OrderFilters {\n customer_id?: string\n origin?: string\n status?: string\n // overdue \"true\" keeps the open orders still owed past their due date.\n overdue?: string\n}\n\n// UsageAction is what staff do to an unpaid usage order.\nexport type UsageAction =\n \"waive_balance\" | \"mark_uncollectible\" | \"record_payment\"\n\nexport interface UsageActionRequest {\n id: string\n action: UsageAction\n amount?: string\n reference?: string\n}\nexport function createOrderEndpoints(client: AdminClient) {\n const { api } = client\n\n const listOrders = (\n filters: OrderFilters,\n page: PageRequest,\n signal?: AbortSignal\n ) =>\n api<ListPage<Order>>(\"/admin/orders\", {\n query: { ...filters, ...page },\n signal,\n })\n\n const getOrder = (id: string, signal?: AbortSignal) =>\n api<Order>(`/admin/orders/${id}`, { signal })\n\n // An order's payments are payments naming it.\n const listOrderPayments = (\n id: string,\n page: PageRequest,\n signal?: AbortSignal\n ) =>\n api<ListPage<Payment>>(\"/admin/payments\", {\n query: { order_id: id, ...page },\n signal,\n })\n\n function applyUsageAction(\n request: UsageActionRequest\n ): Promise<Order | Payment> {\n if (request.action === \"record_payment\") {\n const body: RecordExternalPaymentParams = {\n order_id: request.id,\n amount: request.amount ?? \"\",\n transaction_id: request.reference ?? \"\",\n }\n return api<Payment>(\"/admin/payments\", { method: \"POST\", body })\n }\n const path = {\n waive_balance: \"waive-balance\",\n mark_uncollectible: \"mark-uncollectible\",\n }[request.action]\n return api<Order>(`/admin/orders/${request.id}/${path}`, {\n method: \"POST\",\n })\n }\n return { listOrders, getOrder, listOrderPayments, applyUsageAction }\n}\n","import type { createEndpoints } from \"./endpoints\"\n\nimport type { InvoiceProfile } from \"#orck/client/generated/wire\"\nexport function createInvoiceProfileEndpoints(\n endpoints: ReturnType<typeof createEndpoints>\n) {\n const { getCustomer } = endpoints\n const { updateCustomer } = endpoints\n\n // getInvoiceProfile is the customer's invoice_profile setting; null while it\n // has none.\n const getInvoiceProfile = async (customerId: string, signal?: AbortSignal) =>\n (await getCustomer(customerId, signal)).settings.invoice_profile ?? null\n\n const putInvoiceProfile = async (\n customerId: string,\n profile: InvoiceProfile\n ) => {\n const { settings } = await updateCustomer(customerId, {\n invoice_profile: profile,\n })\n return settings.invoice_profile\n }\n return { getInvoiceProfile, putInvoiceProfile }\n}\n","import type { AdminClient } from \"./client\"\nimport { createEndpoints } from \"./endpoints\"\nimport { createMetrics } from \"./metrics\"\nimport { createCopilot } from \"./copilot\"\nimport { createCreditEndpoints } from \"./credit-endpoints\"\nimport { createOrderEndpoints } from \"./order-endpoints\"\nimport { createInvoiceProfileEndpoints } from \"./invoice-profile-endpoints\"\n\nexport function createAdminAPI(client: AdminClient) {\n const endpoints = createEndpoints(client)\n return {\n ...endpoints,\n ...createMetrics(client),\n ...createCopilot(client),\n ...createCreditEndpoints(client),\n ...createOrderEndpoints(client),\n ...createInvoiceProfileEndpoints(endpoints),\n }\n}\n\nexport type AdminAPI = ReturnType<typeof createAdminAPI>\n","import { toast as sonnerToast } from \"sonner\"\n\nimport { ApiError } from \"#orck/admin/lib/api/client\"\n\nexport function createAdminToast(namespace?: string) {\n const scoped =\n (send: typeof sonnerToast.error) =>\n (\n message: Parameters<typeof send>[0],\n options?: Parameters<typeof send>[1]\n ) =>\n send(message, { ...options, toasterId: namespace })\n return Object.assign(scoped(sonnerToast), {\n error: scoped(sonnerToast.error),\n success: scoped(sonnerToast.success),\n info: scoped(sonnerToast.info),\n warning: scoped(sonnerToast.warning),\n })\n}\n\nexport function createToastHandlers(\n toast: ReturnType<typeof createAdminToast>\n) {\n // toastApiError renders the unified internal/api error envelope consistently.\n // 403s read as a role/permission gap (the API is the authority on\n // permissions — the UI gates on its answers rather than duplicating RBAC).\n function toastApiError(err: unknown, action: string) {\n if (err instanceof ApiError) {\n if (err.code === \"revision_mismatch\") {\n toast.error(`${action}: changed since you opened it`, {\n description: \"The latest version is loaded; review it and try again.\",\n })\n return\n }\n if (err.isPermissionDenied) {\n toast.error(`${action}: your role lacks permission`, {\n description: err.message,\n })\n return\n }\n const label = err.code ? `${action} (${err.code})` : action\n toast.error(label, { description: err.message })\n return\n }\n toast.error(action, {\n description: err instanceof Error ? err.message : String(err),\n })\n }\n\n // toastStaleEdit answers an edit refused with revision_mismatch: the caller\n // closes the form and the reload shows what changed.\n function toastStaleEdit(what: string) {\n toast.error(`${what} changed since you opened it`, {\n description: \"Reloaded. Review the current version and edit again.\",\n })\n }\n\n return { toastApiError, toastStaleEdit }\n}\n","import type { AdminClient } from \"./api/client\"\nimport type { AdminAPI } from \"./api\"\nimport { keepPreviousData, queryOptions } from \"@tanstack/react-query\"\nimport { collectCursorPages } from \"#orck/admin/lib/api/client\"\n\nimport type { ListPage } from \"#orck/client/generated/wire\"\nimport {\n PAGE_MAX,\n type AttemptFilters,\n type CycleFilters,\n type PaymentFilters,\n type SubscriptionFilters,\n} from \"#orck/admin/lib/api/endpoints\"\nimport {\n type MetricsCell,\n type MetricsQuery,\n type MetricsResult,\n} from \"#orck/admin/lib/api/metrics\"\n\nimport type { FindingsGauges } from \"#orck/admin/lib/api/types\"\n\n// metricsRow reads a query without a group-by: its one row, by column name.\nfunction metricsRow(result: MetricsResult): Record<string, MetricsCell> {\n const row = result.rows[0] ?? []\n return Object.fromEntries(\n result.columns.map((column, i) => [column.name, row[i] ?? null])\n )\n}\n\n// Complete collections are explicit: selectors need every eligible record,\n// while catalog screens fetch only their visible page.\nexport async function collectPages<T>(\n loadPage: (\n cursor: string | undefined,\n signal?: AbortSignal\n ) => Promise<ListPage<T>>,\n signal?: AbortSignal\n): Promise<ListPage<T>> {\n const data = await collectCursorPages(\n (cursor) => loadPage(cursor, signal),\n signal\n )\n return { data, next_cursor: null }\n}\n\ntype MerchantRoot = readonly string[]\n\n// One vocabulary of merchant-scoped keys, bound to a root that is either read\n// live or pinned once. Nothing below reaches for the selected merchant itself.\nconst buildQueryKeys = (root: () => MerchantRoot) => ({\n merchant: () => root(),\n customers: () => [...root(), \"customers\"] as const,\n customer: (id: string) => [...root(), \"customers\", id] as const,\n subscriptions: () => [...root(), \"subscriptions\"] as const,\n subscription: (id: string) => [...root(), \"subscriptions\", id] as const,\n payments: () => [...root(), \"payments\"] as const,\n payment: (id: string) => [...root(), \"payments\", id] as const,\n attempts: () => [...root(), \"payment-attempts\"] as const,\n cycles: () => [...root(), \"renewals\"] as const,\n catalog: () => [...root(), \"catalog\"] as const,\n catalogDrift: () => [...root(), \"catalog\", \"drift\"] as const,\n usageMeters: () => [...root(), \"catalog\", \"meters\"] as const,\n usageMeter: (key: string) => [...root(), \"catalog\", \"meters\", key] as const,\n settings: () => [...root(), \"settings\"] as const,\n alerts: () => [...root(), \"alerts\"] as const,\n ops: () => [...root(), \"ops\"] as const,\n dashboard: () => [...root(), \"dashboard\"] as const,\n notifications: () => [...root(), \"notifications\"] as const,\n})\n\nexport type MerchantQueryKeys = ReturnType<typeof buildQueryKeys>\n\nconst queryErrorMeta = (errorAction?: string) =>\n errorAction ? { errorAction } : undefined\nexport function createQueries(client: AdminClient, api: AdminAPI) {\n const { queryRoot } = client\n const {\n getCustomer,\n getMerchantConfiguration,\n getPayment,\n getPaymentAttempt,\n getPrice,\n getPriceHistory,\n getProduct,\n getRenewal,\n getSubscription,\n getUsageMeter,\n listCustomerEntitlements,\n listCustomerPaymentMethods,\n listCustomerProductAccess,\n listCustomers,\n listFindings,\n listPaymentAttempts,\n listPSPs,\n listRails,\n previewPSPRouting,\n listPayments,\n listPrices,\n listProducts,\n listRenewals,\n listPriceMigrations,\n listSubscriptions,\n listUsageMeters,\n getAdminAccess,\n getConfig,\n listWebhooks,\n getDashboard,\n metricsQuery,\n } = api\n\n const currentMerchantRoot = queryRoot\n\n // Read keys belong to this instance and selected merchant.\n const queryKeys: MerchantQueryKeys = buildQueryKeys(currentMerchantRoot)\n\n // Pinned keys: the selected merchant is read once, here. Keys derived from the\n // result name that merchant forever, so work started under one merchant can\n // never invalidate under another that the operator selected while it ran.\n const merchantQueryKeys = (): MerchantQueryKeys => {\n const root = currentMerchantRoot()\n return buildQueryKeys(() => root)\n }\n\n const adminQueries = {\n customers: (search: string, limit: number, cursor: string) =>\n queryOptions({\n queryKey: [...queryKeys.customers(), { search, limit, cursor }],\n queryFn: ({ signal }) => listCustomers(search, limit, cursor, signal),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load customers\" },\n }),\n customer: (id: string) =>\n queryOptions({\n queryKey: queryKeys.customer(id),\n queryFn: ({ signal }) => getCustomer(id, signal),\n enabled: Boolean(id),\n meta: { errorAction: \"Load customer\" },\n }),\n // One page of each of a customer's lists, for the customer page.\n customerSubscriptions: (id: string, limit: number, cursor: string) =>\n queryOptions({\n queryKey: [\n ...queryKeys.customer(id),\n \"subscriptions\",\n { limit, cursor },\n ],\n queryFn: ({ signal }) =>\n listSubscriptions(\n { customer_id: id },\n limit,\n cursor || undefined,\n signal\n ),\n enabled: Boolean(id),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load subscriptions\" },\n }),\n customerPayments: (id: string, limit: number, cursor: string) =>\n queryOptions({\n queryKey: [...queryKeys.customer(id), \"payments\", { limit, cursor }],\n queryFn: ({ signal }) =>\n listPayments(\n { customer_id: id },\n { limit, cursor: cursor || undefined },\n signal\n ),\n enabled: Boolean(id),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load payments\" },\n }),\n customerPaymentMethodsPage: (id: string, limit: number, cursor: string) =>\n queryOptions({\n queryKey: [\n ...queryKeys.customer(id),\n \"payment-methods\",\n { limit, cursor },\n ],\n queryFn: ({ signal }) =>\n listCustomerPaymentMethods(\n id,\n { limit, cursor: cursor || undefined },\n signal\n ),\n enabled: Boolean(id),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load payment methods\" },\n }),\n customerEntitlements: (id: string, limit: number, cursor: string) =>\n queryOptions({\n queryKey: [\n ...queryKeys.customer(id),\n \"entitlements\",\n { limit, cursor },\n ],\n queryFn: ({ signal }) =>\n listCustomerEntitlements(\n id,\n { limit, cursor: cursor || undefined },\n signal\n ),\n enabled: Boolean(id),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load entitlements\" },\n }),\n customerProductAccess: (id: string, limit: number, cursor: string) =>\n queryOptions({\n queryKey: [\n ...queryKeys.customer(id),\n \"product-access\",\n { limit, cursor },\n ],\n queryFn: ({ signal }) =>\n listCustomerProductAccess(\n id,\n { limit, cursor: cursor || undefined },\n signal\n ),\n enabled: Boolean(id),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load product access\" },\n }),\n subscriptions: (\n filters: SubscriptionFilters,\n limit: number,\n cursor: string\n ) =>\n queryOptions({\n queryKey: [...queryKeys.subscriptions(), { filters, limit, cursor }],\n queryFn: ({ signal }) =>\n listSubscriptions(filters, limit, cursor || undefined, signal),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load subscriptions\" },\n }),\n subscription: (id: string) =>\n queryOptions({\n queryKey: queryKeys.subscription(id),\n queryFn: ({ signal }) => getSubscription(id, signal),\n enabled: Boolean(id),\n meta: { errorAction: \"Load subscription\" },\n }),\n // Every saved method: pickers must offer all of them.\n customerPaymentMethods: (customerId?: string) =>\n queryOptions({\n queryKey: [\n ...queryKeys.customer(customerId ?? \"unselected\"),\n \"payment-methods\",\n ],\n queryFn: ({ signal }) =>\n collectCursorPages(\n (cursor) =>\n listCustomerPaymentMethods(\n customerId!,\n { limit: 100, cursor },\n signal\n ),\n signal\n ),\n enabled: Boolean(customerId),\n }),\n payments: (filters: PaymentFilters, limit: number, cursor?: string) =>\n queryOptions({\n queryKey: [...queryKeys.payments(), { filters, limit, cursor }],\n queryFn: ({ signal }) =>\n listPayments(filters, { limit, cursor }, signal),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load payments\" },\n }),\n payment: (id: string) =>\n queryOptions({\n queryKey: queryKeys.payment(id),\n queryFn: ({ signal }) => getPayment(id, signal),\n enabled: Boolean(id),\n meta: { errorAction: \"Load payment\" },\n }),\n attempts: (filters: AttemptFilters, limit: number, cursor?: string) =>\n queryOptions({\n queryKey: [...queryKeys.attempts(), { filters, limit, cursor }],\n queryFn: ({ signal }) =>\n listPaymentAttempts(filters, { limit, cursor }, signal),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load payment attempts\" },\n }),\n attempt: (id: string) =>\n queryOptions({\n queryKey: [...queryKeys.attempts(), id],\n queryFn: ({ signal }) => getPaymentAttempt(id, signal),\n enabled: Boolean(id),\n meta: { errorAction: \"Load payment attempt\" },\n }),\n cycles: (filters: CycleFilters, limit: number, cursor?: string) =>\n queryOptions({\n queryKey: [...queryKeys.cycles(), { filters, limit, cursor }],\n queryFn: ({ signal }) =>\n listRenewals(filters, { limit, cursor }, signal),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load renewals\" },\n }),\n cycle: (id: string) =>\n queryOptions({\n queryKey: [...queryKeys.cycles(), id],\n queryFn: ({ signal }) => getRenewal(id, signal),\n enabled: Boolean(id),\n meta: { errorAction: \"Load renewal\" },\n }),\n products: (\n options: { limit?: number; cursor?: string; errorAction?: string } = {}\n ) => {\n const { limit = 100, cursor, errorAction } = options\n return queryOptions({\n queryKey: [...queryKeys.catalog(), \"products\", { limit, cursor }],\n queryFn: ({ signal }) => listProducts(limit, cursor, undefined, signal),\n placeholderData: keepPreviousData,\n meta: queryErrorMeta(errorAction),\n })\n },\n allProducts: (options: { errorAction?: string } = {}) =>\n queryOptions({\n queryKey: [...queryKeys.catalog(), \"products\", \"all\"],\n queryFn: ({ signal }) =>\n collectPages(\n (cursor, signal) =>\n listProducts(PAGE_MAX, cursor, undefined, signal),\n signal\n ),\n meta: queryErrorMeta(options.errorAction),\n }),\n prices: (\n options: {\n productId?: string\n limit?: number\n cursor?: string\n errorAction?: string\n } = {}\n ) => {\n const { productId, limit = 100, cursor, errorAction } = options\n return queryOptions({\n queryKey: [\n ...queryKeys.catalog(),\n \"prices\",\n { productId, limit, cursor },\n ],\n queryFn: ({ signal }) => listPrices(limit, cursor, productId, signal),\n placeholderData: keepPreviousData,\n meta: queryErrorMeta(errorAction),\n })\n },\n allPrices: (options: { productId?: string; errorAction?: string } = {}) =>\n queryOptions({\n queryKey: [\n ...queryKeys.catalog(),\n \"prices\",\n \"all\",\n { productId: options.productId },\n ],\n queryFn: ({ signal }) =>\n collectPages(\n (cursor, signal) =>\n listPrices(PAGE_MAX, cursor, options.productId, signal),\n signal\n ),\n meta: queryErrorMeta(options.errorAction),\n }),\n price: (\n id: string,\n options: { verify?: boolean; errorAction?: string } = {}\n ) => {\n const { verify = false, errorAction } = options\n return queryOptions({\n queryKey: [...queryKeys.catalog(), \"prices\", id, { verify }],\n queryFn: ({ signal }) => getPrice(id, verify, signal),\n enabled: Boolean(id),\n placeholderData: keepPreviousData,\n meta: queryErrorMeta(errorAction),\n })\n },\n product: (id?: string) =>\n queryOptions({\n queryKey: [...queryKeys.catalog(), \"products\", id ?? \"unselected\"],\n queryFn: ({ signal }) => getProduct(id!, signal),\n enabled: Boolean(id),\n }),\n priceHistory: (priceId?: string) =>\n queryOptions({\n queryKey: [\n ...queryKeys.catalog(),\n \"prices\",\n \"history\",\n priceId ?? \"unselected\",\n ],\n queryFn: ({ signal }) => getPriceHistory(priceId!, signal),\n enabled: Boolean(priceId),\n }),\n priceMigrations: (productKey?: string, priceKey?: string, limit = 5) =>\n queryOptions({\n queryKey: [\n ...queryKeys.catalog(),\n \"price-migrations\",\n { productKey, priceKey, limit },\n ],\n queryFn: ({ signal }) =>\n listPriceMigrations(productKey!, priceKey!, limit, signal),\n enabled: Boolean(productKey && priceKey),\n }),\n catalogDrift: (enabled = true, limit = 200, cursor?: string) =>\n queryOptions({\n queryKey: [...queryKeys.catalogDrift(), { limit, cursor }],\n queryFn: ({ signal }) =>\n listFindings({ type: \"catalog.*\" }, limit, signal),\n enabled,\n meta: { errorAction: \"Load drift\" },\n }),\n checkoutRouting: (priceId: string) =>\n queryOptions({\n queryKey: [...queryKeys.catalog(), \"prices\", priceId, \"routing\"],\n queryFn: ({ signal }) =>\n previewPSPRouting({ price_id: priceId }, signal),\n enabled: Boolean(priceId),\n meta: { errorAction: \"Check checkout readiness\" },\n }),\n usageMeters: (limit = 200, cursor?: string) =>\n queryOptions({\n queryKey: [...queryKeys.usageMeters(), { limit, cursor }],\n queryFn: ({ signal }) => listUsageMeters(limit, cursor, signal),\n placeholderData: keepPreviousData,\n meta: { errorAction: \"Load usage meters\" },\n }),\n allUsageMeters: () =>\n queryOptions({\n queryKey: [...queryKeys.usageMeters(), \"all\"],\n queryFn: ({ signal }) =>\n collectPages(\n (cursor, signal) => listUsageMeters(PAGE_MAX, cursor, signal),\n signal\n ),\n meta: { errorAction: \"Load usage meters\" },\n }),\n usageMeter: (key: string) =>\n queryOptions({\n queryKey: queryKeys.usageMeter(key),\n queryFn: ({ signal }) => getUsageMeter(key, signal),\n enabled: Boolean(key),\n meta: { errorAction: \"Load usage meter\" },\n }),\n findings: (enabled = true) =>\n queryOptions({\n queryKey: [...queryKeys.ops(), \"findings\", { limit: 100 }],\n queryFn: ({ signal }) => listFindings({}, 100, signal),\n enabled,\n meta: { errorAction: \"Load findings\" },\n }),\n findingSummary: () =>\n queryOptions({\n queryKey: [...queryKeys.ops(), \"findings\", \"summary\"],\n queryFn: async ({ signal }): Promise<FindingsGauges> => {\n const row = metricsRow(\n await metricsQuery(\n {\n measures: [\n \"open_findings\",\n \"orphaned_members\",\n \"freeloaders\",\n \"duplicate_coverage\",\n ],\n range: { last: \"1d\" },\n },\n signal\n )\n )\n return {\n total_open: Number(row.open_findings ?? 0),\n orphaned_members: Number(row.orphaned_members ?? 0),\n freeloaders: Number(row.freeloaders ?? 0),\n duplicate_coverage: Number(row.duplicate_coverage ?? 0),\n }\n },\n meta: { errorAction: \"Load the findings summary\" },\n }),\n merchantConfiguration: (errorAction?: string) =>\n queryOptions({\n queryKey: queryKeys.settings(),\n queryFn: ({ signal }) => getMerchantConfiguration(signal),\n meta: queryErrorMeta(errorAction),\n }),\n psps: () =>\n queryOptions({\n queryKey: [...queryKeys.settings(), \"psps\"],\n queryFn: ({ signal }) => listPSPs(signal),\n meta: { errorAction: \"Load PSPs\" },\n }),\n rails: () =>\n queryOptions({\n queryKey: [...queryKeys.settings(), \"rails\"],\n queryFn: ({ signal }) => listRails(signal),\n staleTime: Infinity,\n meta: { errorAction: \"Load rails\" },\n }),\n config: () =>\n queryOptions({\n queryKey: [\"config\"],\n queryFn: ({ signal }) => getConfig(signal),\n staleTime: 5 * 60_000,\n meta: { errorAction: \"Load configuration\" },\n }),\n access: () =>\n queryOptions({\n queryKey: [...queryKeys.merchant(), \"access\"],\n queryFn: ({ signal }) => getAdminAccess(signal),\n staleTime: 5 * 60_000,\n meta: { errorAction: \"Load your access\" },\n }),\n webhooks: () =>\n queryOptions({\n queryKey: [...queryKeys.alerts(), \"webhooks\"],\n queryFn: ({ signal }) => listWebhooks(signal),\n meta: { errorAction: \"Load webhooks\" },\n }),\n dashboard: () =>\n queryOptions({\n queryKey: queryKeys.dashboard(),\n queryFn: ({ signal }) => getDashboard(signal),\n meta: { errorAction: \"Load dashboard\" },\n }),\n widgetMetrics: (query?: MetricsQuery) =>\n queryOptions({\n queryKey: [...queryKeys.dashboard(), \"metrics\", query ?? \"unselected\"],\n queryFn: ({ signal }) => metricsQuery(query!, signal),\n enabled: Boolean(query),\n }),\n // The bell lists the open findings that need a person and counts them.\n notifications: (enabled: boolean) =>\n queryOptions({\n queryKey: queryKeys.notifications(),\n queryFn: ({ signal }) =>\n listFindings({ status: \"requires_review\" }, 10, signal),\n enabled,\n }),\n unreadNotifications: () =>\n queryOptions({\n queryKey: [...queryKeys.notifications(), \"count\"],\n queryFn: async ({ signal }) =>\n Number(\n metricsRow(\n await metricsQuery(\n {\n measures: [\"open_findings\"],\n range: { last: \"1d\" },\n filters: { finding_status: [\"requires_review\"] },\n },\n signal\n )\n ).open_findings ?? 0\n ),\n refetchInterval: 30_000,\n retry: false,\n }),\n }\n return { queryKeys, merchantQueryKeys, adminQueries }\n}\n","import type { AdminClient } from \"./api/client\"\nimport type { AdminAPI } from \"./api\"\nimport type { createQueries } from \"./queries\"\nimport { ApiError, collectCursorPages } from \"#orck/admin/lib/api/client\"\n\nimport type {\n CreateAlertWebhookParams,\n CreatePSPParams,\n CreatePriceParams,\n Meter,\n UpdateAlertWebhookParams,\n UpdateMerchantConfigurationParams,\n UpdatePSPParams,\n UpdateProductParams,\n} from \"#orck/client/generated/wire\"\n\nimport {\n mutationOptions,\n type QueryClient,\n type QueryKey,\n} from \"@tanstack/react-query\"\nimport {\n type DefaultUsageRateCardRequest,\n type PaymentFilters,\n type ProductGrant,\n type ProductRequest,\n type UsageMeterRequest,\n type SubscriptionFilters,\n} from \"#orck/admin/lib/api/endpoints\"\nimport { type Widget } from \"#orck/admin/lib/api/metrics\"\n\nimport type {\n ChangeSubscriptionParams,\n Customer,\n} from \"#orck/client/generated/wire\"\n\nimport type { AdminSubscription } from \"#orck/admin/lib/api/types\"\n\nconst EXPORT_PAGE = 200\n\nconst collectAllCursorPages = async <T>(\n listPage: (\n limit: number,\n cursor?: string\n ) => Promise<{ data: T[]; next_cursor: string | null }>\n) => {\n const rows: T[] = []\n let cursor: string | undefined\n for (;;) {\n const page = await listPage(EXPORT_PAGE, cursor)\n rows.push(...page.data)\n if (!page.next_cursor || page.data.length === 0) return rows\n cursor = page.next_cursor\n }\n}\n\nconst invalidateExact = (\n queryClient: QueryClient,\n queryKey: readonly unknown[]\n) => queryClient.invalidateQueries({ queryKey, exact: true })\n\nconst invalidateExactOnSuccess =\n (queryClient: QueryClient, queryKey: readonly unknown[]) => () =>\n invalidateExact(queryClient, queryKey)\n\nconst invalidateTreeOnSuccess =\n (queryClient: QueryClient, queryKey: readonly unknown[]) => () =>\n queryClient.invalidateQueries({ queryKey })\n\n// reloadIfMoved refetches what an edit was refused for: an object another\n// edit changed since it was read (revision_mismatch).\nconst reloadIfMoved =\n (queryClient: QueryClient, ...queryKeys: QueryKey[]) =>\n (err: unknown) => {\n if (err instanceof ApiError && err.code === \"revision_mismatch\") {\n void Promise.all(\n queryKeys.map((queryKey) => queryClient.invalidateQueries({ queryKey }))\n )\n }\n }\n\nexport function createMutations(\n client: AdminClient,\n api: AdminAPI,\n queries: ReturnType<typeof createQueries>\n) {\n const { selectedMerchant } = client\n const {\n askCatalog,\n cancelPriceMigration,\n cancelSubscription,\n changeSubscriptionPaymentMethod,\n changeSubscription,\n createPrice,\n createProduct,\n createWebhook,\n createPSP,\n deleteWebhook,\n getCustomer,\n getProductByKey,\n grantProductAccess,\n listCustomers,\n listPayments,\n listSubscriptions,\n putUsageMeterRateCard,\n updatePSP,\n putUsageMeter,\n previewPriceMigration,\n previewSubscriptionChange,\n applyCatalog,\n refreshPSPs,\n refundPayment,\n createPriceMigration,\n resolveFinding,\n resumeSubscription,\n revokeProductAccess,\n updateCustomer,\n updateMerchantConfiguration,\n updatePrice,\n updateProduct,\n updateWebhook,\n putDashboard,\n } = api\n\n const { adminQueries, merchantQueryKeys } = queries\n\n // Every factory pins the selected merchant once, up front, with\n // merchantQueryKeys(). Callbacks fire after the request returns, by which time\n // the operator may have switched merchants, so a key built inside onSuccess /\n // onSettled from the live queryKeys would name the wrong merchant: the\n // initiating merchant's screens stay stale and an untouched merchant's cache is\n // invalidated. Importing the live queryKeys here is blocked by lint.\n const readOnlyNow = (queryClient: QueryClient) => (err: Error) => {\n if (err instanceof ApiError && err.merchantConfigReadOnly)\n void queryClient.invalidateQueries({\n queryKey: adminQueries.config().queryKey,\n })\n }\n\n const webhooksChanged =\n (queryClient: QueryClient, keys: ReturnType<typeof merchantQueryKeys>) =>\n () =>\n Promise.all([\n invalidateExact(queryClient, [...keys.alerts(), \"webhooks\"]),\n invalidateExact(queryClient, keys.settings()),\n ])\n const adminMutations = {\n saveDashboard: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n const dashboardKey = keys.dashboard()\n return mutationOptions({\n mutationKey: [...dashboardKey, \"save\"],\n mutationFn: (widgets: Widget[]) => putDashboard(widgets),\n onSuccess: (saved) => queryClient.setQueryData(dashboardKey, saved),\n })\n },\n\n findCustomer: () => {\n const keys = merchantQueryKeys()\n const customersKey = keys.customers()\n return mutationOptions({\n mutationKey: [...customersKey, \"find\"],\n mutationFn: async (term: string) => {\n const result = await listCustomers(term, 1, \"\")\n return result.data[0]\n },\n })\n },\n exportCustomers: () => {\n const keys = merchantQueryKeys()\n const customersKey = keys.customers()\n return mutationOptions({\n mutationKey: [...customersKey, \"export\"],\n mutationFn: (search: string) =>\n collectAllCursorPages<Customer>((limit, cursor) =>\n listCustomers(search, limit, cursor ?? \"\")\n ),\n })\n },\n exportSubscriptions: () => {\n const keys = merchantQueryKeys()\n const subscriptionsKey = keys.subscriptions()\n return mutationOptions({\n mutationKey: [...subscriptionsKey, \"export\"],\n mutationFn: (filters: SubscriptionFilters) =>\n collectAllCursorPages<AdminSubscription>((limit, cursor) =>\n listSubscriptions(filters, limit, cursor)\n ),\n })\n },\n exportPayments: () => {\n const keys = merchantQueryKeys()\n const paymentsKey = keys.payments()\n return mutationOptions({\n mutationKey: [...paymentsKey, \"export\"],\n mutationFn: (filters: PaymentFilters) =>\n collectCursorPages((cursor) =>\n listPayments(filters, { limit: EXPORT_PAGE, cursor })\n ),\n })\n },\n resolveFinding: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n const opsKey = keys.ops()\n return mutationOptions({\n mutationKey: [...opsKey, \"findings\", \"resolve\"],\n mutationFn: ({\n id,\n outcome,\n notes,\n }: {\n id: string\n outcome: \"approve\" | \"ignore\"\n notes: string\n }) => resolveFinding(id, outcome, notes),\n onSuccess: invalidateTreeOnSuccess(queryClient, opsKey),\n })\n },\n refundPayment: (\n queryClient: QueryClient,\n paymentId: string,\n customerId?: string,\n subscriptionId?: string\n ) => {\n const keys = merchantQueryKeys()\n const paymentsKey = keys.payments()\n const customerKey = customerId ? keys.customer(customerId) : undefined\n const subscriptionKey = subscriptionId\n ? keys.subscription(subscriptionId)\n : undefined\n return mutationOptions({\n mutationKey: [...paymentsKey, paymentId, \"refund\"],\n mutationFn: ({\n amount,\n reason,\n revokeAccess,\n }: {\n amount: string\n reason: string\n revokeAccess: boolean\n }) => refundPayment(paymentId, amount, reason, revokeAccess),\n onSuccess: () =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: paymentsKey }),\n ...(customerKey\n ? [queryClient.invalidateQueries({ queryKey: customerKey })]\n : []),\n ...(subscriptionKey\n ? [queryClient.invalidateQueries({ queryKey: subscriptionKey })]\n : []),\n ]),\n })\n },\n cancelSubscription: (\n queryClient: QueryClient,\n subscriptionId: string,\n customerId?: string\n ) => {\n const keys = merchantQueryKeys()\n const subscriptionsKey = keys.subscriptions()\n const customerKey = customerId ? keys.customer(customerId) : undefined\n return mutationOptions({\n mutationKey: [...subscriptionsKey, subscriptionId, \"cancel\"],\n mutationFn: ({\n reason,\n revokeAccess,\n }: {\n reason: string\n revokeAccess: boolean\n }) => cancelSubscription(subscriptionId, reason, revokeAccess),\n onSuccess: () =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: subscriptionsKey }),\n ...(customerKey\n ? [queryClient.invalidateQueries({ queryKey: customerKey })]\n : []),\n ]),\n })\n },\n resumeSubscription: (\n queryClient: QueryClient,\n subscriptionId: string,\n customerId?: string\n ) => {\n const keys = merchantQueryKeys()\n const subscriptionsKey = keys.subscriptions()\n const customerKey = customerId ? keys.customer(customerId) : undefined\n return mutationOptions({\n mutationKey: [...subscriptionsKey, subscriptionId, \"resume\"],\n mutationFn: () => resumeSubscription(subscriptionId),\n onSuccess: () =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: subscriptionsKey }),\n ...(customerKey\n ? [queryClient.invalidateQueries({ queryKey: customerKey })]\n : []),\n ]),\n })\n },\n changeSubscriptionPaymentMethod: (\n queryClient: QueryClient,\n subscriptionId: string,\n customerId?: string\n ) => {\n const keys = merchantQueryKeys()\n const subscriptionsKey = keys.subscriptions()\n const customerKey = customerId ? keys.customer(customerId) : undefined\n return mutationOptions({\n mutationKey: [...subscriptionsKey, subscriptionId, \"payment-method\"],\n mutationFn: (paymentMethodId: string | null) =>\n changeSubscriptionPaymentMethod(subscriptionId, paymentMethodId),\n onSuccess: () =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: subscriptionsKey }),\n ...(customerKey\n ? [queryClient.invalidateQueries({ queryKey: customerKey })]\n : []),\n ]),\n })\n },\n previewSubscriptionChange: (subscriptionId: string) => {\n const keys = merchantQueryKeys()\n const subscriptionsKey = keys.subscriptions()\n return mutationOptions({\n mutationKey: [...subscriptionsKey, subscriptionId, \"change\", \"preview\"],\n mutationFn: (change: ChangeSubscriptionParams) =>\n previewSubscriptionChange(subscriptionId, change),\n })\n },\n changeSubscription: (\n queryClient: QueryClient,\n subscriptionId: string,\n customerId?: string\n ) => {\n const keys = merchantQueryKeys()\n const subscriptionsKey = keys.subscriptions()\n const customerKey = customerId ? keys.customer(customerId) : undefined\n const paymentsKey = keys.payments()\n return mutationOptions({\n mutationKey: [...subscriptionsKey, subscriptionId, \"change\"],\n mutationFn: (request: {\n change: ChangeSubscriptionParams\n idempotencyKey: string\n }) =>\n changeSubscription(\n subscriptionId,\n request.change,\n request.idempotencyKey\n ),\n onSuccess: () =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: subscriptionsKey }),\n queryClient.invalidateQueries({ queryKey: paymentsKey }),\n ...(customerKey\n ? [queryClient.invalidateQueries({ queryKey: customerKey })]\n : []),\n ]),\n })\n },\n grantCustomerProductAccess: (\n queryClient: QueryClient,\n customerId: string\n ) => {\n const keys = merchantQueryKeys()\n const customerKey = keys.customer(customerId)\n return mutationOptions({\n mutationKey: [...customerKey, \"product-access\", \"grant\"],\n mutationFn: (grant: ProductGrant) =>\n grantProductAccess(customerId, grant),\n onSuccess: invalidateTreeOnSuccess(queryClient, customerKey),\n })\n },\n revokeCustomerProductAccess: (\n queryClient: QueryClient,\n customerId: string\n ) => {\n const keys = merchantQueryKeys()\n const customerKey = keys.customer(customerId)\n return mutationOptions({\n mutationKey: [...customerKey, \"product-access\", \"revoke\"],\n mutationFn: ({\n grantId,\n reason,\n }: {\n grantId: string\n reason: string\n }) => revokeProductAccess(grantId, reason),\n onSuccess: invalidateTreeOnSuccess(queryClient, customerKey),\n })\n },\n askCatalogCopilot: () => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"copilot\", \"ask\"],\n mutationFn: (question: string) => askCatalog(question),\n })\n },\n loadCatalogPriceDraft: () => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"copilot\", \"load-price-draft\"],\n mutationFn: async ({\n productKey,\n priceKey,\n }: {\n productKey: string\n priceKey: string\n }) => {\n const product = await getProductByKey(productKey)\n const price = product.prices.find((p) => p.key === priceKey)\n if (!price) throw new Error(`No live price ${productKey}/${priceKey}`)\n return {\n price,\n productName: product.display_name,\n productKey: product.key,\n }\n },\n })\n },\n createCatalogDraftPrice: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"copilot\", \"create-price\"],\n mutationFn: (price: CreatePriceParams) => createPrice(price),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n })\n },\n applyCatalog: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"apply\"],\n mutationFn: ({\n document,\n force,\n }: {\n document: string\n force: boolean\n }) => applyCatalog(document, force),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n })\n },\n refreshPSPs: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalogDrift(), \"refresh\"],\n mutationFn: () => refreshPSPs(),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalogDrift()),\n })\n },\n createProduct: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"products\", \"create\"],\n mutationFn: (product: ProductRequest) => createProduct(product),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n })\n },\n updateProduct: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"products\", \"update\"],\n mutationFn: ({\n id,\n product,\n }: {\n id: string\n product: UpdateProductParams\n }) => updateProduct(id, product),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n onError: reloadIfMoved(queryClient, keys.catalog()),\n })\n },\n setProductActive: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"products\", \"set-active\"],\n mutationFn: ({\n id,\n active,\n revision,\n }: {\n id: string\n active: boolean\n revision: number\n }) =>\n updateProduct(id, { archived: !active, expected_revision: revision }),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n onError: reloadIfMoved(queryClient, keys.catalog()),\n })\n },\n createPrice: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"prices\", \"create\"],\n mutationFn: (price: CreatePriceParams) => createPrice(price),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n })\n },\n setPriceActive: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"prices\", \"set-active\"],\n mutationFn: ({\n id,\n active,\n revision,\n }: {\n id: string\n active: boolean\n revision: number\n }) =>\n updatePrice(id, { archived: !active, expected_revision: revision }),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n onError: reloadIfMoved(queryClient, keys.catalog()),\n })\n },\n putUsageMeter: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n const metersKey = keys.usageMeters()\n return mutationOptions({\n mutationKey: [...metersKey, \"put\"],\n mutationFn: ({\n key,\n meter,\n }: {\n key: string\n meter: UsageMeterRequest\n }) => putUsageMeter(key, meter),\n onSuccess: (_result, { key }) =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: metersKey }),\n queryClient.invalidateQueries({\n queryKey: keys.usageMeter(key),\n }),\n ]),\n onError: reloadIfMoved(queryClient, metersKey),\n })\n },\n putDefaultUsageRateCard: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n const metersKey = keys.usageMeters()\n return mutationOptions({\n mutationKey: [...metersKey, \"rate-card\", \"put\"],\n mutationFn: ({\n meter,\n rateCard,\n }: {\n meter: Meter\n rateCard: DefaultUsageRateCardRequest\n }) => putUsageMeterRateCard(meter, rateCard),\n onSuccess: (_result, { meter }) =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: metersKey }),\n queryClient.invalidateQueries({\n queryKey: keys.usageMeter(meter.key),\n }),\n ]),\n onError: reloadIfMoved(queryClient, metersKey),\n })\n },\n deleteDefaultUsageRateCard: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n const metersKey = keys.usageMeters()\n return mutationOptions({\n mutationKey: [...metersKey, \"rate-card\", \"delete\"],\n mutationFn: (meter: Meter) => putUsageMeterRateCard(meter, null),\n onSuccess: (_result, meter) =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: metersKey }),\n queryClient.invalidateQueries({\n queryKey: keys.usageMeter(meter.key),\n }),\n ]),\n })\n },\n previewPriceChange: () => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"prices\", \"preview-change\"],\n mutationFn: ({\n productKey,\n priceKey,\n }: {\n productKey: string\n priceKey: string\n }) => previewPriceMigration(productKey, priceKey),\n })\n },\n changePrice: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"prices\", \"change\"],\n mutationFn: async ({\n price,\n migration,\n }: {\n price: CreatePriceParams\n migration?: {\n productKey: string\n priceKey: string\n effectiveAt: string\n }\n }) => {\n const created = await createPrice(price)\n if (migration) {\n await createPriceMigration(\n migration.productKey,\n migration.priceKey,\n created.id,\n migration.effectiveAt\n )\n }\n return created\n },\n // The price can be created before scheduling fails. Always refresh so\n // the UI reflects that partial server-side success, or the key's\n // current revision after a revision_mismatch.\n onSettled: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n })\n },\n cancelPriceMigration: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.catalog(), \"price-migrations\", \"cancel\"],\n mutationFn: (migrationId: string) => cancelPriceMigration(migrationId),\n onSuccess: invalidateTreeOnSuccess(queryClient, keys.catalog()),\n })\n },\n // Merchant-config edits: a refused revision means the form is stale, so\n // reload either way; merchant_config_read_only rereads the capabilities so\n // the console turns read-only.\n updateMerchantConfiguration: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.settings(), \"update\"],\n mutationFn: (update: UpdateMerchantConfigurationParams) =>\n updateMerchantConfiguration(update),\n onSettled: invalidateExactOnSuccess(queryClient, keys.settings()),\n onError: readOnlyNow(queryClient),\n })\n },\n createPSP: (queryClient: QueryClient) => {\n const merchant = selectedMerchant()\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.settings(), \"psps\", \"create\"],\n retry: false,\n gcTime: 0,\n mutationFn: (psp: CreatePSPParams) => {\n if (selectedMerchant() !== merchant)\n throw new Error(\"Merchant changed; reopen this form before saving\")\n return createPSP(psp)\n },\n onSettled: invalidateExactOnSuccess(queryClient, [\n ...keys.settings(),\n \"psps\",\n ]),\n onError: readOnlyNow(queryClient),\n })\n },\n // Rotation, settings and archiving: one PATCH at the revision the caller\n // read. A refused revision reloads the list.\n updatePSP: (queryClient: QueryClient) => {\n const merchant = selectedMerchant()\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.settings(), \"psps\", \"update\"],\n retry: false,\n gcTime: 0,\n mutationFn: ({ id, psp }: { id: string; psp: UpdatePSPParams }) => {\n if (selectedMerchant() !== merchant)\n throw new Error(\"Merchant changed; reopen this form before saving\")\n return updatePSP(id, psp)\n },\n onSettled: invalidateExactOnSuccess(queryClient, [\n ...keys.settings(),\n \"psps\",\n ]),\n onError: readOnlyNow(queryClient),\n })\n },\n setCreditLimit: () => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.settings(), \"customer-controls\", \"credit-limit\"],\n mutationFn: ({\n customerId,\n currency,\n amount,\n }: {\n customerId: string\n currency: string\n amount: string\n }) =>\n updateCustomer(customerId, { credit_limits: [{ currency, amount }] }),\n })\n },\n lookupCustomerControls: () => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.settings(), \"customer-controls\", \"lookup\"],\n mutationFn: async ({\n customerId,\n currency,\n }: {\n customerId: string\n currency: string\n }) => {\n const { settings } = await getCustomer(customerId).catch((err) => {\n if (err instanceof ApiError && err.status === 404)\n throw new Error(\"No customer has this ID\")\n throw err\n })\n const code = currency.toUpperCase()\n return {\n currency: code,\n creditLimit:\n settings.credit_limits.find((l) => l.currency === code)?.amount ??\n \"0\",\n trustLevel:\n settings.trust_levels.find((l) => l.currency === code)\n ?.trust_level ?? \"\",\n }\n },\n })\n },\n // Alert webhooks live in the merchant's configuration, so a change moves\n // its revision too.\n createWebhook: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.alerts(), \"webhooks\", \"create\"],\n mutationFn: (webhook: CreateAlertWebhookParams) =>\n createWebhook(webhook),\n onSuccess: webhooksChanged(queryClient, keys),\n onError: readOnlyNow(queryClient),\n })\n },\n updateWebhook: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.alerts(), \"webhooks\", \"update\"],\n mutationFn: ({\n id,\n webhook,\n }: {\n id: string\n webhook: UpdateAlertWebhookParams\n }) => updateWebhook(id, webhook),\n onSuccess: webhooksChanged(queryClient, keys),\n onError: readOnlyNow(queryClient),\n })\n },\n deleteWebhook: (queryClient: QueryClient) => {\n const keys = merchantQueryKeys()\n return mutationOptions({\n mutationKey: [...keys.alerts(), \"webhooks\", \"delete\"],\n mutationFn: (id: string) => deleteWebhook(id),\n onSuccess: webhooksChanged(queryClient, keys),\n onError: readOnlyNow(queryClient),\n })\n },\n }\n return { adminMutations }\n}\n","import type { AdminClient } from \"./api/client\"\nimport type { AdminAPI } from \"./api\"\nimport {\n mutationOptions,\n queryOptions,\n type QueryClient,\n} from \"@tanstack/react-query\"\n\nimport type { CreditGrantInput } from \"#orck/admin/lib/api/credit-types\"\n\nexport const creditCustomerKey = (merchant: string, customer: string) =>\n [\"merchant\", merchant, \"customers\", customer] as const\nexport function createCreditQueries(client: AdminClient, api: AdminAPI) {\n const { selectedMerchant } = client\n const scopedCustomerKey = (merchant: string, customer: string) =>\n [...client.queryRoot(merchant), \"customers\", customer] as const\n const {\n createCreditGrant,\n listCreditGrants,\n listBalanceTransactions,\n revokeCreditGrant,\n } = api\n\n function assertMerchant(merchant: string) {\n if (!merchant || selectedMerchant() !== merchant)\n throw new Error(\n \"The selected merchant changed. Reload this customer's credits.\"\n )\n }\n\n const creditQueries = {\n grants: (\n merchant: string,\n customer: string,\n currency: string,\n limit: number,\n cursor: string\n ) =>\n queryOptions({\n queryKey: [\n ...scopedCustomerKey(merchant, customer),\n \"credit-grants\",\n currency,\n limit,\n cursor,\n ],\n enabled: Boolean(merchant && customer && currency),\n queryFn: ({ signal }) => {\n assertMerchant(merchant)\n return listCreditGrants(customer, currency, limit, cursor, signal)\n },\n }),\n transactions: (\n merchant: string,\n customer: string,\n currency: string,\n limit: number,\n cursor: string\n ) =>\n queryOptions({\n queryKey: [\n ...scopedCustomerKey(merchant, customer),\n \"transactions\",\n currency,\n limit,\n cursor,\n ],\n enabled: Boolean(merchant && customer && currency),\n queryFn: ({ signal }) => {\n assertMerchant(merchant)\n return listBalanceTransactions(\n customer,\n currency,\n limit,\n cursor,\n signal\n )\n },\n }),\n }\n\n const creditMutations = {\n grant: (client: QueryClient, merchant: string, customer: string) =>\n mutationOptions({\n mutationFn: (input: CreditGrantInput) => {\n assertMerchant(merchant)\n return createCreditGrant(customer, input)\n },\n onSettled: () =>\n client.invalidateQueries({\n queryKey: scopedCustomerKey(merchant, customer),\n }),\n }),\n revoke: (client: QueryClient, merchant: string, customer: string) =>\n mutationOptions({\n mutationFn: ({ grant, reason }: { grant: string; reason: string }) => {\n assertMerchant(merchant)\n return revokeCreditGrant(grant, reason)\n },\n onSettled: () =>\n client.invalidateQueries({\n queryKey: scopedCustomerKey(merchant, customer),\n }),\n }),\n }\n return { assertMerchant, creditQueries, creditMutations }\n}\n","import type { AdminClient } from \"./api/client\"\nimport type { AdminAPI } from \"./api\"\nimport type { createQueries } from \"./queries\"\nimport {\n keepPreviousData,\n queryOptions,\n mutationOptions,\n type QueryClient,\n} from \"@tanstack/react-query\"\n\nimport type { OrderFilters } from \"./api/order-endpoints\"\n\nimport type { InvoiceProfile } from \"#orck/client/generated/wire\"\nexport function createOrderQueries(\n client: AdminClient,\n api: AdminAPI,\n queries: ReturnType<typeof createQueries>\n) {\n const { queryRoot } = client\n const { queryKeys } = queries\n const orderAPI = api\n const profileAPI = api\n\n const orderKeys = {\n root: () => [...queryRoot(), \"orders\"] as const,\n detail: (id: string) => [...orderKeys.root(), id] as const,\n profile: (customerId: string) =>\n [...queryKeys.customer(customerId), \"invoice-profile\"] as const,\n }\n\n const orderQueries = {\n list: (filters: OrderFilters, limit: number, cursor?: string) =>\n queryOptions({\n queryKey: [...orderKeys.root(), \"list\", filters, limit, cursor],\n queryFn: ({ signal }) =>\n orderAPI.listOrders(filters, { limit, cursor }, signal),\n placeholderData: keepPreviousData,\n }),\n detail: (id: string) =>\n queryOptions({\n queryKey: orderKeys.detail(id),\n queryFn: ({ signal }) => orderAPI.getOrder(id, signal),\n enabled: !!id,\n }),\n payments: (id: string, limit: number, cursor?: string) =>\n queryOptions({\n queryKey: [...orderKeys.detail(id), \"payments\", limit, cursor],\n queryFn: ({ signal }) =>\n orderAPI.listOrderPayments(id, { limit, cursor }, signal),\n enabled: !!id,\n placeholderData: keepPreviousData,\n }),\n // The customer's invoice profile: the terms and document fields their\n // next usage orders take.\n profile: (customerId: string) =>\n queryOptions({\n queryKey: orderKeys.profile(customerId),\n queryFn: ({ signal }) =>\n profileAPI.getInvoiceProfile(customerId, signal),\n enabled: !!customerId,\n }),\n }\n\n function usageActionMutation(client: QueryClient, customerId: string) {\n const root = orderKeys.root(),\n customer = queryKeys.customer(customerId)\n return mutationOptions({\n mutationFn: orderAPI.applyUsageAction,\n onSettled: async () => {\n await Promise.all([\n client.invalidateQueries({ queryKey: root }),\n client.invalidateQueries({ queryKey: customer }),\n ])\n },\n })\n }\n\n function invoiceProfileMutation(client: QueryClient, customerId: string) {\n const key = orderKeys.profile(customerId)\n return mutationOptions({\n mutationFn: (profile: InvoiceProfile) =>\n profileAPI.putInvoiceProfile(customerId, profile),\n onSuccess: () => client.invalidateQueries({ queryKey: key }),\n })\n }\n return {\n orderKeys,\n orderQueries,\n usageActionMutation,\n invoiceProfileMutation,\n }\n}\n","import { createContext, useContext } from \"react\"\nimport type { BillingAdminMerchant, BillingAdminProps } from \"./types\"\nimport { createAdminClient, type AdminClientOptions } from \"./lib/api/client\"\nimport { createAdminAPI } from \"./lib/api\"\nimport { createAdminToast, createToastHandlers } from \"./lib/toast\"\nimport { createQueries } from \"./lib/queries\"\nimport { createMutations } from \"./lib/mutations\"\nimport { createCreditQueries } from \"./lib/credit-queries\"\nimport { createOrderQueries } from \"./lib/order-queries\"\n\n/** Every request and cache key is bound to this instance's selected merchant. */\nexport function createAdminServices(options: AdminClientOptions) {\n const client = createAdminClient(options)\n const api = createAdminAPI(client)\n const queries = createQueries(client, api)\n const toast = createAdminToast(options.namespace)\n return {\n toast,\n ...createToastHandlers(toast),\n ...client,\n ...api,\n ...queries,\n ...createMutations(client, api, queries),\n ...createCreditQueries(client, api),\n ...createOrderQueries(client, api, queries),\n }\n}\n\nexport interface AdminContextValue {\n props: BillingAdminProps\n services: ReturnType<typeof createAdminServices>\n merchants: BillingAdminMerchant[]\n activeMerchant?: BillingAdminMerchant\n selectMerchant(slug: string): void\n portal: HTMLElement | null\n}\n\nexport const AdminContext = createContext<AdminContextValue | null>(null)\n\nexport function useAdminContext() {\n const value = useContext(AdminContext)\n if (!value) throw new Error(\"BillingAdmin context is missing\")\n return value\n}\n\nexport const useAdminServices = () => useAdminContext().services\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n type ComponentProps,\n type ReactNode,\n} from \"react\"\nimport type { BillingAdminNavigation } from \"./types\"\n\ntype NavigateOptions = { replace?: boolean; state?: unknown }\ntype Location = { pathname: string; search: string; state: unknown }\ninterface RouterValue {\n location: Location\n href(to: string): string\n navigate(to: string | number, options?: NavigateOptions): void\n params: Record<string, string>\n}\nconst Context = createContext<RouterValue | null>(null)\nconst subscribe = (notify: () => void) => {\n window.addEventListener(\"popstate\", notify)\n return () => window.removeEventListener(\"popstate\", notify)\n}\nconst snapshot = () => window.location.pathname + window.location.search\n\nexport function AdminRouter({\n basePath = \"/\",\n navigation,\n children,\n}: {\n basePath?: string\n navigation?: BillingAdminNavigation\n children: ReactNode\n}) {\n const current = useSyncExternalStore(subscribe, snapshot, () => basePath)\n const base = basePath.replace(/\\/$/, \"\")\n const fallback = new URL(current, \"http://billing.local\")\n const pathname = navigation?.pathname ?? fallback.pathname\n const search = navigation?.search ?? fallback.search\n const relative =\n pathname === base\n ? \"/\"\n : pathname.startsWith(base + \"/\")\n ? pathname.slice(base.length)\n : \"/\"\n const [states, setStates] = useState(() => new Map<string, unknown>())\n const href = useCallback(\n (to: string) => {\n if (/^(?:[a-z][a-z\\d+.-]*:|\\/\\/)/i.test(to)) return to\n const resolved = new URL(to, \"http://billing.local\" + relative + search)\n return base + resolved.pathname + resolved.search + resolved.hash\n },\n [base, relative, search]\n )\n const navigate = useCallback(\n (to: string | number, options: NavigateOptions = {}) => {\n if (typeof to === \"number\") {\n window.history.go(to)\n return\n }\n const target = href(to)\n if (/^(?:[a-z][a-z\\d+.-]*:|\\/\\/)/i.test(target)) {\n window.location.assign(target)\n return\n }\n setStates((previous) => new Map(previous).set(target, options.state))\n if (navigation) navigation.navigate(target, { replace: options.replace })\n else {\n window.history[options.replace ? \"replaceState\" : \"pushState\"](\n options.state ?? null,\n \"\",\n target\n )\n window.dispatchEvent(new PopStateEvent(\"popstate\"))\n }\n },\n [href, navigation]\n )\n const value = useMemo<RouterValue>(\n () => ({\n location: {\n pathname: relative,\n search,\n state:\n states.get(pathname + search) ??\n (!navigation ? window.history.state : null),\n },\n href,\n navigate,\n params: {},\n }),\n [relative, pathname, search, href, navigate, navigation, states]\n )\n return <Context.Provider value={value}>{children}</Context.Provider>\n}\n\nfunction useRouter() {\n const router = useContext(Context)\n if (!router) throw new Error(\"BillingAdmin router is missing\")\n return router\n}\nexport const useLocation = () => useRouter().location\nexport const useNavigate = () => useRouter().navigate\nexport const useParams = <T extends string = string>() =>\n useRouter().params as Partial<Record<T, string>>\nexport function useSearchParams() {\n const { location, navigate } = useRouter()\n const params = useMemo(\n () => new URLSearchParams(location.search),\n [location.search]\n )\n const set = (\n value: URLSearchParams | Record<string, string>,\n options?: NavigateOptions\n ) => {\n const query = new URLSearchParams(value).toString()\n navigate(location.pathname + (query ? \"?\" + query : \"\"), options)\n }\n return [params, set] as const\n}\n\nexport function Link({\n to,\n onClick,\n ...props\n}: Omit<ComponentProps<\"a\">, \"href\"> & { to: string }) {\n const { href, navigate } = useRouter()\n return (\n <a\n {...props}\n href={href(to)}\n onClick={(event) => {\n onClick?.(event)\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey ||\n props.target ||\n props.download\n )\n return\n event.preventDefault()\n navigate(to)\n }}\n />\n )\n}\n\nexport function Navigate({ to, replace }: { to: string; replace?: boolean }) {\n const navigate = useNavigate()\n useEffect(() => navigate(to, { replace }), [navigate, to, replace])\n return null\n}\n\nexport function RouteParams({\n params,\n children,\n}: {\n params: Record<string, string>\n children: ReactNode\n}) {\n const router = useRouter()\n return (\n <Context.Provider value={{ ...router, params }}>\n {children}\n </Context.Provider>\n )\n}\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"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"}
|