@wix/himalaya-cli 0.1309.0 → 0.1310.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.
@@ -15,14 +15,14 @@ export interface SessionProvider {
15
15
  /** A catalog item resolved by the backend for the captured member. */
16
16
  export interface PurchaseContext {
17
17
  productId: string;
18
- /** Canonical UUID the backend associates with this site/member. */
18
+ /** Canonical UUID for this one sale (D61: a per-payment purchase intent, not the member). */
19
19
  appAccountToken: string;
20
20
  /** Opaque site/member scope the acknowledgement must echo. */
21
21
  scopeKey: string;
22
22
  }
23
- /** The current member's association, used to recover purchases without a catalog item. */
23
+ /** The current member's scope, used to recover purchases without a catalog item. It names no
24
+ * token: each payment has its own, and the backend decides whose a transaction is. */
24
25
  export interface MemberContext {
25
- appAccountToken: string;
26
26
  scopeKey: string;
27
27
  }
28
28
  export type ContextResult<T> = {
@@ -8,6 +8,9 @@ export interface PurchaseCoordinatorDependencies {
8
8
  jitter?: (baseDelayMs: number) => number;
9
9
  /** Receives a fresh safe snapshot after every change. */
10
10
  onState?: (state: DeliveryState) => void;
11
+ /** Called inside the purchase job when StoreKit defers for Ask to Buy, after the unfinished
12
+ * queue has been listed and before the job returns. The next queued purchase has not started. */
13
+ onAwaitingApproval?: (productId: string) => void;
11
14
  }
12
15
  export interface PurchaseCoordinator {
13
16
  /** Reconciles unfinished purchases now and again after every later session change. */
@@ -0,0 +1,31 @@
1
+ import type { SessionProvider, SessionSnapshot } from "./delivery-contract.js";
2
+ import type { HostCallExpectation, MemberIdentitySource } from "./wix-payments-contract.js";
3
+ export interface HostSessionView extends SessionSnapshot {
4
+ memberId: string | null;
5
+ siteId: string | null;
6
+ appId: string | null;
7
+ ready: boolean;
8
+ epoch: number;
9
+ }
10
+ /** A session provider that can also name the principal captured for one generation. */
11
+ export interface HostIdentitySource {
12
+ readonly identityBound: boolean;
13
+ identity(session: SessionSnapshot): HostCallExpectation | null;
14
+ }
15
+ export interface HostSessionProvider extends SessionProvider, HostIdentitySource {
16
+ }
17
+ /** Wraps a host session clock as the session provider the delivery coordinator and the wix-iap
18
+ * client share. Ignores a generation older than the last one read, and keeps the first member
19
+ * expectation captured for each generation for `identity()`. */
20
+ export declare function createHostSession(source: {
21
+ identityBound: boolean;
22
+ current(): unknown;
23
+ subscribe(listener: () => void): () => void;
24
+ }): HostSessionProvider;
25
+ /** The session on `globalThis.himalaya`. Web publishes `identityBound: false`. */
26
+ export declare function hostSessionFromGlobal(): HostSessionProvider;
27
+ /** The member a host session names for a captured generation, as the identity port the Apple-IAP
28
+ * checkout and the wix-iap client take: null when that generation has no signed-in member. */
29
+ export declare function memberIdentityOf(source: HostIdentitySource): MemberIdentitySource;
30
+ /** Whether the host fences protected calls to the captured member (`identityBound`). Web does not. */
31
+ export declare function readIdentityBound(): boolean;
@@ -9,6 +9,7 @@ export * from "./catalog-price-fields.js";
9
9
  export * from "./catalog-adapters/online-programs.js";
10
10
  export * from "./wix-payments-contract.js";
11
11
  export * from "./wix-payments.js";
12
+ export * from "./host-session.js";
12
13
  /** The three store product categories. */
13
14
  export type ProductType = "subscription" | "nonConsumable" | "consumable";
14
15
  export interface Product {
@@ -25,11 +25,20 @@ export interface WixIapRoute {
25
25
  * was in the generated gateway metadata on 2026-10-08, so there is deliberately no default. */
26
26
  prefix: string;
27
27
  }
28
+ /** Captured when a protected call starts. The native bridge checks it and never puts it on
29
+ * the HTTP request. */
30
+ export interface HostCallExpectation {
31
+ generation: number;
32
+ kind: "member";
33
+ memberId: string;
34
+ siteId: string;
35
+ appId: string;
36
+ }
28
37
  /** The host's Wix REST bridge (`himalaya.wixApi`). Resolves the parsed body of a 2xx and
29
38
  * rejects with `HTTP <status> [<code>]: <message>` otherwise. Credentials are attached
30
- * natively, never in TypeScript. */
39
+ * natively, never in TypeScript. `expectation` is bridge metadata, not a header. */
31
40
  export interface WixTransport {
32
- call(method: "GET" | "POST", path: string, body?: unknown, headers?: Record<string, string>): Promise<unknown>;
41
+ call(method: "GET" | "POST", path: string, body?: unknown, headers?: Record<string, string>, expectation?: HostCallExpectation): Promise<unknown>;
33
42
  }
34
43
  /** Optional, from a trusted host only: the Wix member id signed in for a captured session. Used to
35
44
  * refuse an answer about someone else, never sent: the server derives the member itself. */
@@ -55,10 +64,9 @@ export interface WixIapPayment {
55
64
  canceledDate?: string;
56
65
  refundedDate?: string;
57
66
  }
58
- export type WixIapOperation = "startPayment" | "completePayment" | "getCustomerId" | "getPayment";
67
+ export type WixIapOperation = "startPayment" | "completePayment" | "getPayment";
59
68
  export type StartPaymentErrorCode = "NOT_PENDING" | "WRONG_PAYMENT_METHOD" | "NOT_ORDER_BUYER" | "UNSUPPORTED_ORDER" | "PRODUCT_NOT_AVAILABLE" | "ALREADY_OWNED";
60
- export type CompletePaymentErrorCode = "INVALID_PURCHASE" | "OWNED_BY_ANOTHER_CUSTOMER" | "PURCHASE_REVOKED" | "NOT_PURCHASED" | "ZERO_PRICE" | "NO_MATCHING_PAYMENT" | "APP_NOT_CONFIGURED";
61
- export type GetCustomerIdErrorCode = "APP_NOT_CONFIGURED";
69
+ export type CompletePaymentErrorCode = "INVALID_PURCHASE" | "OWNED_BY_ANOTHER_CUSTOMER" | "PURCHASE_REVOKED" | "NOT_PURCHASED" | "ZERO_PRICE" | "NO_MATCHING_PAYMENT" | "PAYMENT_NOT_PENDING" | "APP_NOT_CONFIGURED";
62
70
  export type GetPaymentErrorCode = "NOT_FOUND";
63
71
  /** Why a call gave no usable answer, other than a named application error.
64
72
  * `unavailable` and `sessionChanged` say nothing about whether the request took effect.
@@ -80,24 +88,21 @@ export type WixIapFailure<Code extends string> = {
80
88
  kind: WixIapFailureKind;
81
89
  httpStatus?: number;
82
90
  };
83
- /** `customerId` goes to StoreKit as `appAccountToken` (the customer id is the token, D59). Keep it
84
- * out of screen state. */
91
+ /** `appAccountToken` goes to StoreKit with the purchase. It is minted for this one payment (a
92
+ * purchase intent, D61), not the member: StartPayment for the same Wix transaction again returns
93
+ * the same payment and the same token. Keep it out of screen state. */
85
94
  export type StartPaymentResult = {
86
95
  status: "started";
87
96
  payment: WixIapPayment;
88
97
  storeProductId: string;
89
- customerId: string;
98
+ appAccountToken: string;
90
99
  } | WixIapFailure<StartPaymentErrorCode>;
91
- /** `matched`: the server verified the proof and matched it to `payment`, which may not be the one
92
- * this device started. Its status may still be `approving`. */
100
+ /** `matched`: the server verified the proof and paid the payment whose token the Apple transaction
101
+ * carries. Its status may still be `approving`. */
93
102
  export type CompletePaymentResult = {
94
103
  status: "matched";
95
104
  payment: WixIapPayment;
96
105
  } | WixIapFailure<CompletePaymentErrorCode>;
97
- export type CustomerIdResult = {
98
- status: "found";
99
- customerId: string;
100
- } | WixIapFailure<GetCustomerIdErrorCode>;
101
106
  export type GetPaymentResult = {
102
107
  status: "found";
103
108
  payment: WixIapPayment;
@@ -12,7 +12,6 @@ export interface CallScope {
12
12
  export declare function startPaymentCall(scope: CallScope, wixTransactionId: string): WixIapCall;
13
13
  /** The JWS goes byte-for-byte: the server derives the member, and the proof names the product. */
14
14
  export declare function completePaymentCall(scope: CallScope, signedTransaction: string): WixIapCall;
15
- export declare function customerIdCall(scope: CallScope): WixIapCall;
16
15
  export declare function paymentCall(scope: CallScope, paymentId: string): WixIapCall;
17
16
  /** A gateway path such as `/_api/<service>/v1`: absolute, no trailing slash, query or scheme. */
18
17
  export declare function isRoutePrefix(prefix: string): boolean;
@@ -26,13 +25,12 @@ export interface PaymentExpectation {
26
25
  export interface StartedPayment {
27
26
  payment: WixIapPayment;
28
27
  storeProductId: string;
29
- customerId: string;
28
+ appAccountToken: string;
30
29
  }
30
+ /** D61: the token is this payment's purchase intent; no other field may stand in for it. */
31
31
  export declare function decodeStarted(raw: unknown, expected: PaymentExpectation): StartedPayment | null;
32
32
  /** CompletePayment's and GetPayment's answer: `{payment}`. */
33
33
  export declare function decodePaymentAnswer(raw: unknown, expected: PaymentExpectation): WixIapPayment | null;
34
- /** D59: the customer's id is the StoreKit `appAccountToken`; no other field may stand in for it. */
35
- export declare function decodeCustomerId(raw: unknown): string | null;
36
34
  /** Maps a bridge rejection to a failure. The message itself is never kept: the bridge copies up
37
35
  * to 300 characters of the response, which can echo the request. */
38
36
  export declare function classifyFailure<Code extends string>(error: unknown, operation: WixIapOperation, codes: readonly Code[]): WixIapFailure<Code>;
@@ -1,6 +1,6 @@
1
1
  import type { AppleTransaction } from "./index.js";
2
2
  import type { SessionProvider } from "./delivery-contract.js";
3
- import type { AppBindingSource, CompletePaymentResult, CustomerIdResult, GetPaymentResult, IapAppHost, MemberIdentitySource, StartPaymentResult, WixIapRoute, WixTransport } from "./wix-payments-contract.js";
3
+ import type { AppBindingSource, CompletePaymentResult, GetPaymentResult, IapAppHost, MemberIdentitySource, StartPaymentResult, WixIapRoute, WixTransport } from "./wix-payments-contract.js";
4
4
  export interface WixIapClientDependencies {
5
5
  /** The trusted host session; each call is bound to the generation current when it starts. */
6
6
  session: SessionProvider;
@@ -14,15 +14,13 @@ export interface WixIapClientDependencies {
14
14
  }
15
15
  export interface WixIapClient {
16
16
  /** StartPayment for a pending `appleIAP` Wix Payments transaction the member placed. Returns the
17
- * store product to sell and the customer id to pass to StoreKit as `appAccountToken`. */
17
+ * store product to sell and this payment's `appAccountToken` to pass to StoreKit. */
18
18
  startPayment(input: {
19
19
  wixTransactionId: string;
20
20
  }): Promise<StartPaymentResult>;
21
- /** CompletePayment with held Apple proof, sent unchanged. Success can still be `approving`. */
21
+ /** CompletePayment with held Apple proof, sent unchanged: the service pays the payment whose
22
+ * token the transaction carries. Success can still be `approving`. */
22
23
  completePayment(transaction: AppleTransaction): Promise<CompletePaymentResult>;
23
- /** GetCustomerId: the member's customer id, for recovering held purchases. Creates the customer
24
- * when there is none. */
25
- getCustomerId(): Promise<CustomerIdResult>;
26
24
  /** GetPayment: one of the member's own Payments. */
27
25
  getPayment(input: {
28
26
  paymentId: string;
@@ -34,14 +32,15 @@ export interface WixIapClient {
34
32
  *
35
33
  * NOT ENABLED and not production-ready. No app wires it, and no call reaches the service: it has
36
34
  * no public gateway route yet, so `route` must be supplied and there is no default. It calls
37
- * StartPayment (`POST …/payments/start`), CompletePayment (`POST …/payments/complete`),
38
- * GetCustomerId (`GET …/customer-id`) and GetPayment (`GET …/payments/{id}`) through the
35
+ * StartPayment (`POST …/payments/start`), CompletePayment (`POST …/payments/complete`)
36
+ * and GetPayment (`GET …/payments/{id}`) through the
39
37
  * `wix_api` bridge. A matched or approved Payment is not durable access and never finishes the
40
38
  * store transaction.
41
39
  *
42
- * Production use is blocked on pending prerequisites: a public route and member authorization on
43
- * the service, the service's own app identity and permissions, a trusted provisioning flow for the
44
- * app binding, and a native bridge that binds each request to the session generation across
45
- * authorization, send and retry. Its checks here protect only this client's own flow.
40
+ * Production use stays blocked: there is no public route or member authorization on the service,
41
+ * no trusted app-binding source, and checkout stays disabled. When this client uses the host
42
+ * bridge, it also requires the host's identity clock and passes that captured expectation
43
+ * through the bridge. An injected transport keeps the previous call shape unless the session
44
+ * itself exposes an identity.
46
45
  */
47
46
  export declare function createWixIapClient(deps: WixIapClientDependencies): WixIapClient;
@@ -1,8 +1,10 @@
1
- import type { AppBindingSource, CatalogReference, Clock, DeliveryState, IapCatalogPricing, SessionProvider, TransactionStore, WixIapClient } from "@wix/himalaya/iap";
1
+ import type { AppBindingSource, CatalogReference, Clock, DeliveryState, HostCallExpectation, IapCatalogPricing, MemberIdentitySource, SessionProvider, TransactionStore, WixIapClient } from "@wix/himalaya/iap";
2
2
  /** The host's Wix REST bridge (`himalaya.wixApi`). Resolves a 2xx body; rejects with
3
- * `HTTP <status> [<code>]: <message>` otherwise. Credentials are attached natively. */
3
+ * `HTTP <status> [<code>]: <message>` otherwise. Credentials are attached natively.
4
+ * Same positional shape as the runtime's `wixApiCall`: `expectation` is bridge metadata for a
5
+ * protected call, after `headers`, and never an HTTP header. */
4
6
  export interface WixBridge {
5
- call(method: "GET" | "POST", path: string, body?: unknown): Promise<unknown>;
7
+ call(method: "GET" | "POST", path: string, body?: unknown, headers?: Record<string, string>, expectation?: HostCallExpectation): Promise<unknown>;
6
8
  }
7
9
  /** Why a bridge call gave no body. `sessionChanged`: the captured session is no longer current,
8
10
  * before the send or after the answer; nothing from it may be used or stored. */
@@ -86,13 +88,13 @@ export interface IapOrderAdapter {
86
88
  /** The vertical's authoritative answer for the order's item and the signed-in member. */
87
89
  readAccess(verticalRef: VerticalRef, bridge: SessionBoundBridge): Promise<AccessRead>;
88
90
  }
89
- /** Durable, member-partitioned purchase references. Ids only: never a proof, an account token
90
- * (the customer id is stored only as a one-way hash in the key), or a credential. */
91
+ /** Durable, member-partitioned purchase references. Ids only: never a proof or a credential, and
92
+ * the member id is stored only as a one-way hash in the key. */
91
93
  export interface OrderPartitionKey {
92
94
  purchasesAppId: string;
93
95
  siteId: string;
94
- /** The member's wix-iap customer id: server-derived per member per app. */
95
- customerId: string;
96
+ /** The signed-in member's Wix id, from the host session (wix-iap records purchases against it). */
97
+ memberId: string;
96
98
  }
97
99
  /** `held`: Apple charged, and CompletePayment refused the proof without recording it, so the
98
100
  * transaction stays unfinished and is retried. `needsSupport`: recorded and refused for good. */
@@ -109,6 +111,8 @@ export interface OrderRef {
109
111
  storeProductId?: string;
110
112
  appProductId?: string;
111
113
  appleTransactionId?: string;
114
+ /** The StoreKit token StartPayment minted for this payment (D61): recovery finds the order by it. */
115
+ appAccountToken?: string;
112
116
  updatedAt: number;
113
117
  }
114
118
  export interface OrderRefPartition {
@@ -122,13 +126,13 @@ export interface OrderRefStore {
122
126
  * unknown-version data. Never an empty stand-in. */
123
127
  open(key: OrderPartitionKey): OrderRefPartition | null;
124
128
  /** Whether any member holds references for this app and site; null when unreadable. Lets a
125
- * start-up skip GetCustomerId (which creates a customer) when nothing was ever handed over. */
129
+ * start-up skip reading the member and tracking when nothing was ever handed over. */
126
130
  hasRefs(app: {
127
131
  purchasesAppId: string;
128
132
  siteId: string;
129
133
  }): boolean | null;
130
134
  }
131
- export type OrderFailureCode = "notEnabled" | "notConfigured" | "signInRequired" | "unsupportedItem" | "notAppleRoute" | "storageUnavailable" | "approvalRequired" | "orderClosed" | "orderRefused" | "chargeFailed" | "paymentRefused" | "paymentHeld" | "alreadyOwned" | "paymentInProgress" | "productChanged" | "matchedOtherOrder" | "invalidAssociation" | "needsSupport" | "unavailable" | "sessionChanged";
135
+ export type OrderFailureCode = "notEnabled" | "notConfigured" | "signInRequired" | "unsupportedItem" | "notAppleRoute" | "storageUnavailable" | "approvalRequired" | "orderClosed" | "orderRefused" | "chargeFailed" | "paymentRefused" | "paymentHeld" | "alreadyOwned" | "paymentInProgress" | "productChanged" | "invalidAssociation" | "needsSupport" | "unavailable" | "sessionChanged";
132
136
  /** Progress of a payment this device handed to wix-iap, tracked from its durable reference. */
133
137
  export type PaymentAccess = "processing" | "granted" | "accessUnknown" | "needsSupport";
134
138
  export interface PaymentProgress {
@@ -151,6 +155,10 @@ export interface AppleIapCheckoutState {
151
155
  }
152
156
  export interface AppleIapCheckoutDependencies {
153
157
  wixIap: WixIapClient;
158
+ /** The member signed in for a captured session, from the trusted host (`memberIdentityOf` over the
159
+ * host session). It partitions the references and scopes acknowledgements: wix-iap has no
160
+ * customer ids any more (D61). */
161
+ identity: MemberIdentitySource;
154
162
  /** The same trusted binding the wix-iap client uses; it partitions the stored references. */
155
163
  binding: AppBindingSource;
156
164
  /** The same host provider the wix-iap client was given: every step compares generations. */
@@ -1,4 +1,4 @@
1
- import type { AppBindingSource, Clock, DeliveryBackend, IapAppleProduct, SessionProvider, WixIapClient } from "@wix/himalaya/iap";
1
+ import type { AppBindingSource, Clock, DeliveryBackend, IapAppleProduct, MemberIdentitySource, SessionProvider, WixIapClient } from "@wix/himalaya/iap";
2
2
  import type { CashierRoute, IapOrderAdapter, IapOrderItem, OrderFailureCode, OrderRefStore, PaymentAccess, WixBridge } from "./apple-iap-contract.js";
3
3
  /** What the backend tells the checkout about an item: why it stopped, or how its payment is. */
4
4
  export interface OrderEvent {
@@ -15,6 +15,8 @@ export interface SaleItem {
15
15
  }
16
16
  export interface WixOrderBackendDependencies {
17
17
  wixIap: WixIapClient;
18
+ /** The member signed in for a captured session; it partitions references and scopes acks. */
19
+ identity: MemberIdentitySource;
18
20
  binding: AppBindingSource;
19
21
  session: SessionProvider;
20
22
  clock: Clock;
@@ -24,6 +26,9 @@ export interface WixOrderBackendDependencies {
24
26
  bridge: WixBridge;
25
27
  /** The item a `buy` asked for, by the catalog ref the coordinator carries. */
26
28
  itemFor(catalogRef: string): SaleItem | undefined;
29
+ /** Whether Apple may already be charging for this product: an unfinished transaction, or an Ask
30
+ * to Buy request awaiting approval. Asked inside the purchase job, after any reconcile. */
31
+ productBusy?(productId: string): boolean;
27
32
  report(event: OrderEvent): void;
28
33
  }
29
34
  export declare function createWixOrderBackend(deps: WixOrderBackendDependencies): DeliveryBackend;