@wix/himalaya-cli 0.1388.0 → 0.1389.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-contract.d.ts +24 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-core.d.ts +3 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/index.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +57 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +57 -0
- package/dist/cli.mjs +7 -5
- package/guides/iap-screen-adoption.md +53 -1
- package/guides/sdk-reference.json +8 -2
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +193 -1
- package/templates/beauty-salon/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/beauty-salon/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/beauty-salon-owner/config.ts +11 -0
- package/templates/beauty-salon-owner/dev/index.ts +540 -0
- package/templates/beauty-salon-owner/himalaya.content.json +6 -0
- package/templates/beauty-salon-owner/platforms.json +2 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/branded-lite/dev/index.ts +194 -2
- package/templates/branded-lite/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/branded-lite/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/community-club/dev/index.ts +193 -1
- package/templates/community-club/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/community-club/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/community-club-owner/config.ts +11 -0
- package/templates/community-club-owner/dev/index.ts +540 -0
- package/templates/community-club-owner/himalaya.content.json +6 -0
- package/templates/community-club-owner/platforms.json +2 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/events-meetups/dev/index.ts +193 -1
- package/templates/events-meetups/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/events-meetups/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/events-meetups-owner/config.ts +11 -0
- package/templates/events-meetups-owner/dev/index.ts +540 -0
- package/templates/events-meetups-owner/himalaya.content.json +6 -0
- package/templates/events-meetups-owner/platforms.json +2 -1
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/gym-fitness/dev/index.ts +193 -1
- package/templates/gym-fitness/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/gym-fitness/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/gym-fitness-owner/config.ts +11 -0
- package/templates/gym-fitness-owner/dev/index.ts +540 -0
- package/templates/gym-fitness-owner/himalaya.content.json +6 -0
- package/templates/gym-fitness-owner/platforms.json +2 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/nonprofit-cause/dev/index.ts +193 -1
- package/templates/nonprofit-cause/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/nonprofit-cause/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/nonprofit-cause-owner/config.ts +11 -0
- package/templates/nonprofit-cause-owner/dev/index.ts +540 -0
- package/templates/nonprofit-cause-owner/himalaya.content.json +6 -0
- package/templates/nonprofit-cause-owner/platforms.json +2 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/owner-lite/config.ts +11 -0
- package/templates/owner-lite/dev/index.ts +540 -0
- package/templates/owner-lite/himalaya.content.json +6 -0
- package/templates/owner-lite/platforms.json +2 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/podcast-creator/dev/index.ts +193 -1
- package/templates/podcast-creator/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/podcast-creator/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/podcast-creator-owner/config.ts +11 -0
- package/templates/podcast-creator-owner/dev/index.ts +540 -0
- package/templates/podcast-creator-owner/himalaya.content.json +6 -0
- package/templates/podcast-creator-owner/platforms.json +2 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/portfolio-creative/dev/index.ts +193 -1
- package/templates/portfolio-creative/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/portfolio-creative/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/portfolio-creative-owner/config.ts +11 -0
- package/templates/portfolio-creative-owner/dev/index.ts +540 -0
- package/templates/portfolio-creative-owner/himalaya.content.json +6 -0
- package/templates/portfolio-creative-owner/platforms.json +2 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/restaurant/dev/index.ts +193 -1
- package/templates/restaurant/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/restaurant/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/restaurant-owner/config.ts +11 -0
- package/templates/restaurant-owner/dev/index.ts +540 -0
- package/templates/restaurant-owner/himalaya.content.json +6 -0
- package/templates/restaurant-owner/platforms.json +2 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/retail-store/dev/index.ts +193 -1
- package/templates/retail-store/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/retail-store/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/retail-store-owner/config.ts +11 -0
- package/templates/retail-store-owner/dev/index.ts +540 -0
- package/templates/retail-store-owner/himalaya.content.json +6 -0
- package/templates/retail-store-owner/platforms.json +2 -1
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
- package/templates/yoga-studio/dev/index.ts +193 -1
- package/templates/yoga-studio/tier5-src/_shared/iap-worker.ts +84 -3
- package/templates/yoga-studio/tier5-src/himi-store-account/index.ts +36 -1
- package/templates/yoga-studio-owner/config.ts +11 -0
- package/templates/yoga-studio-owner/dev/index.ts +540 -0
- package/templates/yoga-studio-owner/himalaya.content.json +6 -0
- package/templates/yoga-studio-owner/platforms.json +2 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-wrist/index.ts +350 -0
|
@@ -50,6 +50,10 @@ export interface IapCommerce {
|
|
|
50
50
|
buy(item: IapOrderItem): Promise<AppleIapCheckoutState>;
|
|
51
51
|
/** On resume: re-reads Apple's unfinished queue and the payments being tracked. */
|
|
52
52
|
reconcile(): Promise<AppleIapCheckoutState>;
|
|
53
|
+
/** Restore purchases (App Review 3.1.1): syncs Apple's purchase history to the device, then makes a
|
|
54
|
+
* new attempt at every unfinished purchase (a scheduled retry is not waited out) and re-reads the
|
|
55
|
+
* member's access. Needs a signed-in member; taps while one runs share it. */
|
|
56
|
+
restore(): Promise<IapRestoreResult>;
|
|
53
57
|
tick(): Promise<AppleIapCheckoutState>;
|
|
54
58
|
/** The screen's one `_poll` for prices and purchase, or undefined when the cadence it already
|
|
55
59
|
* armed still holds (or there is nothing to poll). Emit it from every publish. */
|
|
@@ -59,6 +63,26 @@ export interface IapCommerce {
|
|
|
59
63
|
poll(): Promise<void>;
|
|
60
64
|
dispose(): void;
|
|
61
65
|
}
|
|
66
|
+
/** What a restore found. Counts only: never a product, transaction or member id.
|
|
67
|
+
* - `needsSignIn`: no member is signed in; Apple was not asked.
|
|
68
|
+
* - `restored`: `recovered` purchases were taken by Wix during this restore; `refused` stay held,
|
|
69
|
+
* unfinished, because Wix refused them (another member's purchase, say), plus any Wix refused for good
|
|
70
|
+
* during this restore (finished; the member needs support); `pending` are charged but
|
|
71
|
+
* not yet taken (Wix could not be reached, or asked to retry), and stay held for the next attempt.
|
|
72
|
+
* - `failed`: `storeUnavailable` when the App Store sync or Apple's queue could not be read,
|
|
73
|
+
* `unavailable` when this host does not sell through the App Store, `sessionChanged` when the
|
|
74
|
+
* member changed. */
|
|
75
|
+
export type IapRestoreResult = {
|
|
76
|
+
status: "needsSignIn";
|
|
77
|
+
} | {
|
|
78
|
+
status: "restored";
|
|
79
|
+
recovered: number;
|
|
80
|
+
refused: number;
|
|
81
|
+
pending: number;
|
|
82
|
+
} | {
|
|
83
|
+
status: "failed";
|
|
84
|
+
code: "storeUnavailable" | "unavailable" | "sessionChanged";
|
|
85
|
+
};
|
|
62
86
|
/** Labels from the screen's copy pack; the shared layer only chooses between them. */
|
|
63
87
|
export interface IapPurchaseCopy {
|
|
64
88
|
buy: string;
|
|
@@ -24,6 +24,9 @@ export interface IapCommerceDependencies {
|
|
|
24
24
|
identity: MemberIdentitySource;
|
|
25
25
|
host: CommerceHost;
|
|
26
26
|
store: TransactionStore;
|
|
27
|
+
/** StoreKit's `AppStore.sync()`: brings Apple's purchase history to the device and may ask the
|
|
28
|
+
* person to sign in to their Apple Account. Rejects when the App Store cannot be reached. */
|
|
29
|
+
syncAppStore(): Promise<void>;
|
|
27
30
|
refs: OrderRefStore;
|
|
28
31
|
clock: Clock;
|
|
29
32
|
adapters: readonly IapOrderAdapter[];
|
|
@@ -5,4 +5,4 @@ export { onlineProgramOrders, pricingPlanOrders, storesProductOrders, classifyCa
|
|
|
5
5
|
export { createWorkerOrderRefStore } from "./order-refs.js";
|
|
6
6
|
export { itemPaymentEnabled, storesAppleSalesEnabled } from "./checkout-source.js";
|
|
7
7
|
export type { AccessRead, AppleIapCheckout, AppleIapCheckoutDependencies, AppleIapCheckoutPhase, AppleIapCheckoutState, BridgeOutcome, BridgeRefusal, CashierRoute, IapEligibility, IapOrderAdapter, IapOrderItem, OrderAttempt, OrderFailureCode, OrderPartitionKey, OrderRef, OrderRefPartition, OrderRefStage, OrderRefStore, PaymentAccess, PaymentProgress, SessionBoundBridge, VerticalRef, WixBridge, } from "./apple-iap-contract.js";
|
|
8
|
-
export type { AppleIapCheckoutRoutes, IapCommerce, IapCommerceOptions, IapPurchaseCopy, IapPurchaseFields, IapPurchaseGap, IapPurchaseReadiness, } from "./commerce-contract.js";
|
|
8
|
+
export type { AppleIapCheckoutRoutes, IapCommerce, IapCommerceOptions, IapPurchaseCopy, IapPurchaseFields, IapPurchaseGap, IapPurchaseReadiness, IapRestoreResult, } from "./commerce-contract.js";
|
|
@@ -1345,6 +1345,10 @@ async function getProducts(productIds) {
|
|
|
1345
1345
|
});
|
|
1346
1346
|
return Array.isArray(r?.products) ? r.products : [];
|
|
1347
1347
|
}
|
|
1348
|
+
async function restore() {
|
|
1349
|
+
const r = await dispatch("capability.iap.restore");
|
|
1350
|
+
return Array.isArray(r?.entitlements) ? r.entitlements : [];
|
|
1351
|
+
}
|
|
1348
1352
|
async function purchaseForVerification(input) {
|
|
1349
1353
|
if (!nonempty2(input?.productId) || !isUUID2(input?.appAccountToken)) return failure2("invalidArgument");
|
|
1350
1354
|
const result = await managedDispatch(() => dispatch("capability.iap.purchaseForVerification", input));
|
|
@@ -2526,6 +2530,7 @@ function createIapCommerceWith(deps) {
|
|
|
2526
2530
|
let stopWatchingAccess;
|
|
2527
2531
|
let checkoutStarted = false;
|
|
2528
2532
|
let recheckAfterOpening = false;
|
|
2533
|
+
let restoring;
|
|
2529
2534
|
async function loadPrices(items) {
|
|
2530
2535
|
if (!deps.pricing.enabled) return { scopeComplete: true };
|
|
2531
2536
|
lastPricedAt = deps.clock.now();
|
|
@@ -2557,6 +2562,38 @@ function createIapCommerceWith(deps) {
|
|
|
2557
2562
|
function start() {
|
|
2558
2563
|
return recover((opened) => opened.start());
|
|
2559
2564
|
}
|
|
2565
|
+
function restore2() {
|
|
2566
|
+
return restoring ?? (restoring = restoreOnce().finally(() => {
|
|
2567
|
+
restoring = void 0;
|
|
2568
|
+
}));
|
|
2569
|
+
}
|
|
2570
|
+
async function restoreOnce() {
|
|
2571
|
+
const session = deps.session.current();
|
|
2572
|
+
if (session.kind !== "member") return { status: "needsSignIn" };
|
|
2573
|
+
const before = state().purchase.items;
|
|
2574
|
+
const opened = await startedCheckout();
|
|
2575
|
+
if (deps.session.current().generation !== session.generation) return { status: "failed", code: "sessionChanged" };
|
|
2576
|
+
if (!opened) return { status: "failed", code: "unavailable" };
|
|
2577
|
+
if (!await syncedAppStore()) return { status: "failed", code: "storeUnavailable" };
|
|
2578
|
+
if (deps.session.current().generation !== session.generation) return { status: "failed", code: "sessionChanged" };
|
|
2579
|
+
const purchase = (await recover((opened2) => opened2.retry())).purchase;
|
|
2580
|
+
if (deps.session.current().generation !== session.generation) return { status: "failed", code: "sessionChanged" };
|
|
2581
|
+
const after = purchase.items;
|
|
2582
|
+
const newly = (matches) => Math.max(0, countOf(after, matches) - countOf(before, matches));
|
|
2583
|
+
const result = {
|
|
2584
|
+
status: "restored",
|
|
2585
|
+
recovered: newly(isRecovered),
|
|
2586
|
+
// Held refusals stay in the queue; a final refusal is finished, so only this restore's count.
|
|
2587
|
+
refused: countOf(after, isHeldRefusal) + newly(isFinalRefusal2),
|
|
2588
|
+
pending: countOf(after, isStillPending)
|
|
2589
|
+
};
|
|
2590
|
+
const settled = result.recovered + newly(isFinalRefusal2) > 0;
|
|
2591
|
+
if (purchase.unfinishedCount === null && !settled) return { status: "failed", code: "storeUnavailable" };
|
|
2592
|
+
return result;
|
|
2593
|
+
}
|
|
2594
|
+
function syncedAppStore() {
|
|
2595
|
+
return deps.syncAppStore().then(() => true, () => false);
|
|
2596
|
+
}
|
|
2560
2597
|
async function buy(item) {
|
|
2561
2598
|
if (unanswered2(deps.pricing.view(item.reference))) return state();
|
|
2562
2599
|
const started = await startedCheckout();
|
|
@@ -2687,6 +2724,7 @@ function createIapCommerceWith(deps) {
|
|
|
2687
2724
|
start,
|
|
2688
2725
|
buy,
|
|
2689
2726
|
reconcile: reconcile2,
|
|
2727
|
+
restore: restore2,
|
|
2690
2728
|
tick: () => checkout ? checkout.tick() : Promise.resolve(state()),
|
|
2691
2729
|
pollDirective,
|
|
2692
2730
|
poll,
|
|
@@ -2707,6 +2745,22 @@ var SUSPENDED_AFTER_MS = 2 * PRICE_REFRESH_MS;
|
|
|
2707
2745
|
function unanswered2(view) {
|
|
2708
2746
|
return view.route === "resolving" || view.reason === "mappingUnavailable";
|
|
2709
2747
|
}
|
|
2748
|
+
function isRecovered(item) {
|
|
2749
|
+
return item.completion === "finished" && item.access !== "rejected";
|
|
2750
|
+
}
|
|
2751
|
+
function isFinalRefusal2(item) {
|
|
2752
|
+
return item.completion === "finished" && item.access === "rejected";
|
|
2753
|
+
}
|
|
2754
|
+
function isHeldRefusal(item) {
|
|
2755
|
+
const unfinished = item.completion === "pending" || item.completion === "retryRequired";
|
|
2756
|
+
return unfinished && (item.access === "ownershipConflict" || item.access === "rejected");
|
|
2757
|
+
}
|
|
2758
|
+
function isStillPending(item) {
|
|
2759
|
+
return item.completion !== "finished" && item.completion !== "notFound" && !isHeldRefusal(item);
|
|
2760
|
+
}
|
|
2761
|
+
function countOf(items, matches) {
|
|
2762
|
+
return items.filter(matches).length;
|
|
2763
|
+
}
|
|
2710
2764
|
function hostFor(identity, binding) {
|
|
2711
2765
|
if (binding.himalayaAppId !== identity.appId || binding.bundleId !== identity.bundleId) return null;
|
|
2712
2766
|
return { appId: identity.appId, bundleId: identity.bundleId, siteId: binding.siteId };
|
|
@@ -2725,6 +2779,9 @@ function createIapCommerce(options = {}) {
|
|
|
2725
2779
|
session,
|
|
2726
2780
|
host: hostOfWorker(),
|
|
2727
2781
|
store: appleManagedStore,
|
|
2782
|
+
syncAppStore: async () => {
|
|
2783
|
+
await restore();
|
|
2784
|
+
},
|
|
2728
2785
|
refs: createWorkerOrderRefStore(),
|
|
2729
2786
|
clock: { now: () => Date.now() },
|
|
2730
2787
|
adapters: options.adapters ?? [],
|
|
@@ -1622,6 +1622,10 @@ async function getProducts(productIds) {
|
|
|
1622
1622
|
});
|
|
1623
1623
|
return Array.isArray(r?.products) ? r.products : [];
|
|
1624
1624
|
}
|
|
1625
|
+
async function restore() {
|
|
1626
|
+
const r = await dispatch2("capability.iap.restore");
|
|
1627
|
+
return Array.isArray(r?.entitlements) ? r.entitlements : [];
|
|
1628
|
+
}
|
|
1625
1629
|
async function purchaseForVerification(input) {
|
|
1626
1630
|
if (!nonempty2(input?.productId) || !isUUID2(input?.appAccountToken)) return failure2("invalidArgument");
|
|
1627
1631
|
const result = await managedDispatch(() => dispatch2("capability.iap.purchaseForVerification", input));
|
|
@@ -2797,6 +2801,7 @@ function createIapCommerceWith(deps) {
|
|
|
2797
2801
|
let stopWatchingAccess;
|
|
2798
2802
|
let checkoutStarted = false;
|
|
2799
2803
|
let recheckAfterOpening = false;
|
|
2804
|
+
let restoring;
|
|
2800
2805
|
async function loadPrices(items) {
|
|
2801
2806
|
if (!deps.pricing.enabled) return { scopeComplete: true };
|
|
2802
2807
|
lastPricedAt = deps.clock.now();
|
|
@@ -2828,6 +2833,38 @@ function createIapCommerceWith(deps) {
|
|
|
2828
2833
|
function start() {
|
|
2829
2834
|
return recover((opened) => opened.start());
|
|
2830
2835
|
}
|
|
2836
|
+
function restore2() {
|
|
2837
|
+
return restoring ?? (restoring = restoreOnce().finally(() => {
|
|
2838
|
+
restoring = void 0;
|
|
2839
|
+
}));
|
|
2840
|
+
}
|
|
2841
|
+
async function restoreOnce() {
|
|
2842
|
+
const session = deps.session.current();
|
|
2843
|
+
if (session.kind !== "member") return { status: "needsSignIn" };
|
|
2844
|
+
const before = state().purchase.items;
|
|
2845
|
+
const opened = await startedCheckout();
|
|
2846
|
+
if (deps.session.current().generation !== session.generation) return { status: "failed", code: "sessionChanged" };
|
|
2847
|
+
if (!opened) return { status: "failed", code: "unavailable" };
|
|
2848
|
+
if (!await syncedAppStore()) return { status: "failed", code: "storeUnavailable" };
|
|
2849
|
+
if (deps.session.current().generation !== session.generation) return { status: "failed", code: "sessionChanged" };
|
|
2850
|
+
const purchase = (await recover((opened2) => opened2.retry())).purchase;
|
|
2851
|
+
if (deps.session.current().generation !== session.generation) return { status: "failed", code: "sessionChanged" };
|
|
2852
|
+
const after = purchase.items;
|
|
2853
|
+
const newly = (matches) => Math.max(0, countOf(after, matches) - countOf(before, matches));
|
|
2854
|
+
const result = {
|
|
2855
|
+
status: "restored",
|
|
2856
|
+
recovered: newly(isRecovered),
|
|
2857
|
+
// Held refusals stay in the queue; a final refusal is finished, so only this restore's count.
|
|
2858
|
+
refused: countOf(after, isHeldRefusal) + newly(isFinalRefusal2),
|
|
2859
|
+
pending: countOf(after, isStillPending)
|
|
2860
|
+
};
|
|
2861
|
+
const settled = result.recovered + newly(isFinalRefusal2) > 0;
|
|
2862
|
+
if (purchase.unfinishedCount === null && !settled) return { status: "failed", code: "storeUnavailable" };
|
|
2863
|
+
return result;
|
|
2864
|
+
}
|
|
2865
|
+
function syncedAppStore() {
|
|
2866
|
+
return deps.syncAppStore().then(() => true, () => false);
|
|
2867
|
+
}
|
|
2831
2868
|
async function buy(item) {
|
|
2832
2869
|
if (unanswered2(deps.pricing.view(item.reference))) return state();
|
|
2833
2870
|
const started = await startedCheckout();
|
|
@@ -2958,6 +2995,7 @@ function createIapCommerceWith(deps) {
|
|
|
2958
2995
|
start,
|
|
2959
2996
|
buy,
|
|
2960
2997
|
reconcile: reconcile2,
|
|
2998
|
+
restore: restore2,
|
|
2961
2999
|
tick: () => checkout ? checkout.tick() : Promise.resolve(state()),
|
|
2962
3000
|
pollDirective,
|
|
2963
3001
|
poll,
|
|
@@ -2978,6 +3016,22 @@ var SUSPENDED_AFTER_MS = 2 * PRICE_REFRESH_MS;
|
|
|
2978
3016
|
function unanswered2(view) {
|
|
2979
3017
|
return view.route === "resolving" || view.reason === "mappingUnavailable";
|
|
2980
3018
|
}
|
|
3019
|
+
function isRecovered(item) {
|
|
3020
|
+
return item.completion === "finished" && item.access !== "rejected";
|
|
3021
|
+
}
|
|
3022
|
+
function isFinalRefusal2(item) {
|
|
3023
|
+
return item.completion === "finished" && item.access === "rejected";
|
|
3024
|
+
}
|
|
3025
|
+
function isHeldRefusal(item) {
|
|
3026
|
+
const unfinished = item.completion === "pending" || item.completion === "retryRequired";
|
|
3027
|
+
return unfinished && (item.access === "ownershipConflict" || item.access === "rejected");
|
|
3028
|
+
}
|
|
3029
|
+
function isStillPending(item) {
|
|
3030
|
+
return item.completion !== "finished" && item.completion !== "notFound" && !isHeldRefusal(item);
|
|
3031
|
+
}
|
|
3032
|
+
function countOf(items, matches) {
|
|
3033
|
+
return items.filter(matches).length;
|
|
3034
|
+
}
|
|
2981
3035
|
function hostFor(identity, binding) {
|
|
2982
3036
|
if (binding.himalayaAppId !== identity.appId || binding.bundleId !== identity.bundleId) return null;
|
|
2983
3037
|
return { appId: identity.appId, bundleId: identity.bundleId, siteId: binding.siteId };
|
|
@@ -2996,6 +3050,9 @@ function createIapCommerce(options = {}) {
|
|
|
2996
3050
|
session,
|
|
2997
3051
|
host: hostOfWorker(),
|
|
2998
3052
|
store: appleManagedStore,
|
|
3053
|
+
syncAppStore: async () => {
|
|
3054
|
+
await restore();
|
|
3055
|
+
},
|
|
2999
3056
|
refs: createWorkerOrderRefStore(),
|
|
3000
3057
|
clock: { now: () => Date.now() },
|
|
3001
3058
|
adapters: options.adapters ?? [],
|