@mpgd/game-services 0.28.1 → 0.30.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/README.md +18 -3
- package/dist/account-deletion.d.ts +306 -0
- package/dist/account-deletion.js +491 -0
- package/dist/app-store-recovery.d.ts +6 -0
- package/dist/app-store-recovery.js +26 -16
- package/dist/app-store-server-notifications.d.ts +158 -0
- package/dist/app-store-server-notifications.js +270 -0
- package/dist/app-store-server.d.ts +8 -0
- package/dist/app-store-server.js +135 -37
- package/dist/app-store-verifier.d.ts +34 -0
- package/dist/app-store-verifier.js +161 -31
- package/dist/commerce-ledger.d.ts +55 -0
- package/dist/commerce-ledger.js +198 -0
- package/dist/commerce-reconciler.js +47 -7
- package/dist/evidence-verification.d.ts +19 -0
- package/dist/google-play-publisher-client.d.ts +2 -1
- package/dist/google-play-publisher-client.js +80 -0
- package/dist/google-play-purchase.d.ts +7 -0
- package/dist/google-play-purchase.js +32 -7
- package/dist/google-play-store-server.d.ts +160 -0
- package/dist/google-play-store-server.js +297 -0
- package/dist/guest-session.d.ts +112 -2
- package/dist/guest-session.js +196 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/notifications/delivery-provider.d.ts +7 -0
- package/dist/notifications/fcm.d.ts +30 -3
- package/dist/notifications/fcm.js +72 -13
- package/dist/notifications/service.js +33 -5
- package/dist/notifications/store-conformance.js +7 -1
- package/dist/notifications/store.d.ts +9 -0
- package/dist/notifications/store.js +41 -0
- package/dist/operation-results.d.ts +7 -0
- package/dist/purchase-sharing.d.ts +41 -0
- package/dist/purchase-sharing.js +37 -0
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.js +13 -0
- package/dist/server.d.ts +60 -1
- package/dist/server.js +536 -42
- package/dist/types.d.ts +30 -0
- package/dist/types.js +22 -0
- package/dist/verified-leaderboard.d.ts +13 -0
- package/dist/verified-leaderboard.js +31 -0
- package/package.json +17 -5
package/dist/types.d.ts
CHANGED
|
@@ -38,7 +38,18 @@ export interface VerifyPurchaseRequest {
|
|
|
38
38
|
readonly idempotencyKey: PurchaseIdempotencyKey;
|
|
39
39
|
readonly purchasedAt: string;
|
|
40
40
|
readonly evidence?: PlatformEvidenceEnvelope;
|
|
41
|
+
/**
|
|
42
|
+
* Why the client sends the purchase. `restore` is a purchase the store
|
|
43
|
+
* reported without this client starting it (a reinstall, a new device, or
|
|
44
|
+
* Restore Purchases): the backend may then grant this player a verified
|
|
45
|
+
* non-consumable the store binds to an earlier player (`restoreSharing`,
|
|
46
|
+
* RFC "Restore sharing"). Absent means `purchase`; the intent is a request
|
|
47
|
+
* for that policy, never proof of ownership.
|
|
48
|
+
*/
|
|
49
|
+
readonly intent?: VerifyPurchaseIntent;
|
|
41
50
|
}
|
|
51
|
+
/** `VerifyPurchaseRequest.intent`. */
|
|
52
|
+
export type VerifyPurchaseIntent = 'purchase' | 'restore';
|
|
42
53
|
export interface ClaimAdRewardRequest {
|
|
43
54
|
readonly target: GameServicesAdRewardTarget;
|
|
44
55
|
/** Versioned provider identity, independent of build target; checked by server registration. */
|
|
@@ -98,6 +109,25 @@ export interface EntitlementLedgerRevocation {
|
|
|
98
109
|
/** The notification's own authority identity, when the handler has one. */
|
|
99
110
|
readonly evidenceVerificationId?: string;
|
|
100
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* A ledger note: a store event about a grant that changes nothing by itself
|
|
114
|
+
* and grants nothing (today an App Store `REFUND_REVERSED` after the grant
|
|
115
|
+
* was revoked). It is kept so support can act on it; a re-grant is a new,
|
|
116
|
+
* game-owned grant entry.
|
|
117
|
+
*/
|
|
118
|
+
export interface EntitlementLedgerNote {
|
|
119
|
+
/** Unique per store event, for example `app-store:notification:<notificationUUID>`. */
|
|
120
|
+
readonly noteId: string;
|
|
121
|
+
readonly kind: 'refund_reversed';
|
|
122
|
+
readonly playerId: string;
|
|
123
|
+
/** The grant the event is about. */
|
|
124
|
+
readonly ledgerEntryId: string;
|
|
125
|
+
/** The `revoke` entry the store reversed, when there is one. */
|
|
126
|
+
readonly revocationLedgerEntryId?: string;
|
|
127
|
+
readonly recordedAt: string;
|
|
128
|
+
readonly payload: EntitlementLedgerPayload;
|
|
129
|
+
}
|
|
130
|
+
export declare function assertEntitlementLedgerNote(input: EntitlementLedgerNote): EntitlementLedgerNote;
|
|
101
131
|
export interface EntitlementRevocationTransaction extends EntitlementLedgerRevocation {
|
|
102
132
|
readonly ledgerEntryId: string;
|
|
103
133
|
}
|
package/dist/types.js
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { assertOwnEnumerablePropertyLimit, gameServicesRequestLimits, toGameServicesRequestValidationError, } from './validation.js';
|
|
2
|
+
export function assertEntitlementLedgerNote(input) {
|
|
3
|
+
assertRecord(input, 'EntitlementLedgerNote');
|
|
4
|
+
assertNonEmptyString(input.noteId, 'noteId');
|
|
5
|
+
if (input.kind !== 'refund_reversed') {
|
|
6
|
+
throw new Error('kind must be refund_reversed.');
|
|
7
|
+
}
|
|
8
|
+
assertNonEmptyString(input.playerId, 'playerId');
|
|
9
|
+
assertNonEmptyString(input.ledgerEntryId, 'ledgerEntryId');
|
|
10
|
+
assertOptionalNonEmptyString(input.revocationLedgerEntryId, 'revocationLedgerEntryId');
|
|
11
|
+
assertNonEmptyString(input.recordedAt, 'recordedAt');
|
|
12
|
+
assertPayload(input.payload);
|
|
13
|
+
return input;
|
|
14
|
+
}
|
|
2
15
|
/**
|
|
3
16
|
* Validates an untrusted purchase verification request. Failures throw
|
|
4
17
|
* `GameServicesRequestValidationError` so transports can answer with a stable 400.
|
|
@@ -17,6 +30,9 @@ export function assertVerifyPurchaseRequest(input) {
|
|
|
17
30
|
assertRequestString(input.idempotencyKey, 'idempotencyKey');
|
|
18
31
|
assertRequestString(input.purchasedAt, 'purchasedAt');
|
|
19
32
|
assertOptionalEvidenceEnvelope(input.evidence);
|
|
33
|
+
if (input.intent !== undefined && input.intent !== 'purchase' && input.intent !== 'restore') {
|
|
34
|
+
throw new Error('intent must be purchase or restore.');
|
|
35
|
+
}
|
|
20
36
|
return input;
|
|
21
37
|
});
|
|
22
38
|
}
|
|
@@ -30,6 +46,12 @@ export function assertVerifyPurchaseResponse(input) {
|
|
|
30
46
|
if (input.finalization !== undefined) {
|
|
31
47
|
assertPurchaseGrantFinalization(input.finalization);
|
|
32
48
|
}
|
|
49
|
+
if (input.restoredAcrossPlayers !== undefined && input.restoredAcrossPlayers !== true) {
|
|
50
|
+
throw new Error('restoredAcrossPlayers must be true when present.');
|
|
51
|
+
}
|
|
52
|
+
if (input.restoredAcrossPlayers === true && input.verified !== true) {
|
|
53
|
+
throw new Error('restoredAcrossPlayers requires a verified response.');
|
|
54
|
+
}
|
|
33
55
|
return input;
|
|
34
56
|
}
|
|
35
57
|
/** Bounds one ledger status read; a client asks for the grants of one journal window. */
|
|
@@ -98,6 +98,19 @@ export declare class InMemoryVerifiedLeaderboardService implements VerifiedLeade
|
|
|
98
98
|
private readonly attemptsById;
|
|
99
99
|
private readonly retainedByLeaderboard;
|
|
100
100
|
constructor(now?: () => string);
|
|
101
|
+
/**
|
|
102
|
+
* Account deletion (a `PlayerDataEraser` of `@mpgd/game-services`):
|
|
103
|
+
* removes every attempt and board entry whose participant id is the
|
|
104
|
+
* player id (the id the reference recorder uses). This module stays
|
|
105
|
+
* import-free, so the erasure input is typed structurally.
|
|
106
|
+
*/
|
|
107
|
+
erasePlayerData(input: {
|
|
108
|
+
readonly playerId: string;
|
|
109
|
+
readonly retainedPlayerId: string;
|
|
110
|
+
}): Promise<{
|
|
111
|
+
readonly deleted: number;
|
|
112
|
+
readonly retained: number;
|
|
113
|
+
}>;
|
|
101
114
|
recordVerifiedAttempt(input: RecordVerifiedLeaderboardAttemptRequest): Promise<RecordVerifiedLeaderboardAttemptResponse>;
|
|
102
115
|
getSnapshot(input: GetVerifiedLeaderboardSnapshotRequest): Promise<VerifiedLeaderboardSnapshot | undefined>;
|
|
103
116
|
private createRecordResponse;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export const verifiedLeaderboardIdentifierMaximumLength = 512;
|
|
2
2
|
export const verifiedLeaderboardMetricsMaximumCount = 16;
|
|
3
3
|
export const verifiedLeaderboardMetricKeyMaximumLength = 64;
|
|
4
|
+
/** `retainedPlayerIdPrefix` of `./account-deletion`; this module stays import-free. */
|
|
5
|
+
const retainedPlayerIdPrefix = 'deleted:';
|
|
4
6
|
const verifiedLeaderboardMetricKeyPattern = /^[A-Za-z][A-Za-z0-9._-]{0,63}$/;
|
|
5
7
|
const timestampPattern = new RegExp('^(\\d{4})-(\\d{2})-(\\d{2})'
|
|
6
8
|
+ 'T(\\d{2}):(\\d{2}):(\\d{2})'
|
|
@@ -25,6 +27,35 @@ export class InMemoryVerifiedLeaderboardService {
|
|
|
25
27
|
constructor(now = () => new Date().toISOString()) {
|
|
26
28
|
this.now = now;
|
|
27
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Account deletion (a `PlayerDataEraser` of `@mpgd/game-services`):
|
|
32
|
+
* removes every attempt and board entry whose participant id is the
|
|
33
|
+
* player id (the id the reference recorder uses). This module stays
|
|
34
|
+
* import-free, so the erasure input is typed structurally.
|
|
35
|
+
*/
|
|
36
|
+
async erasePlayerData(input) {
|
|
37
|
+
const participantId = input.playerId;
|
|
38
|
+
if (typeof participantId !== 'string' || participantId.length === 0
|
|
39
|
+
|| participantId.startsWith(retainedPlayerIdPrefix)
|
|
40
|
+
|| typeof input.retainedPlayerId !== 'string'
|
|
41
|
+
|| !input.retainedPlayerId.startsWith(retainedPlayerIdPrefix)
|
|
42
|
+
|| input.retainedPlayerId.length <= retainedPlayerIdPrefix.length) {
|
|
43
|
+
throw new Error('Player data erasure needs a player id and a deleted:<id> retained player id.');
|
|
44
|
+
}
|
|
45
|
+
let removed = 0;
|
|
46
|
+
for (const [key, stored] of [...this.attemptsById]) {
|
|
47
|
+
if (stored.attempt.participantId === participantId) {
|
|
48
|
+
this.attemptsById.delete(key);
|
|
49
|
+
removed += 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
for (const retained of this.retainedByLeaderboard.values()) {
|
|
53
|
+
if (retained.delete(participantId)) {
|
|
54
|
+
removed += 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return { deleted: removed, retained: 0 };
|
|
58
|
+
}
|
|
28
59
|
async recordVerifiedAttempt(input) {
|
|
29
60
|
assertRecordVerifiedLeaderboardAttemptRequest(input);
|
|
30
61
|
const definition = this.ensureDefinition(input.definition);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/game-services",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "Client, contract, server, store, and test helpers for authoritative mpgd game services.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
"types": "./dist/index.d.ts",
|
|
38
38
|
"default": "./dist/index.js"
|
|
39
39
|
},
|
|
40
|
+
"./account-deletion": {
|
|
41
|
+
"types": "./dist/account-deletion.d.ts",
|
|
42
|
+
"default": "./dist/account-deletion.js"
|
|
43
|
+
},
|
|
40
44
|
"./admob-client-reward": {
|
|
41
45
|
"types": "./dist/admob-client-reward.d.ts",
|
|
42
46
|
"default": "./dist/admob-client-reward.js"
|
|
@@ -57,6 +61,10 @@
|
|
|
57
61
|
"types": "./dist/app-store-recovery.d.ts",
|
|
58
62
|
"default": "./dist/app-store-recovery.js"
|
|
59
63
|
},
|
|
64
|
+
"./app-store-server-notifications": {
|
|
65
|
+
"types": "./dist/app-store-server-notifications.d.ts",
|
|
66
|
+
"default": "./dist/app-store-server-notifications.js"
|
|
67
|
+
},
|
|
60
68
|
"./app-store-server": {
|
|
61
69
|
"types": "./dist/app-store-server.d.ts",
|
|
62
70
|
"default": "./dist/app-store-server.js"
|
|
@@ -105,6 +113,10 @@
|
|
|
105
113
|
"types": "./dist/google-play-purchase.d.ts",
|
|
106
114
|
"default": "./dist/google-play-purchase.js"
|
|
107
115
|
},
|
|
116
|
+
"./google-play-store-server": {
|
|
117
|
+
"types": "./dist/google-play-store-server.d.ts",
|
|
118
|
+
"default": "./dist/google-play-store-server.js"
|
|
119
|
+
},
|
|
108
120
|
"./google-play-publisher-client": {
|
|
109
121
|
"types": "./dist/google-play-publisher-client.d.ts",
|
|
110
122
|
"default": "./dist/google-play-publisher-client.js"
|
|
@@ -219,9 +231,9 @@
|
|
|
219
231
|
"@orpc/client": "2.0.0-beta.14",
|
|
220
232
|
"@orpc/contract": "2.0.0-beta.14",
|
|
221
233
|
"@orpc/server": "2.0.0-beta.14",
|
|
222
|
-
"@mpgd/
|
|
223
|
-
"@mpgd/
|
|
224
|
-
"@mpgd/
|
|
234
|
+
"@mpgd/catalog": "0.11.1",
|
|
235
|
+
"@mpgd/platform": "0.30.0",
|
|
236
|
+
"@mpgd/analytics": "0.5.3"
|
|
225
237
|
},
|
|
226
238
|
"peerDependencies": {
|
|
227
239
|
"@apple/app-store-server-library": "^3.1.0"
|
|
@@ -250,7 +262,7 @@
|
|
|
250
262
|
"fix": "ttsc fix",
|
|
251
263
|
"build": "cd ../.. && node tools/run-ttsx.mjs tools/package/build-packages.ts @mpgd/game-services",
|
|
252
264
|
"test:packed-transport": "pnpm build && node test/runtime-transport-package-import.mjs && node test/reward-evidence-import.mjs",
|
|
253
|
-
"test:unit": "cd ../.. && node tools/run-ttsx.mjs packages/game-services/src/client.test.ts && node tools/run-ttsx.mjs packages/game-services/src/client-progress.test.ts && node tools/run-ttsx.mjs packages/game-services/src/runtime.test.ts && node tools/run-ttsx.mjs packages/game-services/src/types.test.ts && node tools/run-ttsx.mjs packages/game-services/src/server.test.ts && node tools/run-ttsx.mjs packages/game-services/src/google-play-purchase.test.ts && node tools/run-ttsx.mjs packages/game-services/src/google-play-publisher-client.test.ts && node tools/run-ttsx.mjs packages/game-services/src/microsoft-store-purchase.test.ts && node tools/run-ttsx.mjs packages/game-services/src/microsoft-store-identity.test.ts && node tools/run-ttsx.mjs packages/game-services/src/platform-order.test.ts && node tools/run-ttsx.mjs packages/game-services/src/progress-link.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notification-delivery.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/service.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/service-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/client.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/client-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/scheduler.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/fcm.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/store-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/ait-functional-delivery.test.ts && node tools/run-ttsx.mjs packages/game-services/src/admob-ssv.test.ts && node tools/run-ttsx.mjs packages/game-services/src/app-store-verifier.test.ts && node tools/run-ttsx.mjs packages/game-services/src/apps-in-toss-evidence-verification-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/apps-in-toss-partner-api.test.ts && node tools/run-ttsx.mjs packages/game-services/src/verified-leaderboard.test.ts && node tools/run-ttsx.mjs packages/game-services/src/verified-leaderboard-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/verified-leaderboard-durability-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/verified-leaderboard-transport.test.ts && node tools/run-ttsx.mjs packages/game-services/src/guest-session.test.ts && node tools/run-ttsx.mjs packages/game-services/src/development-session.test.ts && node tools/run-ttsx.mjs packages/game-services/src/client-reward-evidence.test.ts && node tools/run-ttsx.mjs packages/game-services/src/ad-reward-verifier-registry.test.ts && node tools/run-ttsx.mjs packages/game-services/src/oneplay-reward.test.ts && node tools/run-ttsx.mjs packages/game-services/src/oneplay-purchase.test.ts && node tools/run-ttsx.mjs packages/game-services/src/commerce-registry-routing.test.ts && node tools/run-ttsx.mjs packages/game-services/src/commerce-registry-server.test.ts && node tools/run-ttsx.mjs packages/game-services/src/commerce-ledger-revocation.test.ts && node tools/run-ttsx.mjs packages/game-services/src/apps-in-toss-anonymous-auth.test.ts",
|
|
265
|
+
"test:unit": "cd ../.. && node tools/run-ttsx.mjs packages/game-services/src/client.test.ts && node tools/run-ttsx.mjs packages/game-services/src/client-progress.test.ts && node tools/run-ttsx.mjs packages/game-services/src/runtime.test.ts && node tools/run-ttsx.mjs packages/game-services/src/types.test.ts && node tools/run-ttsx.mjs packages/game-services/src/server.test.ts && node tools/run-ttsx.mjs packages/game-services/src/google-play-purchase.test.ts && node tools/run-ttsx.mjs packages/game-services/src/google-play-publisher-client.test.ts && node tools/run-ttsx.mjs packages/game-services/src/google-play-store-server.test.ts && node tools/run-ttsx.mjs packages/game-services/src/microsoft-store-purchase.test.ts && node tools/run-ttsx.mjs packages/game-services/src/microsoft-store-identity.test.ts && node tools/run-ttsx.mjs packages/game-services/src/platform-order.test.ts && node tools/run-ttsx.mjs packages/game-services/src/progress-link.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notification-delivery.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/service.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/service-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/client.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/client-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/scheduler.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/fcm.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/store-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/notifications/ait-functional-delivery.test.ts && node tools/run-ttsx.mjs packages/game-services/src/admob-ssv.test.ts && node tools/run-ttsx.mjs packages/game-services/src/app-store-verifier.test.ts && node tools/run-ttsx.mjs packages/game-services/src/app-store-server-notifications.test.ts && node tools/run-ttsx.mjs packages/game-services/src/apps-in-toss-evidence-verification-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/apps-in-toss-partner-api.test.ts && node tools/run-ttsx.mjs packages/game-services/src/verified-leaderboard.test.ts && node tools/run-ttsx.mjs packages/game-services/src/verified-leaderboard-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/verified-leaderboard-durability-conformance.test.ts && node tools/run-ttsx.mjs packages/game-services/src/verified-leaderboard-transport.test.ts && node tools/run-ttsx.mjs packages/game-services/src/guest-session.test.ts && node tools/run-ttsx.mjs packages/game-services/src/development-session.test.ts && node tools/run-ttsx.mjs packages/game-services/src/client-reward-evidence.test.ts && node tools/run-ttsx.mjs packages/game-services/src/ad-reward-verifier-registry.test.ts && node tools/run-ttsx.mjs packages/game-services/src/oneplay-reward.test.ts && node tools/run-ttsx.mjs packages/game-services/src/oneplay-purchase.test.ts && node tools/run-ttsx.mjs packages/game-services/src/commerce-registry-routing.test.ts && node tools/run-ttsx.mjs packages/game-services/src/commerce-registry-server.test.ts && node tools/run-ttsx.mjs packages/game-services/src/commerce-ledger-revocation.test.ts && node tools/run-ttsx.mjs packages/game-services/src/purchase-sharing.test.ts && node tools/run-ttsx.mjs packages/game-services/src/apps-in-toss-anonymous-auth.test.ts && node tools/run-ttsx.mjs packages/game-services/src/account-deletion.test.ts",
|
|
254
266
|
"test:recovery": "cd ../.. && node tools/run-ttsx.mjs packages/game-services/src/monetization-recovery.test.ts && node tools/run-ttsx.mjs packages/game-services/src/app-store-recovery.test.ts && node tools/run-ttsx.mjs packages/game-services/src/commerce-reconciler.test.ts && node tools/run-ttsx.mjs packages/game-services/src/commerce-reconciler-conformance.test.ts",
|
|
255
267
|
"test": "pnpm test:unit && pnpm test:app-store-server && pnpm test:recovery && pnpm test:packed-transport",
|
|
256
268
|
"test:app-store-server": "vitest run"
|