@sixtyninecommerce/admin 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +359 -2
  2. package/dist/apps/assertion.d.ts +30 -3
  3. package/dist/apps/assertion.js +40 -3
  4. package/dist/apps/config.d.ts +39 -0
  5. package/dist/apps/config.js +22 -0
  6. package/dist/apps/credential.d.ts +5 -0
  7. package/dist/apps/credential.js +55 -4
  8. package/dist/apps/index.d.ts +11 -0
  9. package/dist/client.d.ts +54 -1
  10. package/dist/client.js +34 -1
  11. package/dist/custom-objects/index.d.ts +66 -0
  12. package/dist/custom-objects/index.js +48 -0
  13. package/dist/customers/index.d.ts +225 -0
  14. package/dist/customers/index.js +279 -0
  15. package/dist/documents/index.d.ts +432 -0
  16. package/dist/documents/index.js +289 -0
  17. package/dist/index.d.ts +34 -2
  18. package/dist/index.js +16 -1
  19. package/dist/jobs/index.d.ts +143 -0
  20. package/dist/jobs/index.js +132 -0
  21. package/dist/metafields/index.d.ts +291 -0
  22. package/dist/metafields/index.js +141 -0
  23. package/dist/orders/index.d.ts +106 -0
  24. package/dist/orders/index.js +115 -0
  25. package/dist/orders/surcharges.d.ts +121 -0
  26. package/dist/orders/surcharges.js +110 -0
  27. package/dist/payments/index.d.ts +103 -0
  28. package/dist/payments/index.js +55 -0
  29. package/dist/payments/providers.d.ts +281 -0
  30. package/dist/payments/providers.js +205 -0
  31. package/dist/platform/provision-store.d.ts +9 -26
  32. package/dist/platform/provision-store.js +8 -66
  33. package/dist/tax/index.d.ts +128 -0
  34. package/dist/tax/index.js +101 -0
  35. package/dist/tenant/capabilities.d.ts +15 -0
  36. package/dist/types.d.ts +20 -3
  37. package/dist/uploads/index.d.ts +146 -0
  38. package/dist/uploads/index.js +72 -0
  39. package/package.json +3 -3
@@ -0,0 +1,121 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * A surcharge: an adjustment on a PLACED order that is not a line — a delivery
5
+ * charge, a negotiated discount, a handling fee.
6
+ *
7
+ * Money is integer MINOR UNITS of the order's currency, and `price` is NEGATIVE
8
+ * for a discount. `priceIncludesTax` says which basis the amount is stated in;
9
+ * there is no default, because guessing it is a 21% error.
10
+ */
11
+ export interface SurchargeInput {
12
+ description: string;
13
+ sku?: string | null;
14
+ /** Minor units. Negative for a discount agreed after the order was placed. */
15
+ price: number;
16
+ /** Whether `price` is gross. Required: the engine will not guess a basis. */
17
+ priceIncludesTax: boolean;
18
+ /**
19
+ * Percentage (21 for 21%). Omit it for no tax line at all — and never send it
20
+ * together with `taxClass`, which is refused rather than silently resolved
21
+ * one way.
22
+ */
23
+ taxRate?: number | null;
24
+ /**
25
+ * Label for the tax line. Refused together with `taxClass`: a class-priced
26
+ * line is named by the store's own tax setup — including names that are a
27
+ * policy statement, like `EU Reverse Charge (0%)` — and relabelling one would
28
+ * put on an invoice something the line is not.
29
+ */
30
+ taxDescription?: string | null;
31
+ }
32
+ /** Options for a surcharge write. */
33
+ export interface SurchargeCall extends Call {
34
+ /**
35
+ * Price the surcharge from one of the store's tax classes (spec §8.6)
36
+ * instead of from an explicit `taxRate`.
37
+ *
38
+ * Resolved PER ORDER, which is the half of the platform's tax-class decision
39
+ * that is not write-time: a surcharge is money the platform composes, with no
40
+ * product variant behind it to have been priced already.
41
+ *
42
+ * **Which country, and which zone — they are two different questions.** The
43
+ * order's shipping COUNTRY picks the class's mapping (that is the store's own
44
+ * "what kind of thing is this" decision, one row per country). The order's
45
+ * tax ZONE picks the rate for the category that mapping names. The two can
46
+ * legitimately differ: a store only moves a country into its own zone by
47
+ * listing it in the tax-exclusive countries setting, so a Belgian order on a
48
+ * store that has not listed BE is still priced in the store's default zone
49
+ * while the BE mapping decides the category. Map a country and configure that
50
+ * zone's rates, or the write is refused rather than silently untaxed.
51
+ *
52
+ * **The order's own tax policy still wins.** A tax-removed order and an EU
53
+ * reverse charge override whatever the class resolved to, because the
54
+ * resolved rate is run through the same tax-line strategy the order's lines
55
+ * go through. The class chooses which rate is looked up, never what the line
56
+ * finally says. A per-line rate imported from an ERP is the one policy that
57
+ * does NOT carry over: it belongs to a line the ERP sent, never to a charge
58
+ * the merchant adds afterwards.
59
+ *
60
+ * Refusals: `TAX_CLASS_NOT_FOUND` (→ `NotFoundError`) for a key this store
61
+ * does not have; `TAX_CLASS_UNMAPPED` (→ `ValidationError`) when the class
62
+ * says nothing about the order's country and has no `*` fallback; and
63
+ * `TAX_CLASS_RATE_MISSING` (→ `ValidationError`) when it is mapped but that
64
+ * category has no rate in the order's zone. Sending it together with
65
+ * `input.taxRate` or `input.taxDescription` is refused as bad input.
66
+ */
67
+ taxClass?: string;
68
+ }
69
+ /**
70
+ * The order the mutation answers with, as much of it as this surface projects.
71
+ *
72
+ * The totals are re-derived and PERSISTED by every one of these calls, so the
73
+ * numbers here are the order's new state rather than a projection of the
74
+ * request.
75
+ */
76
+ export interface SurchargedOrder {
77
+ id: string;
78
+ code: string;
79
+ currencyCode: string;
80
+ /** Minor units. */
81
+ total: number;
82
+ totalWithTax: number;
83
+ surcharges: Array<{
84
+ id: string;
85
+ description: string;
86
+ sku: string | null;
87
+ price: number;
88
+ priceWithTax: number;
89
+ taxRate: number;
90
+ }>;
91
+ }
92
+ /**
93
+ * Surcharges on a placed order.
94
+ *
95
+ * These exist beside Vendure's `modifyOrder`, which hard-requires a refund
96
+ * input for ANY downward price delta — so it cannot express "remove this
97
+ * discount" at all on an order with no payment to refund against. Needs
98
+ * `UpdateOrder`; refused once the order's invoice has been approved.
99
+ */
100
+ export interface SurchargesModule {
101
+ /** Add a surcharge and re-total the order. */
102
+ add(orderId: string, input: SurchargeInput, options?: SurchargeCall): Promise<SurchargedOrder>;
103
+ /**
104
+ * Replace a surcharge in place and re-total the order. The surcharge keeps
105
+ * its id, so a delivery charge stays linked to the fulfillment that created
106
+ * it, and an omitted `sku` is left alone rather than cleared.
107
+ *
108
+ * TAX IS NOT LIKE `sku`: this is a whole replacement, so omitting BOTH
109
+ * `options.taxClass` and `input.taxRate` writes a surcharge with no tax line
110
+ * at all and lowers the order total. Re-send whichever of the two the
111
+ * surcharge should carry — a `taxClass` is then resolved afresh, so the rate
112
+ * that applies now is the one written.
113
+ */
114
+ update(orderId: string, surchargeId: string, input: SurchargeInput, options?: SurchargeCall): Promise<SurchargedOrder>;
115
+ /** Remove a surcharge entirely and re-total the order. */
116
+ remove(orderId: string, surchargeId: string, options?: Call): Promise<SurchargedOrder>;
117
+ }
118
+ export declare const ADD_ORDER_SURCHARGE_MUTATION = "\n mutation AddOrderSurcharge(\n $orderId: ID!\n $input: SurchargeInput!\n $taxClass: String\n $idempotencyKey: String\n ) {\n addOrderSurcharge(\n orderId: $orderId\n input: $input\n taxClass: $taxClass\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
119
+ export declare const UPDATE_ORDER_SURCHARGE_MUTATION = "\n mutation UpdateOrderSurcharge(\n $orderId: ID!\n $surchargeId: ID!\n $input: SurchargeInput!\n $taxClass: String\n $idempotencyKey: String\n ) {\n updateOrderSurcharge(\n orderId: $orderId\n surchargeId: $surchargeId\n input: $input\n taxClass: $taxClass\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
120
+ export declare const REMOVE_ORDER_SURCHARGE_MUTATION = "\n mutation RemoveOrderSurcharge($orderId: ID!, $surchargeId: ID!, $idempotencyKey: String) {\n removeOrderSurcharge(\n orderId: $orderId\n surchargeId: $surchargeId\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
121
+ export declare function createSurchargesModule(transport: Transport): SurchargesModule;
@@ -0,0 +1,110 @@
1
+ const SURCHARGED_ORDER_FIELDS = /* GraphQL */ `
2
+ id
3
+ code
4
+ currencyCode
5
+ total
6
+ totalWithTax
7
+ surcharges {
8
+ id
9
+ description
10
+ sku
11
+ price
12
+ priceWithTax
13
+ taxRate
14
+ }
15
+ `;
16
+ export const ADD_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
17
+ mutation AddOrderSurcharge(
18
+ $orderId: ID!
19
+ $input: SurchargeInput!
20
+ $taxClass: String
21
+ $idempotencyKey: String
22
+ ) {
23
+ addOrderSurcharge(
24
+ orderId: $orderId
25
+ input: $input
26
+ taxClass: $taxClass
27
+ idempotencyKey: $idempotencyKey
28
+ ) {
29
+ ${SURCHARGED_ORDER_FIELDS}
30
+ }
31
+ }
32
+ `;
33
+ export const UPDATE_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
34
+ mutation UpdateOrderSurcharge(
35
+ $orderId: ID!
36
+ $surchargeId: ID!
37
+ $input: SurchargeInput!
38
+ $taxClass: String
39
+ $idempotencyKey: String
40
+ ) {
41
+ updateOrderSurcharge(
42
+ orderId: $orderId
43
+ surchargeId: $surchargeId
44
+ input: $input
45
+ taxClass: $taxClass
46
+ idempotencyKey: $idempotencyKey
47
+ ) {
48
+ ${SURCHARGED_ORDER_FIELDS}
49
+ }
50
+ }
51
+ `;
52
+ export const REMOVE_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
53
+ mutation RemoveOrderSurcharge($orderId: ID!, $surchargeId: ID!, $idempotencyKey: String) {
54
+ removeOrderSurcharge(
55
+ orderId: $orderId
56
+ surchargeId: $surchargeId
57
+ idempotencyKey: $idempotencyKey
58
+ ) {
59
+ ${SURCHARGED_ORDER_FIELDS}
60
+ }
61
+ }
62
+ `;
63
+ /**
64
+ * `undefined` rather than `null` for an absent tax class: a variable explicitly
65
+ * set to null is still a value the engine reads, and this argument's whole
66
+ * contract is "omit it and the legacy `taxRate` path is untouched".
67
+ */
68
+ function taxClassVariable(options) {
69
+ const value = options?.taxClass;
70
+ return typeof value === 'string' && value.trim() !== '' ? value : undefined;
71
+ }
72
+ export function createSurchargesModule(transport) {
73
+ return {
74
+ async add(orderId, input, options) {
75
+ const data = await transport.graphql({
76
+ api: 'admin',
77
+ query: ADD_ORDER_SURCHARGE_MUTATION,
78
+ variables: {
79
+ orderId,
80
+ input,
81
+ taxClass: taxClassVariable(options),
82
+ idempotencyKey: options?.idempotencyKey,
83
+ },
84
+ }, options);
85
+ return data.addOrderSurcharge;
86
+ },
87
+ async update(orderId, surchargeId, input, options) {
88
+ const data = await transport.graphql({
89
+ api: 'admin',
90
+ query: UPDATE_ORDER_SURCHARGE_MUTATION,
91
+ variables: {
92
+ orderId,
93
+ surchargeId,
94
+ input,
95
+ taxClass: taxClassVariable(options),
96
+ idempotencyKey: options?.idempotencyKey,
97
+ },
98
+ }, options);
99
+ return data.updateOrderSurcharge;
100
+ },
101
+ async remove(orderId, surchargeId, options) {
102
+ const data = await transport.graphql({
103
+ api: 'admin',
104
+ query: REMOVE_ORDER_SURCHARGE_MUTATION,
105
+ variables: { orderId, surchargeId, idempotencyKey: options?.idempotencyKey },
106
+ }, options);
107
+ return data.removeOrderSurcharge;
108
+ },
109
+ };
110
+ }
@@ -0,0 +1,103 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ import { type ProvidersModule } from './providers.js';
4
+ /**
5
+ * What an order has actually been paid, in minor units of its own currency.
6
+ *
7
+ * Derived from the order's payments on every read, never stored — a stored copy
8
+ * is a second source of truth that drifts the first time a refund lands.
9
+ */
10
+ export interface OrderPaymentPosition {
11
+ /** The order's own gross total, carrying the order's rounding rule. */
12
+ total: number;
13
+ /** Settled plus authorized, less refunds: what is accounted for. */
14
+ covered: number;
15
+ /** Money actually taken, less refunds. This is what `orders.settle` requires. */
16
+ settled: number;
17
+ /** Money a payment handler may take and has not. */
18
+ authorized: number;
19
+ refunded: number;
20
+ /** `total - covered`, floored at zero. */
21
+ outstanding: number;
22
+ /**
23
+ * `covered - total`, floored at zero. Over-payment is refused at the door, so
24
+ * this is non-zero only for imported history, rows predating the guard, or a
25
+ * refund that landed after a second payment.
26
+ */
27
+ overpaid: number;
28
+ /** What a further payment may take. */
29
+ availableToCharge: number;
30
+ }
31
+ /** Money the merchant HAS, recorded against an order. */
32
+ export interface RecordPaymentInput {
33
+ /**
34
+ * Minor units of the order's currency. Greater than zero, and at most the
35
+ * order's `outstanding` — an over-payment is refused rather than accepted,
36
+ * and the refusal carries the position so a till can correct itself without a
37
+ * second round trip.
38
+ */
39
+ amount: number;
40
+ /** A payment method code configured on this channel. */
41
+ method: string;
42
+ /**
43
+ * Free-form detail stored on the payment, MINUS two keys the platform writes
44
+ * itself: `attribution` (the vouched-for staff, device and register refs) and
45
+ * `isDeposit`. Sending either is refused with `METADATA_KEY_RESERVED` rather
46
+ * than merged, so no caller can invent a till or a member of staff that every
47
+ * later report would believe.
48
+ *
49
+ * Anything you put under `public` is visible to the storefront — Vendure's
50
+ * Shop API exposes `metadata.public`. The platform never writes there.
51
+ */
52
+ metadata?: Record<string, unknown>;
53
+ }
54
+ /** The order, as much of it as this surface projects. */
55
+ export interface PaidOrder {
56
+ id: string;
57
+ code: string;
58
+ state: string;
59
+ currencyCode: string;
60
+ total: number;
61
+ totalWithTax: number;
62
+ }
63
+ /**
64
+ * Payments: money against an order (spec §8.2), and the provider accounts
65
+ * it runs through (spec §8.9).
66
+ *
67
+ * `providers` is payment-provider onboarding, terminals and readiness. The
68
+ * rest of this namespace is the money itself.
69
+ *
70
+ * `record` writes money the merchant HAS, which lands the payment `Settled`.
71
+ * There is no payment state to choose: an AUTHORIZATION is a payment method
72
+ * handler's business — the gateway decides whether a card may be charged later
73
+ * — so one cannot be created here. Authorized payments that handlers DO create
74
+ * are counted by `position()` all the same, under `authorized`; only the write
75
+ * side is narrowed.
76
+ *
77
+ * Needs `UpdateOrder` to record, `ReadOrder` to read the position.
78
+ */
79
+ export interface PaymentsModule {
80
+ /** Provider onboarding, terminals and readiness (spec §8.9). */
81
+ providers: ProvidersModule;
82
+ /**
83
+ * Record part (or all) of what an order owes, and return the order.
84
+ *
85
+ * `options.idempotencyKey` is honoured: the Admin API takes it as a mutation
86
+ * argument, so a retry under the same key returns the first call's order
87
+ * rather than taking the money twice. Use a fresh key per intended payment.
88
+ *
89
+ * Refusals: `AMOUNT_EXCEEDS_OUTSTANDING` (over-payment, with the position
90
+ * attached), `AMOUNT_NOT_POSITIVE`, `ORDER_NOT_RECORDABLE` (the order's state
91
+ * cannot take a payment), `DEPOSITS_NOT_ENABLED` — a PARTIAL payment on a
92
+ * store that has not turned deposits on; paying the whole outstanding balance
93
+ * is not a deposit and always works — `METADATA_KEY_RESERVED`,
94
+ * `PAYMENT_METHOD_NOT_FOUND`, `ORDER_NOT_FOUND`.
95
+ */
96
+ record(orderId: string, input: RecordPaymentInput, options?: Call): Promise<PaidOrder>;
97
+ /** Read an order's payment position. */
98
+ position(orderId: string, options?: Call): Promise<OrderPaymentPosition>;
99
+ }
100
+ export declare const RECORD_ORDER_PAYMENT_MUTATION = "\n mutation RecordOrderPayment($orderId: ID!, $input: RecordPaymentInput!, $idempotencyKey: String) {\n recordOrderPayment(orderId: $orderId, input: $input, idempotencyKey: $idempotencyKey) {\n \n id\n code\n state\n currencyCode\n total\n totalWithTax\n\n }\n }\n";
101
+ export declare const ORDER_PAYMENT_POSITION_QUERY = "\n query OrderPaymentPosition($orderId: ID!) {\n orderPaymentPosition(orderId: $orderId) {\n \n total\n covered\n settled\n authorized\n refunded\n outstanding\n overpaid\n availableToCharge\n\n }\n }\n";
102
+ export declare function createPaymentsModule(transport: Transport): PaymentsModule;
103
+ export type { ProviderConnection, ProviderCredentialPath, ProviderOnboardingStart, ProviderReadiness, ProvidersModule, ProviderTerminal, ProviderTerminalsModule, ProvisionTerminalInput, ReadinessOptions, } from './providers.js';
@@ -0,0 +1,55 @@
1
+ import { createProvidersModule } from './providers.js';
2
+ const PAID_ORDER_FIELDS = /* GraphQL */ `
3
+ id
4
+ code
5
+ state
6
+ currencyCode
7
+ total
8
+ totalWithTax
9
+ `;
10
+ const POSITION_FIELDS = /* GraphQL */ `
11
+ total
12
+ covered
13
+ settled
14
+ authorized
15
+ refunded
16
+ outstanding
17
+ overpaid
18
+ availableToCharge
19
+ `;
20
+ export const RECORD_ORDER_PAYMENT_MUTATION = /* GraphQL */ `
21
+ mutation RecordOrderPayment($orderId: ID!, $input: RecordPaymentInput!, $idempotencyKey: String) {
22
+ recordOrderPayment(orderId: $orderId, input: $input, idempotencyKey: $idempotencyKey) {
23
+ ${PAID_ORDER_FIELDS}
24
+ }
25
+ }
26
+ `;
27
+ export const ORDER_PAYMENT_POSITION_QUERY = /* GraphQL */ `
28
+ query OrderPaymentPosition($orderId: ID!) {
29
+ orderPaymentPosition(orderId: $orderId) {
30
+ ${POSITION_FIELDS}
31
+ }
32
+ }
33
+ `;
34
+ export function createPaymentsModule(transport) {
35
+ return {
36
+ providers: createProvidersModule(transport),
37
+ async record(orderId, input, options) {
38
+ const data = await transport.graphql({
39
+ api: 'admin',
40
+ query: RECORD_ORDER_PAYMENT_MUTATION,
41
+ // Forwarded as a VARIABLE, not a header: the Admin API has no header
42
+ // for it, which is why the mutation takes the key as an argument.
43
+ // `undefined`, never an explicit null — `JSON.stringify` drops it, so
44
+ // an omitted key stays off the wire entirely rather than arriving as a
45
+ // value a future server could read as one.
46
+ variables: { orderId, input, idempotencyKey: options?.idempotencyKey },
47
+ }, options);
48
+ return data.recordOrderPayment;
49
+ },
50
+ async position(orderId, options) {
51
+ const data = await transport.graphql({ api: 'admin', query: ORDER_PAYMENT_POSITION_QUERY, variables: { orderId } }, options);
52
+ return data.orderPaymentPosition;
53
+ },
54
+ };
55
+ }
@@ -0,0 +1,281 @@
1
+ import { type Page, type Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * Which credential a store is actually paying through.
5
+ *
6
+ * `connect` — an account the store onboarded through the platform.
7
+ * `legacy` — the channel's own per-provider API key, as it has always worked.
8
+ * Supported indefinitely: a store moves when it chooses to, and both paths
9
+ * can be fully ready.
10
+ * `none` — neither, so nothing can be charged.
11
+ */
12
+ export type ProviderCredentialPath = 'connect' | 'legacy' | 'none';
13
+ /** A payment provider's account, as the platform holds it for one seller. */
14
+ export interface ProviderConnection {
15
+ id: string;
16
+ /**
17
+ * The legal entity this account belongs to, resolved from the channel's
18
+ * seller. Several stores of one seller SHARE a connection — the money lands
19
+ * in one place and the merchant onboards once.
20
+ */
21
+ sellerId: string;
22
+ /** Provider key — `test`, `mollie`, `stripe`. */
23
+ provider: string;
24
+ /** `pending` while onboarding is in flight, then `connected` or `disconnected`. */
25
+ status: string;
26
+ /**
27
+ * The account's PUBLIC id at the provider. Null while pending. Never a
28
+ * secret: credentials stay with the provider package that obtained them.
29
+ */
30
+ externalId: string | null;
31
+ scopes: string[];
32
+ /** Payment methods active on the account, as the provider reports them. */
33
+ activeMethods: string[];
34
+ /**
35
+ * `test` or `live`, as the provider reported it when the account was
36
+ * connected. REPORTED, not enforced: the rule that a sandbox store may hold
37
+ * only a `test` connection needs a way to identify a sandbox store, which
38
+ * does not exist yet. The mode is recorded now so that rule has something to
39
+ * act on the day it lands.
40
+ */
41
+ mode: string;
42
+ connectedAt: string | null;
43
+ /**
44
+ * Set when the connection ended. The row STAYS — which account a store was
45
+ * paid through outlives the connection, and it is the first thing anyone asks
46
+ * after a dispute.
47
+ */
48
+ disconnectedAt: string | null;
49
+ createdAt: string;
50
+ updatedAt: string;
51
+ }
52
+ /** A card terminal registered against a connection. Terminals are per Location. */
53
+ export interface ProviderTerminal {
54
+ id: string;
55
+ /** The terminal's id at the provider — the identity a re-provision reuses. */
56
+ externalId: string;
57
+ label: string;
58
+ /** The stock location it serves, or null while it is unassigned. */
59
+ stockLocationId: string | null;
60
+ status: string;
61
+ lastSeenAt: string | null;
62
+ createdAt: string;
63
+ updatedAt: string;
64
+ }
65
+ /** Where to send the merchant, and the state to hand back on return. */
66
+ export interface ProviderOnboardingStart {
67
+ url: string;
68
+ /** Opaque and single-use. Pass it to {@link ProvidersModule.completeOnboarding}. */
69
+ state: string;
70
+ mode: string;
71
+ }
72
+ /**
73
+ * Independently verifiable evidence that this store can be paid through this
74
+ * provider — never a UI flag. Each signal is a row, the provider's own answer,
75
+ * a count, or one piece of arithmetic on the order.
76
+ */
77
+ export interface ProviderReadiness {
78
+ provider: string;
79
+ /** Which credential this verdict is about. Both `connect` and `legacy` can be ready. */
80
+ path: ProviderCredentialPath;
81
+ /** `test` or `live` when there is a connection; null on the legacy path. */
82
+ mode: string | null;
83
+ connected: boolean;
84
+ /**
85
+ * The software for this provider is loaded in the deployment you are talking
86
+ * to.
87
+ *
88
+ * False only for a store that IS connected through a provider package the
89
+ * deployment no longer runs. Nothing about the credential is known then, and
90
+ * it is not the merchant's to fix — show the blocker, do not offer a
91
+ * reconnect. A provider the server has never heard of is refused instead.
92
+ */
93
+ adapterAvailable: boolean;
94
+ /**
95
+ * The provider ANSWERED when the server asked about this account.
96
+ *
97
+ * False means the call did not come back — an outage, a timeout — so nothing
98
+ * else here about the credential was verified and `blockers` holds that one
99
+ * sentence. Retry; do NOT send the merchant to reconnect on it. Always true
100
+ * on the `legacy` path and with no credential, where there is no probe.
101
+ */
102
+ providerReachable: boolean;
103
+ /**
104
+ * On the `connect` path: the provider itself accepts the stored credential
105
+ * RIGHT NOW. On the `legacy` path it means only that the store holds a key on
106
+ * an enabled method — the server never reads that key here, so a legacy key
107
+ * the provider has since revoked still reads `true`.
108
+ */
109
+ credentialUsable: boolean;
110
+ methodActive: boolean;
111
+ terminalProvisioned: boolean;
112
+ /**
113
+ * A registered terminal serves the `locationId` you asked about — and `false`
114
+ * when you asked about none, since there is no location for it to be true of.
115
+ * Same for `orderPayable`. Neither produces a blocker or moves `overall`
116
+ * outside its own question, so do not render either as a problem unless you
117
+ * asked the question it answers.
118
+ */
119
+ terminalUsableForLocation: boolean;
120
+ /**
121
+ * The provider can take PART of an order's total. Reported, never gating: it
122
+ * answers your question (may I take a deposit), not whether the store can be
123
+ * paid at all.
124
+ */
125
+ partialSupported: boolean;
126
+ orderPayable: boolean;
127
+ /**
128
+ * The answer to "can this store be paid through this provider" FOR THE
129
+ * QUESTION ASKED. Signals outside it do not gate: a web-only store with no
130
+ * terminal is ready, because you did not ask about a location.
131
+ */
132
+ overall: boolean;
133
+ /**
134
+ * The server's evidence for anything short of a clean pass, one entry per
135
+ * failing gate, in the platform's own words. Never a sentence this SDK
136
+ * composed, and never a blocker for something you did not ask about.
137
+ */
138
+ blockers: string[];
139
+ }
140
+ export interface ProvisionTerminalInput {
141
+ /** What the merchant calls it — "Counter 1". At most 120 characters. */
142
+ label: string;
143
+ /** Assign it to this stock location as it is created. Must be in this channel. */
144
+ stockLocationId?: string | null;
145
+ }
146
+ export interface ReadinessOptions extends Call {
147
+ /** Ask about a specific order: `orderPayable` then gates the verdict. */
148
+ orderId?: string;
149
+ /** Ask about a counter sale: the terminal signals then gate the verdict. */
150
+ locationId?: string;
151
+ }
152
+ /** Terminals of one provider. */
153
+ export interface ProviderTerminalsModule {
154
+ /**
155
+ * The terminals this platform holds. A pure read of stored rows; see
156
+ * {@link refresh} for reconciling with the provider.
157
+ *
158
+ * A `Page` because every list in this SDK is one (spec §9.2), not because
159
+ * this query pages: it answers the complete array.
160
+ */
161
+ list(provider: string, options?: Call): Promise<Page<ProviderTerminal>>;
162
+ /**
163
+ * Reconcile with the provider: new readers are recorded, known ones updated,
164
+ * and one the provider no longer reports is marked `inactive` so it stops
165
+ * counting towards readiness. Rows are never deleted — a row is the evidence
166
+ * that a reader existed and where it stood.
167
+ *
168
+ * A WRITE (`UpdatePaymentMethod`), because it changes what the platform holds.
169
+ */
170
+ refresh(provider: string, options?: Call): Promise<Page<ProviderTerminal>>;
171
+ /**
172
+ * Ask the provider for a terminal.
173
+ *
174
+ * Provisioning the same reader twice is the SAME reader — the provider's id
175
+ * is the identity — so this is safe to retry even without a key. Send
176
+ * `idempotencyKey` to make the whole mutation replay instead.
177
+ */
178
+ provision(provider: string, input: ProvisionTerminalInput, options?: Call): Promise<ProviderTerminal>;
179
+ /** Put a terminal on a location. */
180
+ assign(terminalId: string, locationId: string, options?: Call): Promise<ProviderTerminal>;
181
+ /**
182
+ * Take a terminal off its location. The row stays: the reader still exists.
183
+ *
184
+ * This is the ONLY way to unassign through this SDK — `assign` requires a
185
+ * location id. (The underlying mutation accepts a null `locationId` too; the
186
+ * SDK keeps the two intents as two methods so neither call has a meaningless
187
+ * argument.)
188
+ */
189
+ unassign(terminalId: string, options?: Call): Promise<ProviderTerminal>;
190
+ }
191
+ /**
192
+ * Payment-provider onboarding, terminals and readiness (headless spec §8.9).
193
+ *
194
+ * ## A connection belongs to the SELLER, not to the store
195
+ *
196
+ * A PSP account belongs to the legal entity that gets paid, so several stores of
197
+ * one seller share one connection: onboard once, and the money lands in one
198
+ * place. A store whose channel has no seller is refused with `SELLER_REQUIRED`
199
+ * rather than given a connection keyed on nothing.
200
+ *
201
+ * ## Two credential paths, both first-class
202
+ *
203
+ * A store on a raw per-channel API key is supported, not broken — there is no
204
+ * migration, and it moves when it chooses to. {@link readiness} reports which
205
+ * path it is on and treats both equally in `overall`. The per-channel key
206
+ * surface is deprecated in the schema and supported in the code; those are
207
+ * different statements and both are deliberate.
208
+ *
209
+ * ## Readiness is evidence, not a flag
210
+ *
211
+ * Every signal is something you could verify yourself, and `blockers` are the
212
+ * server's words. Ask the question you are about to act on: pass `locationId`
213
+ * for a counter sale and `orderId` for a payment, and signals outside that
214
+ * question are reported without gating `overall` — a web-only store has no
215
+ * terminal and is not broken.
216
+ *
217
+ * **Coded refusals**, delivered as GraphQL errors with `extensions.code`:
218
+ * `SELLER_REQUIRED`, `PAYMENT_PROVIDER_NOT_REGISTERED`, `PROVIDER_NOT_CONNECTED`,
219
+ * `PROVIDER_ALREADY_CONNECTED` (→ `ConflictError`; disconnect first rather than
220
+ * silently re-pointing a store's money), `ONBOARDING_STATE_INVALID`,
221
+ * `PROVIDER_CREDENTIAL_REJECTED`, `TERMINAL_NOT_FOUND` (→ `NotFoundError`),
222
+ * `TERMINAL_REJECTED`, `LIVE_CONNECTION_REFUSED`, and the `INVALID_*` input
223
+ * refusals (→ `ValidationError`). Assigning a terminal to a location of another
224
+ * channel answers `LOCATION_NOT_IN_CHANNEL`, the same code the rest of the
225
+ * platform uses for that one rule.
226
+ */
227
+ export interface ProvidersModule {
228
+ /**
229
+ * Every connection of this store's seller, including disconnected ones: a
230
+ * seller that WAS connected and is not any more gives a different answer to
231
+ * one that never connected at all, and support needs to tell them apart.
232
+ */
233
+ list(options?: Call): Promise<Page<ProviderConnection>>;
234
+ /** One provider's connection, or null when this seller has never connected it. */
235
+ status(provider: string, options?: Call): Promise<ProviderConnection | null>;
236
+ /**
237
+ * Begin connecting this seller's account. Send the merchant to the `url`, and
238
+ * hand the `state` back to {@link completeOnboarding} when they return.
239
+ *
240
+ * Refused with `PROVIDER_ALREADY_CONNECTED` while a live connection exists.
241
+ *
242
+ * This is the one call here that takes NO `idempotencyKey`, and it needs
243
+ * none: a repeat replaces the pending attempt rather than creating a second
244
+ * account, and it answers with a FRESH url and state — which is what a
245
+ * merchant who lost the first link needs. Storing the answer for a day would
246
+ * re-serve a link that may be single-use and, once the onboarding is
247
+ * finished, one that can no longer be completed.
248
+ */
249
+ startOnboarding(provider: string, input: {
250
+ returnUrl: string;
251
+ }, options?: Call): Promise<ProviderOnboardingStart>;
252
+ /**
253
+ * Finish what {@link startOnboarding} began. The `state` is single-use, so a
254
+ * replayed callback cannot re-complete an onboarding.
255
+ */
256
+ completeOnboarding(provider: string, input: {
257
+ state: string;
258
+ code: string;
259
+ }, options?: Call): Promise<ProviderConnection>;
260
+ /** Activate one payment method on the connected account (`ideal`, `pointofsale`, …). */
261
+ activateMethod(provider: string, method: string, options?: Call): Promise<ProviderConnection>;
262
+ /** Can this store be paid through this provider, and if not, what is missing? */
263
+ readiness(provider: string, options?: ReadinessOptions): Promise<ProviderReadiness>;
264
+ /**
265
+ * End the connection at the provider. False when there was nothing to
266
+ * disconnect. The row stays, marked disconnected.
267
+ */
268
+ disconnect(provider: string, options?: Call): Promise<boolean>;
269
+ terminals: ProviderTerminalsModule;
270
+ }
271
+ export declare const PROVIDER_CONNECTIONS_QUERY = "\n query ProviderConnections {\n providerConnections { \n id\n sellerId\n provider\n status\n externalId\n scopes\n activeMethods\n mode\n connectedAt\n disconnectedAt\n createdAt\n updatedAt\n }\n }\n";
272
+ export declare const PROVIDER_READINESS_QUERY = "\n query PaymentProviderReadiness($provider: String!, $orderId: ID, $locationId: ID) {\n paymentProviderReadiness(provider: $provider, orderId: $orderId, locationId: $locationId) {\n \n provider\n path\n mode\n connected\n adapterAvailable\n providerReachable\n credentialUsable\n methodActive\n terminalProvisioned\n terminalUsableForLocation\n partialSupported\n orderPayable\n overall\n blockers\n\n }\n }\n";
273
+ export declare const PROVIDER_TERMINALS_QUERY = "\n query ProviderTerminals($provider: String!) {\n providerTerminals(provider: $provider) { \n id\n externalId\n label\n stockLocationId\n status\n lastSeenAt\n createdAt\n updatedAt\n }\n }\n";
274
+ export declare const START_ONBOARDING_MUTATION = "\n mutation StartPaymentProviderOnboarding($provider: String!, $returnUrl: String!) {\n startPaymentProviderOnboarding(provider: $provider, returnUrl: $returnUrl) {\n url\n state\n mode\n }\n }\n";
275
+ export declare const COMPLETE_ONBOARDING_MUTATION = "\n mutation CompletePaymentProviderOnboarding($provider: String!, $state: String!, $code: String!, $idempotencyKey: String) {\n completePaymentProviderOnboarding(provider: $provider, state: $state, code: $code, idempotencyKey: $idempotencyKey) {\n \n id\n sellerId\n provider\n status\n externalId\n scopes\n activeMethods\n mode\n connectedAt\n disconnectedAt\n createdAt\n updatedAt\n\n }\n }\n";
276
+ export declare const ACTIVATE_METHOD_MUTATION = "\n mutation ActivatePaymentProviderMethod($provider: String!, $method: String!) {\n activatePaymentProviderMethod(provider: $provider, method: $method) { \n id\n sellerId\n provider\n status\n externalId\n scopes\n activeMethods\n mode\n connectedAt\n disconnectedAt\n createdAt\n updatedAt\n }\n }\n";
277
+ export declare const REFRESH_TERMINALS_MUTATION = "\n mutation RefreshProviderTerminals($provider: String!) {\n refreshProviderTerminals(provider: $provider) { \n id\n externalId\n label\n stockLocationId\n status\n lastSeenAt\n createdAt\n updatedAt\n }\n }\n";
278
+ export declare const PROVISION_TERMINAL_MUTATION = "\n mutation ProvisionProviderTerminal($provider: String!, $input: ProvisionTerminalInput!, $idempotencyKey: String) {\n provisionProviderTerminal(provider: $provider, input: $input, idempotencyKey: $idempotencyKey) {\n \n id\n externalId\n label\n stockLocationId\n status\n lastSeenAt\n createdAt\n updatedAt\n\n }\n }\n";
279
+ export declare const ASSIGN_TERMINAL_MUTATION = "\n mutation AssignProviderTerminal($terminalId: ID!, $locationId: ID) {\n assignProviderTerminal(terminalId: $terminalId, locationId: $locationId) { \n id\n externalId\n label\n stockLocationId\n status\n lastSeenAt\n createdAt\n updatedAt\n }\n }\n";
280
+ export declare const DISCONNECT_PROVIDER_MUTATION = "\n mutation DisconnectPaymentProvider($provider: String!) {\n disconnectPaymentProvider(provider: $provider)\n }\n";
281
+ export declare function createProvidersModule(transport: Transport): ProvidersModule;