@mpgd/platform 0.8.0 → 0.10.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/capability-conformance.d.ts +2 -1
- package/dist/capability-conformance.js +21 -6
- package/dist/index.d.ts +28 -1
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PlatformCapabilities, PlatformGateway, PlatformTarget } from './index.js';
|
|
2
|
-
export declare const platformCapabilityKeys: readonly ["nativeIap", "nativeAds", "rewardedAds", "interstitialAds", "nativeLeaderboard", "achievements", "cloudSave", "socialShare", "haptics", "localizedContent"];
|
|
2
|
+
export declare const platformCapabilityKeys: readonly ["nativeIap", "nativeAds", "rewardedAds", "interstitialAds", "nativeLeaderboard", "remoteLeaderboard", "achievements", "cloudSave", "socialShare", "haptics", "localizedContent"];
|
|
3
|
+
export declare const optionalPlatformCapabilityKeys: readonly ["bannerAds"];
|
|
3
4
|
export interface PlatformGatewayCapabilityConformanceTransition {
|
|
4
5
|
readonly update: () => Promise<void> | void;
|
|
5
6
|
readonly expectedCapabilities: PlatformCapabilities;
|
|
@@ -4,12 +4,22 @@ export const platformCapabilityKeys = Object.freeze([
|
|
|
4
4
|
'rewardedAds',
|
|
5
5
|
'interstitialAds',
|
|
6
6
|
'nativeLeaderboard',
|
|
7
|
+
'remoteLeaderboard',
|
|
7
8
|
'achievements',
|
|
8
9
|
'cloudSave',
|
|
9
10
|
'socialShare',
|
|
10
11
|
'haptics',
|
|
11
12
|
'localizedContent',
|
|
12
13
|
]);
|
|
14
|
+
export const optionalPlatformCapabilityKeys = Object.freeze([
|
|
15
|
+
'bannerAds',
|
|
16
|
+
]);
|
|
17
|
+
const allowedPlatformCapabilityKeys = Object.freeze([
|
|
18
|
+
...platformCapabilityKeys,
|
|
19
|
+
...optionalPlatformCapabilityKeys,
|
|
20
|
+
]);
|
|
21
|
+
const allowedPlatformCapabilityKeySet = new Set(allowedPlatformCapabilityKeys);
|
|
22
|
+
const optionalPlatformCapabilityKeySet = new Set(optionalPlatformCapabilityKeys);
|
|
13
23
|
/**
|
|
14
24
|
* Runs provider-neutral capability checks against real adapter gateways or
|
|
15
25
|
* target-configured wrappers. Every read must return a complete boolean
|
|
@@ -60,11 +70,15 @@ async function runFixture(fixture) {
|
|
|
60
70
|
}
|
|
61
71
|
function assertCapabilitySnapshot(actual, expected) {
|
|
62
72
|
const actualKeys = Object.keys(actual).sort();
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
const missingKeys = platformCapabilityKeys.filter((key) => !Object.hasOwn(actual, key));
|
|
74
|
+
const unexpectedKeys = actualKeys.filter((key) => !allowedPlatformCapabilityKeySet.has(key));
|
|
75
|
+
assertEqual(JSON.stringify({ missingKeys, unexpectedKeys }), JSON.stringify({ missingKeys: [], unexpectedKeys: [] }), 'capability snapshots must contain all required keys and no unknown keys');
|
|
76
|
+
for (const key of allowedPlatformCapabilityKeys) {
|
|
77
|
+
const optional = optionalPlatformCapabilityKeySet.has(key);
|
|
78
|
+
if (!optional || Object.hasOwn(actual, key)) {
|
|
79
|
+
assertEqual(typeof actual[key], 'boolean', `capability ${key} must be a boolean`);
|
|
80
|
+
}
|
|
81
|
+
assertEqual(optional ? (actual[key] ?? false) : actual[key], optional ? (expected[key] ?? false) : expected[key], `capability ${key} must match the expected provider state`);
|
|
68
82
|
}
|
|
69
83
|
}
|
|
70
84
|
function tryMutateSnapshot(snapshot) {
|
|
@@ -76,7 +90,8 @@ function tryMutateSnapshot(snapshot) {
|
|
|
76
90
|
}
|
|
77
91
|
}
|
|
78
92
|
function hasCapabilityDifference(first, second) {
|
|
79
|
-
return
|
|
93
|
+
return allowedPlatformCapabilityKeys
|
|
94
|
+
.some((key) => (first[key] ?? false) !== (second[key] ?? false));
|
|
80
95
|
}
|
|
81
96
|
function assert(condition, message) {
|
|
82
97
|
if (!condition) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type PlatformTarget = 'browser' | 'android' | 'ios' | 'ait' | 'reddit' | 'verse8' | 'telegram' | 'tauri';
|
|
1
|
+
export type PlatformTarget = 'browser' | 'microsoft-store' | 'android' | 'ios' | 'ait' | 'reddit' | 'verse8' | 'telegram' | 'tauri';
|
|
2
2
|
export type StarterLogicalProductId = 'COINS_100' | 'COINS_500' | 'REMOVE_ADS';
|
|
3
3
|
export type LogicalProductId = StarterLogicalProductId | (string & Record<never, never>);
|
|
4
4
|
export type StarterLogicalAdPlacementId = 'CONTINUE_AFTER_FAIL' | 'STAGE_END_INTERSTITIAL';
|
|
@@ -29,6 +29,11 @@ export interface PurchaseResult {
|
|
|
29
29
|
readonly transactionId?: string;
|
|
30
30
|
readonly entitlementIds: readonly string[];
|
|
31
31
|
readonly evidence?: PlatformEvidenceEnvelope;
|
|
32
|
+
/** Present only when the adapter already completed the authoritative server grant. */
|
|
33
|
+
readonly authoritativeGrant?: Readonly<{
|
|
34
|
+
readonly ledgerEntryId: string;
|
|
35
|
+
readonly alreadyProcessed?: boolean;
|
|
36
|
+
}>;
|
|
32
37
|
}
|
|
33
38
|
export interface PurchaseRestoreResult {
|
|
34
39
|
readonly restoredEntitlements: readonly Entitlement[];
|
|
@@ -42,6 +47,16 @@ export interface RewardedAdResult {
|
|
|
42
47
|
export interface InterstitialAdResult {
|
|
43
48
|
readonly status: 'shown' | 'skipped' | 'unavailable';
|
|
44
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Result of mounting a platform-rendered inline banner into a game-owned surface.
|
|
52
|
+
* The platform host owns the native/SDK attachment; games only reserve and name
|
|
53
|
+
* a surface, so this contract does not leak DOM or provider types. Adapters must
|
|
54
|
+
* release any partial attachment before resolving `unavailable` or `failed`;
|
|
55
|
+
* games only need to unmount a successfully mounted banner.
|
|
56
|
+
*/
|
|
57
|
+
export interface BannerAdMountResult {
|
|
58
|
+
readonly status: 'mounted' | 'unavailable' | 'failed';
|
|
59
|
+
}
|
|
45
60
|
export interface CommerceAdapter {
|
|
46
61
|
getProducts(): Promise<readonly ProductInfo[]>;
|
|
47
62
|
purchase(input: {
|
|
@@ -63,6 +78,14 @@ export interface AdAdapter {
|
|
|
63
78
|
showInterstitial?(input: {
|
|
64
79
|
readonly placementId: LogicalAdPlacementId;
|
|
65
80
|
}): Promise<InterstitialAdResult>;
|
|
81
|
+
mountBanner?(input: {
|
|
82
|
+
readonly placementId: LogicalAdPlacementId;
|
|
83
|
+
/** Host-resolvable identifier for an empty, game-owned inline ad surface. */
|
|
84
|
+
readonly surfaceId: string;
|
|
85
|
+
}): Promise<BannerAdMountResult>;
|
|
86
|
+
unmountBanner?(input: {
|
|
87
|
+
readonly surfaceId: string;
|
|
88
|
+
}): Promise<void>;
|
|
66
89
|
}
|
|
67
90
|
export type PromotionRewardAvailability = 'available' | 'configuration-required' | 'unsupported';
|
|
68
91
|
export type PromotionRewardResult = {
|
|
@@ -110,7 +133,11 @@ export interface PlatformCapabilities {
|
|
|
110
133
|
readonly nativeAds: boolean;
|
|
111
134
|
readonly rewardedAds: boolean;
|
|
112
135
|
readonly interstitialAds: boolean;
|
|
136
|
+
/** Optional for compatibility with adapters published before inline ads. */
|
|
137
|
+
readonly bannerAds?: boolean;
|
|
113
138
|
readonly nativeLeaderboard: boolean;
|
|
139
|
+
/** A game-owned server leaderboard is available without a native platform surface. */
|
|
140
|
+
readonly remoteLeaderboard: boolean;
|
|
114
141
|
readonly achievements: boolean;
|
|
115
142
|
readonly cloudSave: boolean;
|
|
116
143
|
readonly socialShare: boolean;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED