@mpgd/game-services 0.1.0 → 0.3.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 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, GameServicesStoreTarget, RecordLeaderboardScoreRequest, RecordLeaderboardScoreResponse, VerifyPurchaseRequest, VerifyPurchaseResponse } from './types';
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: GameServicesStoreTarget;
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: input.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: input.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' && input !== 'android' && input !== 'ios' && input !== 'ait') {
107
- throw new Error('target must be browser, android, ios, or ait.');
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.1.0",
3
+ "version": "0.3.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.1.0",
57
- "@mpgd/catalog": "0.1.0",
58
- "@mpgd/platform": "0.1.0"
56
+ "@mpgd/analytics": "0.3.0",
57
+ "@mpgd/catalog": "0.3.0",
58
+ "@mpgd/platform": "0.3.0"
59
59
  },
60
60
  "devDependencies": {
61
61
  "ttsc": "0.16.9",