@mpgd/game-services 0.1.0 → 0.2.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/client.d.ts +2 -2
- package/dist/client.js +44 -2
- package/dist/types.d.ts +1 -1
- package/dist/types.js +6 -2
- package/package.json +4 -4
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AnalyticsSink } from '@mpgd/analytics';
|
|
2
2
|
import type { LeaderboardScoreInput, LogicalAdPlacementId, LogicalProductId, PlatformGateway, PlatformTarget, PurchaseResult, RewardedAdResult } from '@mpgd/platform';
|
|
3
3
|
import type { GameServicesContractClient } from './contract';
|
|
4
|
-
import type { ClaimAdRewardRequest, ClaimAdRewardResponse,
|
|
4
|
+
import type { ClaimAdRewardRequest, ClaimAdRewardResponse, GameServicesLedgerTarget, RecordLeaderboardScoreRequest, RecordLeaderboardScoreResponse, VerifyPurchaseRequest, VerifyPurchaseResponse } from './types';
|
|
5
5
|
export interface PurchaseVerificationApi {
|
|
6
6
|
verifyPurchase(input: VerifyPurchaseRequest): Promise<VerifyPurchaseResponse>;
|
|
7
7
|
}
|
|
@@ -73,7 +73,7 @@ export interface CreateGameServicesClientInput {
|
|
|
73
73
|
readonly gateway: PlatformGateway;
|
|
74
74
|
readonly backend: GameServicesBackendApi;
|
|
75
75
|
readonly playerId: string;
|
|
76
|
-
readonly target:
|
|
76
|
+
readonly target: GameServicesLedgerTarget;
|
|
77
77
|
readonly analytics?: AnalyticsSink;
|
|
78
78
|
readonly analyticsSessionId?: string;
|
|
79
79
|
readonly now?: () => string;
|
package/dist/client.js
CHANGED
|
@@ -28,6 +28,25 @@ export function createGameServicesClient(input) {
|
|
|
28
28
|
});
|
|
29
29
|
return {
|
|
30
30
|
async purchase(purchaseInput) {
|
|
31
|
+
const target = input.target;
|
|
32
|
+
if (!isGameServicesStoreTarget(target)) {
|
|
33
|
+
const purchase = {
|
|
34
|
+
status: 'failed',
|
|
35
|
+
entitlementIds: [],
|
|
36
|
+
};
|
|
37
|
+
await analytics.track({
|
|
38
|
+
name: 'purchase_rejected',
|
|
39
|
+
properties: {
|
|
40
|
+
productId: purchaseInput.productId,
|
|
41
|
+
status: purchase.status,
|
|
42
|
+
reason: 'unsupported_target',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
status: 'rejected',
|
|
47
|
+
purchase,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
31
50
|
const purchase = await input.gateway.commerce.purchase(purchaseInput);
|
|
32
51
|
if (purchase.status !== 'completed' || purchase.transactionId === undefined) {
|
|
33
52
|
await analytics.track({
|
|
@@ -44,7 +63,7 @@ export function createGameServicesClient(input) {
|
|
|
44
63
|
};
|
|
45
64
|
}
|
|
46
65
|
const verification = await input.backend.purchases.verifyPurchase({
|
|
47
|
-
target
|
|
66
|
+
target,
|
|
48
67
|
playerId: input.playerId,
|
|
49
68
|
productId: purchaseInput.productId,
|
|
50
69
|
platformTransactionId: purchase.transactionId,
|
|
@@ -72,6 +91,26 @@ export function createGameServicesClient(input) {
|
|
|
72
91
|
return result;
|
|
73
92
|
},
|
|
74
93
|
async claimRewardedAd(rewardInput) {
|
|
94
|
+
const target = input.target;
|
|
95
|
+
if (!isGameServicesStoreTarget(target)) {
|
|
96
|
+
const reward = {
|
|
97
|
+
status: 'unavailable',
|
|
98
|
+
rewardGranted: false,
|
|
99
|
+
};
|
|
100
|
+
await analytics.track({
|
|
101
|
+
name: 'rewarded_ad_rejected',
|
|
102
|
+
properties: {
|
|
103
|
+
placementId: rewardInput.placementId,
|
|
104
|
+
status: reward.status,
|
|
105
|
+
rewardGranted: reward.rewardGranted,
|
|
106
|
+
reason: 'unsupported_target',
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
status: 'rejected',
|
|
111
|
+
reward,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
75
114
|
const reward = await input.gateway.ads.showRewarded(rewardInput);
|
|
76
115
|
if (reward.status !== 'completed' || !reward.rewardGranted) {
|
|
77
116
|
await analytics.track({
|
|
@@ -88,7 +127,7 @@ export function createGameServicesClient(input) {
|
|
|
88
127
|
};
|
|
89
128
|
}
|
|
90
129
|
const claim = await input.backend.adRewards.claimAdReward({
|
|
91
|
-
target
|
|
130
|
+
target,
|
|
92
131
|
playerId: input.playerId,
|
|
93
132
|
placementId: rewardInput.placementId,
|
|
94
133
|
...(reward.ledgerEntryId === undefined
|
|
@@ -240,6 +279,9 @@ export function createGameServicesIdempotencyKey(input) {
|
|
|
240
279
|
function normalizeSegment(value) {
|
|
241
280
|
return value.replaceAll(/[^a-zA-Z0-9_-]+/g, '-').replaceAll(/^-|-$/g, '').slice(0, 64);
|
|
242
281
|
}
|
|
282
|
+
function isGameServicesStoreTarget(target) {
|
|
283
|
+
return target === 'android' || target === 'ios' || target === 'ait';
|
|
284
|
+
}
|
|
243
285
|
async function sendGameServicesBackendRequest(transport, endpoint, body) {
|
|
244
286
|
const response = await transport.send({
|
|
245
287
|
method: 'POST',
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ProductGrant } from '@mpgd/catalog';
|
|
2
2
|
import type { LeaderboardScoreInput, LogicalAdPlacementId, LogicalProductId, PlatformTarget } from '@mpgd/platform';
|
|
3
3
|
export type GameServicesStoreTarget = Extract<PlatformTarget, 'android' | 'ios' | 'ait'>;
|
|
4
|
-
export type GameServicesLedgerTarget = Extract<PlatformTarget, 'browser' | 'android' | 'ios' | 'ait'>;
|
|
4
|
+
export type GameServicesLedgerTarget = Extract<PlatformTarget, 'browser' | 'android' | 'ios' | 'ait' | 'reddit'>;
|
|
5
5
|
export type PurchaseIdempotencyKey = string;
|
|
6
6
|
export type AdRewardIdempotencyKey = string;
|
|
7
7
|
export type EntitlementIdempotencyKey = PurchaseIdempotencyKey | AdRewardIdempotencyKey;
|
package/dist/types.js
CHANGED
|
@@ -103,8 +103,12 @@ function assertStoreTarget(input) {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
function assertLeaderboardTarget(input) {
|
|
106
|
-
if (input !== 'browser'
|
|
107
|
-
|
|
106
|
+
if (input !== 'browser'
|
|
107
|
+
&& input !== 'android'
|
|
108
|
+
&& input !== 'ios'
|
|
109
|
+
&& input !== 'ait'
|
|
110
|
+
&& input !== 'reddit') {
|
|
111
|
+
throw new Error('target must be browser, android, ios, ait, or reddit.');
|
|
108
112
|
}
|
|
109
113
|
}
|
|
110
114
|
function assertNonEmptyString(input, label) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/game-services",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Client, contract, server, store, and test helpers for authoritative mpgd game services.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"@orpc/client": "2.0.0-beta.14",
|
|
54
54
|
"@orpc/contract": "2.0.0-beta.14",
|
|
55
55
|
"@orpc/server": "2.0.0-beta.14",
|
|
56
|
-
"@mpgd/analytics": "0.
|
|
57
|
-
"@mpgd/catalog": "0.
|
|
58
|
-
"@mpgd/platform": "0.
|
|
56
|
+
"@mpgd/analytics": "0.2.0",
|
|
57
|
+
"@mpgd/catalog": "0.2.0",
|
|
58
|
+
"@mpgd/platform": "0.2.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"ttsc": "0.16.9",
|