@openrails/billing-ui 0.230.0 → 0.233.2
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 +103 -9
- package/README.md +88 -39
- package/dist/account/account-billing.d.ts +3 -3
- package/dist/account/cancel-dialog.d.ts +2 -2
- package/dist/account/format.d.ts +4 -4
- package/dist/account/payment-methods-panel.d.ts +7 -9
- package/dist/account/section.d.ts +3 -1
- package/dist/checkout-page.d.ts +6 -1
- package/dist/client/client.d.ts +76 -62
- package/dist/client/generated/currencies.d.ts +1 -0
- package/dist/client/generated/error-codes.d.ts +7 -0
- package/dist/client/generated/routes.d.ts +775 -0
- package/dist/client/generated/wire.d.ts +682 -0
- package/dist/client/index.d.ts +3 -3
- package/dist/client/types.d.ts +425 -379
- package/dist/client-DXUPzA8C.js +889 -0
- package/dist/client-DXUPzA8C.js.map +1 -0
- package/dist/client.js +2 -3
- package/dist/components/methods.d.ts +3 -3
- package/dist/config-BQELtBh4.js +341 -0
- package/dist/config-BQELtBh4.js.map +1 -0
- package/dist/frame.d.ts +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1447 -1539
- package/dist/index.js.map +1 -1
- package/dist/lib/billing.d.ts +14 -0
- package/dist/lib/money.d.ts +1 -0
- package/dist/lib/period.d.ts +0 -2
- package/dist/lib/rail-meta.d.ts +4 -4
- package/dist/locales/de.js +11 -8
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/en.d.ts +8 -5
- package/dist/locales/en.js +11 -8
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +11 -8
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/ja.js +11 -8
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +11 -8
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +11 -8
- package/dist/locales/zh.js.map +1 -1
- package/dist/psp.d.ts +10 -21
- package/dist/react/config.d.ts +34 -0
- package/dist/react/context.d.ts +5 -8
- package/dist/react/hooks.d.ts +20 -14
- package/dist/react/index.d.ts +1 -0
- package/dist/react/provider.d.ts +1 -9
- package/dist/react/remote.d.ts +0 -1
- package/dist/react.js +24 -28
- package/dist/react.js.map +1 -1
- package/dist/save-payment-method.d.ts +1 -1
- package/dist/source.d.ts +0 -9
- package/dist/styles.css +1 -1
- package/dist/types.d.ts +114 -55
- package/docs/payment-form-contract.md +23 -40
- package/package.json +3 -3
- package/dist/client/generated/openrails-routes.d.ts +0 -2
- package/dist/client-DhG2jv34.js +0 -771
- package/dist/client-DhG2jv34.js.map +0 -1
- package/dist/errors-T-PRm3vV.js +0 -54
- package/dist/errors-T-PRm3vV.js.map +0 -1
- package/dist/hooks-DLFF-zx5.js +0 -285
- package/dist/hooks-DLFF-zx5.js.map +0 -1
- package/docs/1055-nmi-host-integration.md +0 -28
package/dist/client/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CheckoutSource } from '../source';
|
|
2
|
-
import {
|
|
2
|
+
import { CardSetup, CheckoutSessionLink, PublicConfig, PaymentAuthentication, CurrencyScales, Invoice, ListPage, NewCard, NextAction, Page, Payment, PaymentMethod, Product, SolanaToken, Subscription, TierChange, TierChangePreview } from './types';
|
|
3
3
|
export interface BillingClientOptions {
|
|
4
4
|
/** OpenRails embedded mount. Default "/billing/v1". */
|
|
5
5
|
baseUrl?: string;
|
|
@@ -18,12 +18,29 @@ export interface BillingClientOptions {
|
|
|
18
18
|
*/
|
|
19
19
|
currencies?: CurrencyScales;
|
|
20
20
|
}
|
|
21
|
+
export interface CheckoutSourceOptions {
|
|
22
|
+
/**
|
|
23
|
+
* A customer surface's base: its `/me` prefix, such as `/billing/v1/me` or
|
|
24
|
+
* a host's own `/api/v1/merchants/acme/billing/me`. The session is read and
|
|
25
|
+
* paid there with this client's credential, which proves the session's
|
|
26
|
+
* customer, so its saved cards pay. Default: the session id alone, at
|
|
27
|
+
* `{baseUrl}/checkout-sessions`.
|
|
28
|
+
*/
|
|
29
|
+
customerBase?: string;
|
|
30
|
+
}
|
|
21
31
|
export interface ListOptions {
|
|
22
32
|
limit?: number;
|
|
23
33
|
offset?: number;
|
|
34
|
+
/** A cursor list's next page: the previous page's `next_cursor`. */
|
|
35
|
+
cursor?: string;
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
}
|
|
38
|
+
/** A cursor list read: pass the previous page's `next_cursor` for the next. */
|
|
39
|
+
export interface CursorOptions {
|
|
40
|
+
limit?: number;
|
|
41
|
+
cursor?: string | null;
|
|
24
42
|
signal?: AbortSignal;
|
|
25
43
|
}
|
|
26
|
-
export type SolanaCancelStage = "preparing" | "signing" | "confirming";
|
|
27
44
|
/**
|
|
28
45
|
* Signs and submits a base64 transaction with the customer's wallet and
|
|
29
46
|
* returns its signature. Throw `WalletRejectedError` when the user declines.
|
|
@@ -32,27 +49,39 @@ export type SendSolanaTransaction = (transactionBase64: string) => Promise<strin
|
|
|
32
49
|
export declare class WalletRejectedError extends Error {
|
|
33
50
|
constructor(message?: string);
|
|
34
51
|
}
|
|
35
|
-
export declare const
|
|
36
|
-
export declare const
|
|
52
|
+
export declare const CANCEL_REASON_MIN = 4;
|
|
53
|
+
export declare const CANCEL_REASON_MAX = 500;
|
|
54
|
+
/** A next action the customer's wallet completes. */
|
|
55
|
+
export declare const isWalletAction: (next: NextAction | null | undefined) => boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Signs and sends a `solana_sign_transactions` next action's transactions in
|
|
58
|
+
* order and returns the last signature, the value the action is repeated
|
|
59
|
+
* with. A declined prompt is a local `wallet_rejected` error.
|
|
60
|
+
*/
|
|
61
|
+
export declare function signWalletAction(next: NextAction, sendTransaction: SendSolanaTransaction): Promise<string>;
|
|
37
62
|
/** Total wait a GET may spend on its one retry. */
|
|
38
63
|
export declare const RETRY_BUDGET_MS = 2000;
|
|
39
64
|
export declare function createBillingClient(options?: BillingClientOptions): {
|
|
40
65
|
baseUrl: string;
|
|
41
|
-
|
|
66
|
+
/** One page of the customer's subscriptions, newest first. */
|
|
67
|
+
listSubscriptions(opts?: CursorOptions & {
|
|
42
68
|
status?: string;
|
|
43
|
-
}): Promise<
|
|
69
|
+
}): Promise<ListPage<Subscription>>;
|
|
44
70
|
/** Includes `recovery` (list rows do not). */
|
|
45
71
|
getSubscription(subscriptionId: string, signal?: AbortSignal): Promise<Subscription>;
|
|
46
72
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
73
|
+
* Cancels at period end and answers the subscription. When the rail needs
|
|
74
|
+
* the customer's step (`next_action`, a Solana wallet signature), the
|
|
75
|
+
* subscription is unchanged: complete it with `signWalletAction` and
|
|
76
|
+
* repeat with `signature`.
|
|
49
77
|
*/
|
|
50
78
|
cancelSubscription(subscriptionId: string, input: {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
79
|
+
reason: string;
|
|
80
|
+
signature?: string;
|
|
81
|
+
}): Promise<Subscription>;
|
|
82
|
+
/** Undoes a scheduled cancel before the period ends. */
|
|
83
|
+
resumeSubscription(subscriptionId: string): Promise<Subscription>;
|
|
84
|
+
setSubscriptionPaymentMethod(subscriptionId: string, paymentMethodId: string): Promise<Subscription>;
|
|
56
85
|
/** What `changeTier` would charge now and at the next renewal. */
|
|
57
86
|
previewTierChange(subscriptionId: string, priceId: string, signal?: AbortSignal): Promise<TierChangePreview>;
|
|
58
87
|
/**
|
|
@@ -60,35 +89,19 @@ export declare function createBillingClient(options?: BillingClientOptions): {
|
|
|
60
89
|
* charges the saved card now, a downgrade applies at period end.
|
|
61
90
|
* `idempotencyKey` identifies this attempt; reuse it until the change
|
|
62
91
|
* resolves (`processing`, a `tier_change_in_flight` refusal or a lost
|
|
63
|
-
* response) so the stored result replays instead of charging twice.
|
|
92
|
+
* response) so the stored result replays instead of charging twice. A
|
|
93
|
+
* wallet next action (Solana) is completed with `signWalletAction` and
|
|
94
|
+
* the change repeated with `signature`.
|
|
64
95
|
*/
|
|
65
96
|
changeTier(subscriptionId: string, input: {
|
|
66
97
|
priceId: string;
|
|
67
98
|
idempotencyKey: string;
|
|
99
|
+
signature?: string;
|
|
68
100
|
}): Promise<TierChange>;
|
|
101
|
+
listPaymentMethods(opts?: CursorOptions): Promise<ListPage<PaymentMethod>>;
|
|
69
102
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*/
|
|
73
|
-
prepareSolanaTierChange(subscriptionId: string, newPriceId: string): Promise<SolanaTierChangeTx>;
|
|
74
|
-
/**
|
|
75
|
-
* Records the landed transaction. Keep the signature until this succeeds:
|
|
76
|
-
* confirming it again replays the result (`already_confirmed`).
|
|
77
|
-
*/
|
|
78
|
-
confirmSolanaTierChange(subscriptionId: string, input: {
|
|
79
|
-
signature: string;
|
|
80
|
-
newPriceId: string;
|
|
81
|
-
}): Promise<SolanaTierChange>;
|
|
82
|
-
/**
|
|
83
|
-
* On-chain cancellation for the solana rail: the server prepares an
|
|
84
|
-
* unsigned transaction, the wallet signs and submits it, the server
|
|
85
|
-
* verifies the signature and records the cancel.
|
|
86
|
-
*/
|
|
87
|
-
cancelSubscriptionOnChain(subscriptionId: string, sendTransaction: SendSolanaTransaction, onStage?: (stage: SolanaCancelStage) => void): Promise<void>;
|
|
88
|
-
listPaymentMethods(opts?: ListOptions): Promise<Page<PaymentMethod>>;
|
|
89
|
-
/**
|
|
90
|
-
* Stores a card entered in the page: a Collect.js token
|
|
91
|
-
* (`cardSetupDriver` "collect_js") or the card itself ("card").
|
|
103
|
+
* Stores a card entered in the page with the PSP `psp_id`: a Collect.js
|
|
104
|
+
* token (`cardSetupDriver` "collect_js") or the card itself ("card").
|
|
92
105
|
*/
|
|
93
106
|
addPaymentMethod(card: NewCard): Promise<PaymentMethod>;
|
|
94
107
|
/**
|
|
@@ -107,56 +120,57 @@ export declare function createBillingClient(options?: BillingClientOptions): {
|
|
|
107
120
|
confirmPaymentAuthentication(operationId: string): Promise<void>;
|
|
108
121
|
/** `pending` when the provider is still converging (202). */
|
|
109
122
|
removePaymentMethod(paymentMethodId: string): Promise<"removed" | "pending">;
|
|
110
|
-
/** Makes the
|
|
111
|
-
|
|
123
|
+
/** Makes the card the one that collects one currency's invoices. */
|
|
124
|
+
setCollectionPaymentMethod(input: {
|
|
112
125
|
currency: string;
|
|
113
126
|
paymentMethodId: string;
|
|
114
127
|
}): Promise<void>;
|
|
115
128
|
/** Charges and refunds, newest first. `rail` filters by rail. */
|
|
116
|
-
listPayments(opts?:
|
|
129
|
+
listPayments(opts?: CursorOptions & {
|
|
117
130
|
rail?: string;
|
|
118
|
-
}): Promise<
|
|
119
|
-
listInvoices(opts?:
|
|
131
|
+
}): Promise<ListPage<Payment>>;
|
|
132
|
+
listInvoices(opts?: CursorOptions): Promise<ListPage<Invoice>>;
|
|
120
133
|
getInvoice(invoiceId: string, signal?: AbortSignal): Promise<Invoice>;
|
|
121
|
-
|
|
122
|
-
/** Active products with their active prices. */
|
|
134
|
+
/** Products on sale, each with its current prices. */
|
|
123
135
|
listProducts(opts?: ListOptions): Promise<Page<Product>>;
|
|
124
|
-
/** Active prices. `product` is a `prod_` id; `type` is `recurring | one_time`. */
|
|
125
|
-
listPrices(opts?: ListOptions & {
|
|
126
|
-
currency?: string;
|
|
127
|
-
product?: string;
|
|
128
|
-
type?: string;
|
|
129
|
-
}): Promise<Page<Price>>;
|
|
130
|
-
/** The server's currency registry; `currencies` is the pinned copy. */
|
|
131
|
-
listCurrencies(signal?: AbortSignal): Promise<Currency[]>;
|
|
132
136
|
/**
|
|
133
137
|
* Mints a hosted checkout session for the signed-in customer and one
|
|
134
138
|
* price. Render it with `<CheckoutFrame url>` when the session has a
|
|
135
139
|
* `url`, else with `<Checkout source={client.checkoutSource(id)}>`.
|
|
140
|
+
* Select a price by `priceId`, or by both `productKey` and `priceKey`.
|
|
136
141
|
* `successUrl` brings the buyer back from a redirect rail; it must be on
|
|
137
142
|
* one of this app's return origins.
|
|
138
143
|
*/
|
|
139
144
|
createCheckoutSession(input: {
|
|
140
145
|
priceKey?: string;
|
|
146
|
+
productKey?: string;
|
|
141
147
|
priceId?: string;
|
|
148
|
+
/** Customer-selected deposit in the price currency’s native units. */
|
|
149
|
+
amount?: string;
|
|
150
|
+
/** Defaults to true for recurring prices; false buys the initial term only. */
|
|
151
|
+
autoRenew?: boolean;
|
|
142
152
|
successUrl?: string;
|
|
143
|
-
}): Promise<
|
|
153
|
+
}): Promise<CheckoutSessionLink>;
|
|
154
|
+
/**
|
|
155
|
+
* Reads and pays one hosted checkout session. By default the id is the
|
|
156
|
+
* only credential: no bearer is sent. With `customerBase` the session's
|
|
157
|
+
* customer reads and pays it on that customer surface, signed in. A
|
|
158
|
+
* refusal the buyer can answer (an invalid card form, too many attempts)
|
|
159
|
+
* resolves as `failed`; an expired or unknown session as `expired`.
|
|
160
|
+
*/
|
|
161
|
+
checkoutSource(sessionId: string, opts?: CheckoutSourceOptions): CheckoutSource;
|
|
144
162
|
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* or unknown session as `expired`.
|
|
163
|
+
* The deployment's public configuration: what the mount serves, the
|
|
164
|
+
* currency registry and the merchant's payment setup. React components
|
|
165
|
+
* share one copy through `useConfig()`.
|
|
149
166
|
*/
|
|
150
|
-
|
|
151
|
-
/** Network and accepted tokens; served only with a Solana PSP. */
|
|
152
|
-
getSolanaConfig(signal?: AbortSignal): Promise<SolanaConfig>;
|
|
167
|
+
getConfig(signal?: AbortSignal): Promise<PublicConfig>;
|
|
153
168
|
/**
|
|
154
|
-
* Accepted tokens with live prices. `priceId`
|
|
155
|
-
*
|
|
169
|
+
* Accepted tokens with live prices. `priceId` adds each token's `quote`;
|
|
170
|
+
* `wallet` adds its `balance`.
|
|
156
171
|
*/
|
|
157
172
|
listSolanaTokens(opts?: {
|
|
158
173
|
priceId?: string;
|
|
159
|
-
checkoutSessionId?: string;
|
|
160
174
|
wallet?: string;
|
|
161
175
|
signal?: AbortSignal;
|
|
162
176
|
}): Promise<SolanaToken[]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const OPENRAILS_CURRENCY_SCALES: Readonly<Record<string, number>>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type OpenRailsErrorCode = "access_token_invalid" | "access_token_issuer_unknown" | "access_token_merchant_not_bound" | "admission_captured" | "admission_not_found" | "allowance_meter_not_found" | "allowance_source_in_use" | "allowance_source_invalid" | "api_host_claim_missing" | "api_host_reserved" | "api_host_taken" | "api_host_unproven" | "as_of_required" | "authentication_required" | "authentication_unavailable" | "authorization_unavailable" | "billing_archive_integrity" | "billing_archive_invalid_artifact" | "billing_archive_merchant_mismatch" | "billing_archive_not_empty" | "billing_archive_unavailable" | "billing_archive_unsupported_state" | "billing_policy_not_found" | "cancel_unsupported_on_rail" | "captcha_invalid" | "captcha_required" | "card_attempts_blocked" | "card_declined" | "card_not_saved" | "card_requires_https" | "catalog_benefit_overlap" | "catalog_revision_conflict" | "catalog_updates_disabled" | "checkout_attempt_closed" | "checkout_attempt_expired" | "checkout_offer_unavailable" | "checkout_payment_in_progress" | "checkout_request_invalid" | "checkout_session_expired" | "checkout_session_not_found" | "checkout_session_unavailable" | "collection_payment_method_invalid" | "collection_payment_method_required" | "creation_refused" | "credential_custody_transition_required" | "credential_expired" | "credential_identity_mismatch" | "credential_operation_conflict" | "credential_revoked" | "credential_source_read_only" | "credential_store_read_only" | "credentials_manage_required" | "credit_grant_held" | "credit_grant_not_found" | "credit_grant_unavailable" | "csrf_origin_denied" | "currency_unsupported" | "custodian_capture_unavailable" | "customer_action_required" | "customer_blocked" | "customer_email_required" | "customer_not_found" | "customer_payment_unsupported" | "customer_proof_required" | "customer_session_required" | "dashboard_invalid" | "database_busy" | "default_rate_card_not_found" | "default_rate_card_required" | "delegated_principal_invalid" | "email_unverified" | "finding_action_failed" | "finding_not_actionable" | "hold_not_found" | "host_event_not_found" | "host_merchant_mismatch" | "host_principal_invalid" | "idempotency_key_required" | "idempotency_key_reused" | "insufficient_credits" | "insufficient_funds" | "insufficient_scope" | "internal_error" | "invalid_api_host" | "invalid_cursor" | "invalid_customer_id" | "invalid_email" | "invalid_host_event_request" | "invalid_name" | "invalid_param" | "invalid_payment_method" | "invalid_psp_reference" | "invalid_query" | "invalid_request_body" | "invalid_settlement_status_request" | "invalid_user" | "invites_disabled" | "invoice_action_not_allowed" | "invoice_not_retryable" | "invoice_payment_exceeds_due" | "invoice_payment_invalid" | "invoice_payment_reference_used" | "invoice_retry_idempotency_conflict" | "invoice_retry_in_progress" | "invoice_retry_outcome_unknown" | "invoker_scoped_principal" | "last_owner" | "members_manage_required" | "merchant_binding_mismatch" | "merchant_configuration_application_conflict" | "merchant_configuration_revision_conflict" | "merchant_context_mismatch" | "merchant_creation_payment_method_required" | "merchant_directory_unavailable" | "merchant_not_found" | "merchant_selector_invalid" | "merchant_unresolved" | "meter_in_use" | "meter_rate_card_conflict" | "method_not_allowed" | "metrics_query_invalid" | "model_unavailable" | "name_reserved" | "name_taken" | "operation_authorization_conflict" | "operation_authorization_has_billing_evidence" | "operation_authorization_not_found" | "operation_authorization_not_open" | "payment_duplicate_refused" | "payment_failed" | "payment_idempotency_conflict" | "payment_in_progress" | "payment_method_delete_failed" | "payment_method_delete_unsupported" | "payment_method_not_psp_vaulted" | "payment_method_not_usable" | "payment_method_psp_mismatch" | "payment_method_required" | "payment_method_same_vault" | "payment_method_stale" | "payment_method_update_failed" | "payment_method_update_retry_required" | "payment_method_update_unsupported" | "payment_not_found" | "payment_not_refundable" | "payment_not_retryable" | "payment_provider_rejected" | "permission_required" | "price_key_cadence_conflict" | "price_key_not_found" | "price_not_found" | "price_not_sellable" | "product_not_found" | "product_tier_group_conflict" | "product_tier_group_in_use" | "provider_billing_observation_conflict" | "provider_billing_qualification_not_found" | "provider_billing_qualification_not_refused" | "provider_billing_qualification_refused" | "provider_billing_refusal_conflict" | "provider_billing_resolution_conflict" | "provider_cancel_held" | "provider_outcome_unknown" | "psp_claim_requires_proof" | "psp_credentials_rejected" | "psp_exists" | "psp_key_taken" | "psp_last_active" | "psp_not_found" | "purchase_review_resolved" | "rate_card_currency_mismatch" | "rate_card_has_overrides" | "rate_card_product_not_found" | "rate_limit_exceeded" | "rebill_terms_committed" | "refund_failed" | "refund_rail_unavailable" | "refund_unsupported" | "rename_too_soon" | "renames_disabled" | "reprice_already_scheduled" | "reprice_cross_currency" | "reprice_cross_product" | "reprice_inactive_price" | "reprice_not_found" | "reprice_not_scheduled" | "reprice_notice_window_violation" | "reprice_price_key_not_found" | "reprice_target_price_not_found" | "request_body_too_large" | "resource_access_denied" | "resource_conflict" | "resource_not_found" | "role_escalation" | "route_not_found" | "sender_proof_required" | "service_credential_customer_scope_denied" | "service_credential_invalid" | "service_credential_merchant_unresolved" | "service_credential_resource_scope_denied" | "service_unavailable" | "solana_rpc_unavailable" | "solana_transaction_refused" | "spend_delegation_not_found" | "step_up_required" | "step_up_unavailable" | "subscription_not_active" | "subscription_not_found" | "subscription_paid_through" | "subscription_resumable" | "tier_change_already_scheduled" | "tier_change_cadence_unsupported" | "tier_change_credit_exceeds_price" | "tier_change_cycle_unknown" | "tier_change_idempotency_conflict" | "tier_change_idempotency_key_required" | "tier_change_in_flight" | "tier_change_period_unknown" | "tier_change_provider_conflict" | "tier_change_refused" | "tier_change_renewal_due" | "tier_change_requires_linked_plan" | "tier_change_target_inactive" | "tier_change_unsupported_on_rail" | "trial_unsupported_on_rail" | "unknown_field" | "unknown_role" | "unsupported_media_type" | "usage_meter_invalid" | "usage_meter_not_found" | "usage_rate_card_invalid" | "use_dpop_nonce" | "webhook_account_mismatch" | "webhook_invalid" | "widget_generation_invalid";
|
|
2
|
+
export type OpenRailsErrorType = "api_error" | "authentication_error" | "authorization_error" | "card_error" | "invalid_request_error" | "rate_limit_error";
|
|
3
|
+
export declare const OPENRAILS_ERROR_CODES: Readonly<Record<OpenRailsErrorCode, {
|
|
4
|
+
status: number;
|
|
5
|
+
type: OpenRailsErrorType;
|
|
6
|
+
meaning: string;
|
|
7
|
+
}>>;
|