@mpgd/game-services 0.29.0 → 0.30.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/dist/commerce-reconciler.js +42 -7
- package/package.json +4 -4
|
@@ -461,22 +461,49 @@ export function createCommerceReconciler(input) {
|
|
|
461
461
|
trigger();
|
|
462
462
|
scheduleRun();
|
|
463
463
|
};
|
|
464
|
-
|
|
464
|
+
/**
|
|
465
|
+
* Reads the store's available purchases into the inbox. `restore` is the
|
|
466
|
+
* player's Restore Purchases read only: the store also lists owned
|
|
467
|
+
* non-consumables its recovery list hides (acknowledged on Play, bound to
|
|
468
|
+
* another guest's token on StoreKit), so a reinstall or a new device can
|
|
469
|
+
* restore them. Startup and resume recovery never set it, so an
|
|
470
|
+
* acknowledged durable is not sent again on every launch.
|
|
471
|
+
*/
|
|
472
|
+
const readAvailable = async (capabilitiesNow, restore = false) => {
|
|
465
473
|
if (!capabilitiesNow.lifecycle.availablePurchases) {
|
|
466
474
|
return true;
|
|
467
475
|
}
|
|
468
|
-
|
|
476
|
+
const read = async (withRestore) => {
|
|
469
477
|
const available = await provider.getAvailablePurchases({
|
|
470
478
|
includePending: capabilitiesNow.lifecycle.pending,
|
|
479
|
+
...(withRestore ? { restore: true } : {}),
|
|
471
480
|
});
|
|
472
481
|
for (const purchase of available) {
|
|
473
482
|
inbox.push({ type: 'purchaseUpdated', purchase });
|
|
474
483
|
}
|
|
484
|
+
};
|
|
485
|
+
try {
|
|
486
|
+
await read(restore);
|
|
475
487
|
return true;
|
|
476
488
|
}
|
|
477
489
|
catch (error) {
|
|
490
|
+
if (!restore) {
|
|
491
|
+
fail('available', error);
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
// A failed restore read still makes the recovery read, so Restore
|
|
495
|
+
// Purchases never finds less than a recovery pass: a bridge host built
|
|
496
|
+
// before `restore` rejects the field, and a store may fail only the
|
|
497
|
+
// wider read. The restore failure is still reported.
|
|
478
498
|
fail('available', error);
|
|
479
|
-
|
|
499
|
+
try {
|
|
500
|
+
await read(false);
|
|
501
|
+
return true;
|
|
502
|
+
}
|
|
503
|
+
catch (fallbackError) {
|
|
504
|
+
fail('available', fallbackError);
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
480
507
|
}
|
|
481
508
|
};
|
|
482
509
|
const buildRequest = (record) => {
|
|
@@ -852,7 +879,8 @@ export function createCommerceReconciler(input) {
|
|
|
852
879
|
// read again until it succeeds, so a purchase that predates the
|
|
853
880
|
// subscription is not missed for the session.
|
|
854
881
|
if (capabilitiesNow !== undefined && (!capabilitiesNow.lifecycle.events || initialScanPending)) {
|
|
855
|
-
initialScanPending = !(await readAvailable(capabilitiesNow))
|
|
882
|
+
initialScanPending = !(await readAvailable(capabilitiesNow, options.restore === true))
|
|
883
|
+
&& capabilitiesNow.lifecycle.events;
|
|
856
884
|
}
|
|
857
885
|
// An event for a product whose store call is still running waits for that
|
|
858
886
|
// call to journal the store answer: matched then, it is never journaled
|
|
@@ -1297,11 +1325,18 @@ export function createCommerceReconciler(input) {
|
|
|
1297
1325
|
await loadRecords();
|
|
1298
1326
|
}
|
|
1299
1327
|
const capabilitiesNow = await readCapabilities(true);
|
|
1300
|
-
// A polled provider is read by the pass itself.
|
|
1328
|
+
// A polled provider is read by the pass itself. Either read is a
|
|
1329
|
+
// restore read: owned non-consumables the store's recovery list
|
|
1330
|
+
// hides (a reinstall, a new device) reach the backend as restores.
|
|
1331
|
+
let restoreRead = false;
|
|
1301
1332
|
if (capabilitiesNow !== undefined && capabilitiesNow.lifecycle.events) {
|
|
1302
|
-
await readAvailable(capabilitiesNow);
|
|
1333
|
+
restoreRead = await readAvailable(capabilitiesNow, true);
|
|
1334
|
+
if (restoreRead) {
|
|
1335
|
+
// This read covers a start-time read that failed.
|
|
1336
|
+
initialScanPending = false;
|
|
1337
|
+
}
|
|
1303
1338
|
}
|
|
1304
|
-
await pass({ explicit: true, refreshCapabilities: false });
|
|
1339
|
+
await pass({ explicit: true, refreshCapabilities: false, restore: !restoreRead });
|
|
1305
1340
|
});
|
|
1306
1341
|
await runUntilIdle();
|
|
1307
1342
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/game-services",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.2",
|
|
4
4
|
"description": "Client, contract, server, store, and test helpers for authoritative mpgd game services.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -231,9 +231,9 @@
|
|
|
231
231
|
"@orpc/client": "2.0.0-beta.14",
|
|
232
232
|
"@orpc/contract": "2.0.0-beta.14",
|
|
233
233
|
"@orpc/server": "2.0.0-beta.14",
|
|
234
|
-
"@mpgd/analytics": "0.5.
|
|
235
|
-
"@mpgd/platform": "0.
|
|
236
|
-
"@mpgd/catalog": "0.11.
|
|
234
|
+
"@mpgd/analytics": "0.5.5",
|
|
235
|
+
"@mpgd/platform": "0.32.0",
|
|
236
|
+
"@mpgd/catalog": "0.11.3"
|
|
237
237
|
},
|
|
238
238
|
"peerDependencies": {
|
|
239
239
|
"@apple/app-store-server-library": "^3.1.0"
|