@mpgd/platform 0.12.1 → 0.12.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/capability-conformance.d.ts +6 -0
- package/dist/capability-conformance.js +18 -5
- package/dist/index.d.ts +22 -0
- package/dist/index.js +35 -0
- package/package.json +1 -1
|
@@ -26,5 +26,11 @@ export interface PlatformGatewayCapabilityConformanceReport {
|
|
|
26
26
|
* Runs provider-neutral capability checks against real adapter gateways or
|
|
27
27
|
* target-configured wrappers. Every read must return a complete boolean
|
|
28
28
|
* snapshot, a fresh object, and the provider's latest state.
|
|
29
|
+
* @evidence docs/specs/platform-capability-snapshots.md#snapshot-shape Checks each gateway read against the required boolean keys and expected provider state.
|
|
30
|
+
* @evidenceReview docs/specs/platform-capability-snapshots.md#snapshot-shape #f83948b Reviewed the required keys, optional banner default, and fresh reread in runFixture.
|
|
31
|
+
* @evidence docs/specs/platform-capability-snapshots.md#provider-transitions Checks a fresh provider read after the optional transition update.
|
|
32
|
+
* @evidenceReview docs/specs/platform-capability-snapshots.md#provider-transitions #839c0c8 Reviewed the changed-state guard and post-update snapshot assertion.
|
|
33
|
+
* @evidence docs/specs/platform-capability-snapshots.md#fixture-validation Rejects invalid fixture sets and returns the names of passing fixtures.
|
|
34
|
+
* @evidenceReview docs/specs/platform-capability-snapshots.md#fixture-validation #d566052 Checked the nonempty and unique name guards and target assertion.
|
|
29
35
|
*/
|
|
30
36
|
export declare function runPlatformGatewayCapabilityConformance(input: RunPlatformGatewayCapabilityConformanceInput): Promise<PlatformGatewayCapabilityConformanceReport>;
|
|
@@ -24,6 +24,12 @@ const optionalPlatformCapabilityKeySet = new Set(optionalPlatformCapabilityKeys)
|
|
|
24
24
|
* Runs provider-neutral capability checks against real adapter gateways or
|
|
25
25
|
* target-configured wrappers. Every read must return a complete boolean
|
|
26
26
|
* snapshot, a fresh object, and the provider's latest state.
|
|
27
|
+
* @evidence docs/specs/platform-capability-snapshots.md#snapshot-shape Checks each gateway read against the required boolean keys and expected provider state.
|
|
28
|
+
* @evidenceReview docs/specs/platform-capability-snapshots.md#snapshot-shape #f83948b Reviewed the required keys, optional banner default, and fresh reread in runFixture.
|
|
29
|
+
* @evidence docs/specs/platform-capability-snapshots.md#provider-transitions Checks a fresh provider read after the optional transition update.
|
|
30
|
+
* @evidenceReview docs/specs/platform-capability-snapshots.md#provider-transitions #839c0c8 Reviewed the changed-state guard and post-update snapshot assertion.
|
|
31
|
+
* @evidence docs/specs/platform-capability-snapshots.md#fixture-validation Rejects invalid fixture sets and returns the names of passing fixtures.
|
|
32
|
+
* @evidenceReview docs/specs/platform-capability-snapshots.md#fixture-validation #d566052 Checked the nonempty and unique name guards and target assertion.
|
|
27
33
|
*/
|
|
28
34
|
export async function runPlatformGatewayCapabilityConformance(input) {
|
|
29
35
|
if (input.fixtures.length === 0) {
|
|
@@ -52,21 +58,28 @@ export async function runPlatformGatewayCapabilityConformance(input) {
|
|
|
52
58
|
return { passedFixtures };
|
|
53
59
|
}
|
|
54
60
|
async function runFixture(fixture) {
|
|
61
|
+
// A fixture may accidentally share its expected object with the provider.
|
|
62
|
+
// Keep the oracle independent before tryMutateSnapshot probes isolation.
|
|
63
|
+
const initialExpected = { ...fixture.expectedCapabilities };
|
|
64
|
+
const transitionExpected = fixture.transition === undefined
|
|
65
|
+
? undefined
|
|
66
|
+
: { ...fixture.transition.expectedCapabilities };
|
|
55
67
|
assertEqual(fixture.gateway.target, fixture.expectedTarget, 'gateway target must match the fixture target');
|
|
56
68
|
const first = await fixture.gateway.getCapabilities();
|
|
57
|
-
assertCapabilitySnapshot(first,
|
|
69
|
+
assertCapabilitySnapshot(first, initialExpected);
|
|
58
70
|
tryMutateSnapshot(first);
|
|
59
71
|
const second = await fixture.gateway.getCapabilities();
|
|
60
72
|
assert(second !== first, 'getCapabilities must return a fresh snapshot object for every read');
|
|
61
|
-
assertCapabilitySnapshot(second,
|
|
62
|
-
if (fixture.transition === undefined) {
|
|
73
|
+
assertCapabilitySnapshot(second, initialExpected);
|
|
74
|
+
if (fixture.transition === undefined || transitionExpected === undefined) {
|
|
63
75
|
return;
|
|
64
76
|
}
|
|
65
|
-
assert(hasCapabilityDifference(
|
|
77
|
+
assert(hasCapabilityDifference(initialExpected, transitionExpected), 'a transition fixture must change at least one capability');
|
|
66
78
|
await fixture.transition.update();
|
|
67
79
|
const updated = await fixture.gateway.getCapabilities();
|
|
68
80
|
assert(updated !== second, 'getCapabilities must return a fresh snapshot after a provider transition');
|
|
69
|
-
|
|
81
|
+
assert(updated !== first, 'getCapabilities must not reuse an earlier snapshot after a provider transition');
|
|
82
|
+
assertCapabilitySnapshot(updated, transitionExpected);
|
|
70
83
|
}
|
|
71
84
|
function assertCapabilitySnapshot(actual, expected) {
|
|
72
85
|
const actualKeys = Object.keys(actual).sort();
|
package/dist/index.d.ts
CHANGED
|
@@ -59,7 +59,29 @@ export interface PurchaseResult {
|
|
|
59
59
|
}
|
|
60
60
|
export interface PurchaseRestoreResult {
|
|
61
61
|
readonly restoredEntitlements: readonly Entitlement[];
|
|
62
|
+
/** Server-confirmed consumable outcomes; native order visibility alone is not a grant. */
|
|
63
|
+
readonly settledPurchases?: readonly PurchaseSettlement[];
|
|
62
64
|
}
|
|
65
|
+
export interface PurchaseSettlement {
|
|
66
|
+
readonly transactionId: string;
|
|
67
|
+
readonly productId: LogicalProductId;
|
|
68
|
+
readonly status: 'granted' | 'refunded';
|
|
69
|
+
readonly ledgerEntryId?: string;
|
|
70
|
+
readonly alreadyProcessed?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolve a specific purchase from authoritative checkout or restore evidence.
|
|
74
|
+
* A completed native checkout without authoritativeGrant is still unconfirmed.
|
|
75
|
+
* This is UI status evidence, never permission to credit a wallet locally.
|
|
76
|
+
* The caller must pair `purchase` with its requested `productId` because
|
|
77
|
+
* PurchaseResult itself does not carry a product identifier.
|
|
78
|
+
*/
|
|
79
|
+
export declare function findAuthoritativePurchaseSettlement(input: {
|
|
80
|
+
readonly productId: LogicalProductId;
|
|
81
|
+
readonly transactionId?: string;
|
|
82
|
+
readonly purchase?: PurchaseResult;
|
|
83
|
+
readonly restore?: PurchaseRestoreResult;
|
|
84
|
+
}): PurchaseSettlement | null;
|
|
63
85
|
export interface RewardedAdResult {
|
|
64
86
|
readonly status: 'completed' | 'skipped' | 'unavailable' | 'failed';
|
|
65
87
|
readonly rewardGranted: boolean;
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,41 @@ function isPlatformOperationCode(code) {
|
|
|
41
41
|
&& code.length <= 128
|
|
42
42
|
&& /^[A-Z][A-Z0-9_:-]*$/u.test(code);
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a specific purchase from authoritative checkout or restore evidence.
|
|
46
|
+
* A completed native checkout without authoritativeGrant is still unconfirmed.
|
|
47
|
+
* This is UI status evidence, never permission to credit a wallet locally.
|
|
48
|
+
* The caller must pair `purchase` with its requested `productId` because
|
|
49
|
+
* PurchaseResult itself does not carry a product identifier.
|
|
50
|
+
*/
|
|
51
|
+
export function findAuthoritativePurchaseSettlement(input) {
|
|
52
|
+
const effectiveTransactionId = input.transactionId ?? input.purchase?.transactionId;
|
|
53
|
+
const matchingRestored = input.restore?.settledPurchases?.filter((settlement) => settlement.productId === input.productId
|
|
54
|
+
&& (effectiveTransactionId === undefined || settlement.transactionId === effectiveTransactionId));
|
|
55
|
+
// Without an order ID, multiple historical outcomes are ambiguous.
|
|
56
|
+
if (matchingRestored !== undefined && matchingRestored.length > 1) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
if (matchingRestored?.[0] !== undefined) {
|
|
60
|
+
return matchingRestored[0];
|
|
61
|
+
}
|
|
62
|
+
const purchase = input.purchase;
|
|
63
|
+
if (purchase?.status !== 'completed'
|
|
64
|
+
|| purchase.transactionId === undefined
|
|
65
|
+
|| purchase.authoritativeGrant === undefined
|
|
66
|
+
|| (effectiveTransactionId !== undefined && effectiveTransactionId !== purchase.transactionId)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
transactionId: purchase.transactionId,
|
|
71
|
+
productId: input.productId,
|
|
72
|
+
status: 'granted',
|
|
73
|
+
ledgerEntryId: purchase.authoritativeGrant.ledgerEntryId,
|
|
74
|
+
...(purchase.authoritativeGrant.alreadyProcessed === undefined
|
|
75
|
+
? {}
|
|
76
|
+
: { alreadyProcessed: purchase.authoritativeGrant.alreadyProcessed }),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
44
79
|
export function resolveShareCompletion(result) {
|
|
45
80
|
if (result.status !== 'shared') {
|
|
46
81
|
return undefined;
|
package/package.json
CHANGED