playe-developer-sdk 1.0.7 → 1.0.9
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 +296 -134
- package/dist/index.cjs.js +5 -25
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +5 -25
- package/dist/index.esm.js.map +1 -1
- package/dist/playe-sdk.umd.js +5 -25
- package/dist/playe-sdk.umd.js.map +1 -1
- package/dist/playe-sdk.umd.min.js +1 -1
- package/dist/playe-sdk.umd.min.js.map +1 -1
- package/examples/flappy-bird.html +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
# Playe Developer SDK
|
|
1
|
+
# 🎮 Playe Developer SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://npmjs.com/package/playe-developer-sdk)
|
|
4
|
+
[](https://github.com/playe/playe/blob/main/LICENSE)
|
|
5
|
+
[](https://bundlephobia.com/package/playe-developer-sdk)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
A browser-based SDK for integrating games with the Playe platform. Provides game session management, campaign integration, leaderboards, and integrity verification.
|
|
9
|
+
|
|
10
|
+
## ✨ Features
|
|
6
11
|
|
|
7
12
|
- 🎮 **Game Session Management** - Initialize, start, update, and complete game sessions
|
|
8
|
-
- 🛡️ **Integrity Verification** - Built-in session integrity with cryptographic hashing
|
|
13
|
+
- 🛡️ **Integrity Verification** - Built-in session integrity with cryptographic hashing
|
|
9
14
|
- 🏆 **Campaign Integration** - Access campaign information, leaderboards, and player attempts
|
|
10
15
|
- 🔄 **Anti-Cheat Protection** - Advanced validation, heartbeat mechanisms, and session monitoring
|
|
11
16
|
- 📱 **Device Detection** - Automatic device information and fingerprinting
|
|
12
|
-
- 🔧 **Developer Tools** - Test game sessions and
|
|
17
|
+
- 🔧 **Developer Tools** - Test game sessions and debugging utilities
|
|
13
18
|
- 📊 **Real-time Updates** - Progress tracking and live leaderboards
|
|
14
19
|
- ⚡ **Browser Optimized** - Lightweight and fast for web games with automatic retry logic
|
|
15
20
|
|
|
16
|
-
## Installation
|
|
21
|
+
## 🚀 Installation
|
|
17
22
|
|
|
18
|
-
### NPM
|
|
23
|
+
### NPM
|
|
19
24
|
|
|
20
25
|
```bash
|
|
21
26
|
npm install playe-developer-sdk
|
|
@@ -25,17 +30,13 @@ yarn add playe-developer-sdk
|
|
|
25
30
|
pnpm add playe-developer-sdk
|
|
26
31
|
```
|
|
27
32
|
|
|
28
|
-
### CDN
|
|
33
|
+
### CDN
|
|
29
34
|
|
|
30
35
|
```html
|
|
31
|
-
<!-- For production -->
|
|
32
36
|
<script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
33
|
-
|
|
34
|
-
<!-- Alternative CDN -->
|
|
35
|
-
<script src="https://cdn.jsdelivr.net/npm/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
36
37
|
```
|
|
37
38
|
|
|
38
|
-
### Workspace
|
|
39
|
+
### Workspace
|
|
39
40
|
|
|
40
41
|
```json
|
|
41
42
|
{
|
|
@@ -45,39 +46,33 @@ pnpm add playe-developer-sdk
|
|
|
45
46
|
}
|
|
46
47
|
```
|
|
47
48
|
|
|
48
|
-
## Quick Start
|
|
49
|
+
## 📖 Quick Start
|
|
49
50
|
|
|
50
51
|
### NPM Usage
|
|
51
52
|
|
|
52
53
|
```typescript
|
|
53
54
|
import { createPlayeSDK } from "playe-developer-sdk";
|
|
54
55
|
|
|
55
|
-
// Initialize
|
|
56
|
+
// Initialize SDK
|
|
56
57
|
const sdk = createPlayeSDK({
|
|
57
58
|
apiBaseUrl: "https://api.playe.com",
|
|
58
59
|
apiKey: "your-api-key",
|
|
59
|
-
enableDebugMode: true,
|
|
60
|
+
enableDebugMode: true,
|
|
60
61
|
});
|
|
61
62
|
|
|
62
|
-
// Initialize
|
|
63
|
+
// Initialize game session (gets sessionId from URL)
|
|
63
64
|
const session = await sdk.initializeGameSession();
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
sessionId: session.sessionId,
|
|
67
|
-
campaignId: session.campaign.id,
|
|
68
|
-
playerId: session.player.id,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Start the game
|
|
66
|
+
// Start game
|
|
72
67
|
await sdk.startGameSession({
|
|
73
68
|
difficulty: "normal",
|
|
74
69
|
mode: "classic",
|
|
75
70
|
});
|
|
76
71
|
|
|
77
|
-
// Update progress
|
|
72
|
+
// Update progress
|
|
78
73
|
await sdk.updateGameProgress({
|
|
79
74
|
currentScore: 1500,
|
|
80
|
-
elapsedTime: 120,
|
|
75
|
+
elapsedTime: 120,
|
|
81
76
|
gameState: {
|
|
82
77
|
level: 3,
|
|
83
78
|
lives: 2,
|
|
@@ -92,7 +87,7 @@ await sdk.updateGameProgress({
|
|
|
92
87
|
],
|
|
93
88
|
});
|
|
94
89
|
|
|
95
|
-
// Complete
|
|
90
|
+
// Complete game
|
|
96
91
|
const result = await sdk.completeGame({
|
|
97
92
|
finalScore: 2500,
|
|
98
93
|
validationChecksum: "client-checksum",
|
|
@@ -107,12 +102,6 @@ const result = await sdk.completeGame({
|
|
|
107
102
|
finalLives: 1,
|
|
108
103
|
},
|
|
109
104
|
});
|
|
110
|
-
|
|
111
|
-
console.log("Game completed!", {
|
|
112
|
-
isWinner: result.isWinner,
|
|
113
|
-
finalRank: result.finalRank,
|
|
114
|
-
prizeAmount: result.prizeAmount,
|
|
115
|
-
});
|
|
116
105
|
```
|
|
117
106
|
|
|
118
107
|
### CDN Usage
|
|
@@ -120,24 +109,35 @@ console.log("Game completed!", {
|
|
|
120
109
|
```html
|
|
121
110
|
<script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
122
111
|
<script>
|
|
123
|
-
// SDK is available as global PlayeSDK
|
|
124
112
|
const sdk = PlayeSDK.createPlayeSDK({
|
|
125
113
|
apiBaseUrl: 'https://api.playe.com',
|
|
126
114
|
apiKey: 'your-api-key',
|
|
127
115
|
enableDebugMode: true,
|
|
128
116
|
});
|
|
129
117
|
|
|
130
|
-
|
|
131
|
-
const fingerprint = PlayeSDK.DeviceUtils.generateFingerprint();
|
|
132
|
-
|
|
133
|
-
// Same API as NPM version
|
|
134
|
-
const session = await sdk.initializeGameSession(); // Gets sessionId from URL
|
|
135
|
-
|
|
118
|
+
const session = await sdk.initializeGameSession();
|
|
136
119
|
console.log('Session initialized:', session.sessionId);
|
|
137
120
|
</script>
|
|
138
121
|
```
|
|
139
122
|
|
|
140
|
-
##
|
|
123
|
+
## 📋 Table of Contents
|
|
124
|
+
|
|
125
|
+
- [🎮 Playe Developer SDK](#-playe-developer-sdk)
|
|
126
|
+
- [✨ Features](#-features)
|
|
127
|
+
- [🚀 Installation](#-installation)
|
|
128
|
+
- [📖 Quick Start](#-quick-start)
|
|
129
|
+
- [📋 Table of Contents](#-table-of-contents)
|
|
130
|
+
- [🔧 API Reference](#-api-reference)
|
|
131
|
+
- [🔒 Security & Integrity](#-security--integrity)
|
|
132
|
+
- [🧪 Testing & Development](#-testing--development)
|
|
133
|
+
- [🚨 Error Handling](#-error-handling)
|
|
134
|
+
- [📚 Examples](#-examples)
|
|
135
|
+
- [🔄 Migration Guide](#-migration-guide)
|
|
136
|
+
- [🔧 Troubleshooting](#-troubleshooting)
|
|
137
|
+
- [🤝 Contributing](#-contributing)
|
|
138
|
+
- [📄 License](#-license)
|
|
139
|
+
|
|
140
|
+
## 🔧 API Reference
|
|
141
141
|
|
|
142
142
|
### SDK Configuration
|
|
143
143
|
|
|
@@ -159,9 +159,11 @@ interface SDKConfig {
|
|
|
159
159
|
```typescript
|
|
160
160
|
// Initialize game session (gets sessionId from URL query parameter)
|
|
161
161
|
const session = await sdk.initializeGameSession(): Promise<GameSessionResponse>;
|
|
162
|
+
// Returns: { sessionId, campaignId, gameId, status, campaign, player, createdAt, expiresAt }
|
|
162
163
|
|
|
163
|
-
// Start
|
|
164
|
+
// Start game session
|
|
164
165
|
await sdk.startGameSession(config?: Record<string, any>): Promise<GameSessionResponse>;
|
|
166
|
+
// Returns: { sessionId, status, startTime }
|
|
165
167
|
|
|
166
168
|
// Update game progress with integrity verification
|
|
167
169
|
await sdk.updateGameProgress({
|
|
@@ -171,17 +173,20 @@ await sdk.updateGameProgress({
|
|
|
171
173
|
achievements?: Achievement[];
|
|
172
174
|
clientTimestamp?: string;
|
|
173
175
|
}): Promise<ProgressUpdateResponse>;
|
|
176
|
+
// Returns: { isValid, validationMessage, currentRank, isLeading, campaignStatus, warnings }
|
|
174
177
|
|
|
175
|
-
// Complete
|
|
178
|
+
// Complete game with integrity verification
|
|
176
179
|
await sdk.completeGame({
|
|
177
180
|
finalScore: number;
|
|
178
181
|
validationChecksum: string;
|
|
179
182
|
gameMetrics?: GameMetrics;
|
|
180
183
|
finalGameState?: Record<string, any>; // Automatically hashed for integrity
|
|
181
184
|
}): Promise<GameCompletionResponse>;
|
|
185
|
+
// Returns: { isWinner, prizeAmount, prizeType, finalRank, totalParticipants, winnerDetails, reward, campaignResult }
|
|
182
186
|
|
|
183
|
-
// Abandon
|
|
187
|
+
// Abandon game
|
|
184
188
|
await sdk.abandonGame(reason?: string, lastKnownScore?: number): Promise<AbandonGameResponse>;
|
|
189
|
+
// Returns: { success, message, gamepassRefunded, abandonedAt }
|
|
185
190
|
```
|
|
186
191
|
|
|
187
192
|
#### Campaign Information
|
|
@@ -189,12 +194,19 @@ await sdk.abandonGame(reason?: string, lastKnownScore?: number): Promise<Abandon
|
|
|
189
194
|
```typescript
|
|
190
195
|
// Get campaign status
|
|
191
196
|
await sdk.getCampaignStatus(campaignId: string, playerId?: string): Promise<CampaignStatusResponse>;
|
|
197
|
+
// Returns: { campaignId, status, campaignStyle, remainingGamepasses, totalParticipants,
|
|
198
|
+
// totalPrizePool, endDate, playerStatus, topPlayers, prizeBreakdown }
|
|
192
199
|
|
|
193
200
|
// Get leaderboard
|
|
194
201
|
await sdk.getLeaderboard(campaignId: string, limit?: number, playerId?: string): Promise<LeaderboardResponse>;
|
|
202
|
+
// Returns: { campaignId, entries, playerRank, lastUpdated, isLive }
|
|
203
|
+
// entries: [{ rank, playerId, displayName, score, achievedAt, isCurrentPlayer, prizeAmount }]
|
|
195
204
|
|
|
196
205
|
// Get player attempts
|
|
197
206
|
await sdk.getPlayerAttempts(campaignId: string, playerId: string): Promise<PlayerAttemptsResponse>;
|
|
207
|
+
// Returns: { playerId, campaignId, totalAttempts, remainingAttempts, attempts, stats }
|
|
208
|
+
// attempts: [{ sessionId, score, playedAt, duration, status, wasWinner }]
|
|
209
|
+
// stats: { bestScore, averageScore, totalPlayTime, firstAttempt, lastAttempt }
|
|
198
210
|
```
|
|
199
211
|
|
|
200
212
|
#### Validation & Anti-Cheat
|
|
@@ -207,9 +219,11 @@ await sdk.validateGameSession({
|
|
|
207
219
|
timingData?: unknown;
|
|
208
220
|
behaviorMetrics?: unknown;
|
|
209
221
|
}): Promise<ValidationResponse>;
|
|
222
|
+
// Returns: { isValid, confidenceScore, validationIssues, warnings, requiresRevalidation, validatedAt }
|
|
210
223
|
|
|
211
224
|
// Send heartbeat (usually handled automatically)
|
|
212
225
|
await sdk.sendHeartbeat(currentScore?: number): Promise<HeartbeatResponse>;
|
|
226
|
+
// Returns: { acknowledged, serverTimestamp, nextHeartbeatIn, campaignStillActive, message }
|
|
213
227
|
```
|
|
214
228
|
|
|
215
229
|
#### Developer Tools
|
|
@@ -217,6 +231,7 @@ await sdk.sendHeartbeat(currentScore?: number): Promise<HeartbeatResponse>;
|
|
|
217
231
|
```typescript
|
|
218
232
|
// Create test game session for development
|
|
219
233
|
await sdk.createTestGameSession(testConfig?: Record<string, any>): Promise<TestGameResponse>;
|
|
234
|
+
// Returns: { testSessionId, testScenario, mockCampaign, testData, expiresAt }
|
|
220
235
|
```
|
|
221
236
|
|
|
222
237
|
### Utility Methods
|
|
@@ -237,6 +252,77 @@ sdk.gamePlayStop(): void; // Stop heartbeat and emit stop event
|
|
|
237
252
|
sdk.destroy(): void; // Clean up session artifacts and stop heartbeat
|
|
238
253
|
```
|
|
239
254
|
|
|
255
|
+
### Response Types
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// Game Session Response
|
|
259
|
+
interface GameSessionResponse {
|
|
260
|
+
sessionId: string;
|
|
261
|
+
campaignId: string;
|
|
262
|
+
gameId: string;
|
|
263
|
+
status: string;
|
|
264
|
+
campaign: CampaignInfo;
|
|
265
|
+
player: PlayerInfo;
|
|
266
|
+
createdAt: string;
|
|
267
|
+
expiresAt?: string;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Progress Update Response
|
|
271
|
+
interface ProgressUpdateResponse {
|
|
272
|
+
isValid: boolean;
|
|
273
|
+
validationMessage?: string;
|
|
274
|
+
currentRank: number;
|
|
275
|
+
isLeading: boolean;
|
|
276
|
+
campaignStatus?: CampaignStatusInfo;
|
|
277
|
+
warnings?: string[];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Game Completion Response
|
|
281
|
+
interface GameCompletionResponse {
|
|
282
|
+
isWinner: boolean;
|
|
283
|
+
prizeAmount?: number;
|
|
284
|
+
prizeType?: string;
|
|
285
|
+
finalRank: number;
|
|
286
|
+
totalParticipants: number;
|
|
287
|
+
winnerDetails?: WinnerInfo;
|
|
288
|
+
reward?: RewardInfo;
|
|
289
|
+
campaignResult?: CampaignResultInfo;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Campaign Status Response
|
|
293
|
+
interface CampaignStatusResponse {
|
|
294
|
+
campaignId: string;
|
|
295
|
+
status: string;
|
|
296
|
+
campaignStyle: string;
|
|
297
|
+
remainingGamepasses: number;
|
|
298
|
+
totalParticipants: number;
|
|
299
|
+
totalPrizePool: number;
|
|
300
|
+
endDate?: string;
|
|
301
|
+
playerStatus?: PlayerStatusInfo;
|
|
302
|
+
topPlayers?: TopPlayer[];
|
|
303
|
+
prizeBreakdown?: PrizeBreakdown;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Leaderboard Response
|
|
307
|
+
interface LeaderboardResponse {
|
|
308
|
+
campaignId: string;
|
|
309
|
+
entries: LeaderboardEntry[];
|
|
310
|
+
playerRank?: PlayerRankInfo;
|
|
311
|
+
lastUpdated: string;
|
|
312
|
+
isLive: boolean;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Validation Response
|
|
316
|
+
interface ValidationResponse {
|
|
317
|
+
isValid: boolean;
|
|
318
|
+
confidenceScore: number;
|
|
319
|
+
validationIssues: string[];
|
|
320
|
+
warnings: string[];
|
|
321
|
+
requiresRevalidation: boolean;
|
|
322
|
+
validatedAt: string;
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
240
326
|
### Integrity Verification Utilities
|
|
241
327
|
|
|
242
328
|
```typescript
|
|
@@ -294,35 +380,7 @@ try {
|
|
|
294
380
|
}
|
|
295
381
|
```
|
|
296
382
|
|
|
297
|
-
##
|
|
298
|
-
|
|
299
|
-
The SDK supports different campaign styles:
|
|
300
|
-
|
|
301
|
-
- **SingleWinner**: One winner takes all
|
|
302
|
-
- **FixedPool**: Fixed number of winners
|
|
303
|
-
- **Leaderboard**: Winners based on ranking
|
|
304
|
-
- **RewardForAll**: Everyone gets rewards
|
|
305
|
-
|
|
306
|
-
## Events
|
|
307
|
-
|
|
308
|
-
The SDK emits custom browser events for tracking:
|
|
309
|
-
|
|
310
|
-
```typescript
|
|
311
|
-
// Listen for SDK events
|
|
312
|
-
window.addEventListener("playe:game-loading-start", () => {
|
|
313
|
-
console.log("Game loading started");
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
window.addEventListener("playe:game-loading-finished", () => {
|
|
317
|
-
console.log("Game loading finished");
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
window.addEventListener("playe:game-play-stop", () => {
|
|
321
|
-
console.log("Game play stopped");
|
|
322
|
-
});
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
## Integrity Verification
|
|
383
|
+
## 🔒 Security & Integrity
|
|
326
384
|
|
|
327
385
|
The SDK includes built-in integrity verification to prevent cheating and ensure fair play:
|
|
328
386
|
|
|
@@ -356,43 +414,7 @@ if (!validation.isValid) {
|
|
|
356
414
|
}
|
|
357
415
|
```
|
|
358
416
|
|
|
359
|
-
##
|
|
360
|
-
|
|
361
|
-
### Flappy Bird Example
|
|
362
|
-
|
|
363
|
-
The `examples/flappy-bird.html` provides a complete game integration example with player eligibility validation and score submission.
|
|
364
|
-
|
|
365
|
-
#### Setup
|
|
366
|
-
|
|
367
|
-
1. Build the SDK:
|
|
368
|
-
```bash
|
|
369
|
-
pnpm --filter playe-developer-sdk build
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
2. Open the example:
|
|
373
|
-
```bash
|
|
374
|
-
# Using any local server
|
|
375
|
-
python -m http.server 8000
|
|
376
|
-
# or
|
|
377
|
-
npx serve
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
3. Navigate to: `http://localhost:8000/packages/playe-developer-sdk/examples/flappy-bird.html`
|
|
381
|
-
|
|
382
|
-
#### Features Demonstrated
|
|
383
|
-
|
|
384
|
-
- ✅ Player eligibility validation (attempts remaining, campaign status)
|
|
385
|
-
- ✅ Game session initialization with SDK
|
|
386
|
-
- ✅ Real-time progress tracking
|
|
387
|
-
- ✅ Score submission with completion data
|
|
388
|
-
- ✅ Graceful fallback to demo mode if SDK unavailable
|
|
389
|
-
- ✅ Responsive game canvas with mobile support
|
|
390
|
-
|
|
391
|
-
#### Demo Mode
|
|
392
|
-
|
|
393
|
-
If the SDK is not available (e.g., not built), the game runs in demo mode without server integration. This allows testing game mechanics offline.
|
|
394
|
-
|
|
395
|
-
## Development
|
|
417
|
+
## 🧪 Testing & Development
|
|
396
418
|
|
|
397
419
|
### Testing
|
|
398
420
|
|
|
@@ -422,46 +444,186 @@ const sdk = createPlayeSDK({
|
|
|
422
444
|
|
|
423
445
|
### URL Requirements
|
|
424
446
|
|
|
425
|
-
For `initializeGameSession()` to work,
|
|
447
|
+
For `initializeGameSession()` to work, page URL must include a `sessionId` query parameter:
|
|
426
448
|
|
|
427
449
|
```
|
|
428
450
|
https://yourgame.com/play?sessionId=abc123-def456-ghi789
|
|
429
451
|
```
|
|
430
452
|
|
|
431
|
-
The SDK will automatically extract this sessionId and initialize
|
|
453
|
+
The SDK will automatically extract this sessionId and initialize session.
|
|
432
454
|
|
|
433
|
-
##
|
|
455
|
+
## 📚 Examples
|
|
434
456
|
|
|
435
|
-
|
|
436
|
-
- Firefox 55+
|
|
437
|
-
- Safari 12+
|
|
438
|
-
- Edge 79+
|
|
457
|
+
### Browser Example
|
|
439
458
|
|
|
440
|
-
|
|
459
|
+
The `examples/browser-example.html` provides a complete integration example with:
|
|
441
460
|
|
|
442
|
-
|
|
461
|
+
- SDK initialization and configuration
|
|
462
|
+
- Session management (initialize, start, update, complete)
|
|
463
|
+
- Progress tracking with integrity verification
|
|
464
|
+
- Leaderboard fetching and display
|
|
465
|
+
- Error handling and recovery
|
|
466
|
+
- Debug mode logging
|
|
467
|
+
- Device fingerprinting
|
|
443
468
|
|
|
444
|
-
|
|
445
|
-
- **CDN (UMD)**: `https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js`
|
|
446
|
-
- **Workspace**: `@workspace/playe-developer-sdk` (internal development)
|
|
469
|
+
### Flappy Bird Example
|
|
447
470
|
|
|
448
|
-
|
|
471
|
+
The `examples/flappy-bird.html` provides a complete game integration example with:
|
|
449
472
|
|
|
450
|
-
-
|
|
451
|
-
-
|
|
452
|
-
-
|
|
453
|
-
-
|
|
473
|
+
- Player eligibility validation (attempts remaining, campaign status)
|
|
474
|
+
- Game session initialization with SDK
|
|
475
|
+
- Real-time progress tracking
|
|
476
|
+
- Score submission with completion data
|
|
477
|
+
- Graceful fallback to demo mode if SDK unavailable
|
|
478
|
+
- Responsive game canvas with mobile support
|
|
454
479
|
|
|
455
|
-
|
|
480
|
+
## 🔄 Migration Guide
|
|
456
481
|
|
|
457
|
-
|
|
482
|
+
### Migrating from v0.x to v1.x
|
|
458
483
|
|
|
459
|
-
|
|
484
|
+
#### Breaking Changes
|
|
460
485
|
|
|
461
|
-
|
|
486
|
+
1. **SDK Initialization**
|
|
487
|
+
```typescript
|
|
488
|
+
// v0.x
|
|
489
|
+
import { PlayeDeveloperSDK } from 'playe-developer-sdk';
|
|
490
|
+
const sdk = new PlayeDeveloperSDK(config);
|
|
462
491
|
|
|
463
|
-
|
|
492
|
+
// v1.x
|
|
493
|
+
import { createPlayeSDK } from 'playe-developer-sdk';
|
|
494
|
+
const sdk = createPlayeSDK(config);
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
2. **Method Signatures**
|
|
498
|
+
```typescript
|
|
499
|
+
// v0.x - Callback-based
|
|
500
|
+
sdk.initializeGameSession((error, session) => {
|
|
501
|
+
if (error) handleError(error);
|
|
502
|
+
else handleSuccess(session);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// v1.x - Promise-based
|
|
506
|
+
try {
|
|
507
|
+
const session = await sdk.initializeGameSession();
|
|
508
|
+
handleSuccess(session);
|
|
509
|
+
} catch (error) {
|
|
510
|
+
handleError(error);
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## 🚨 Error Handling
|
|
515
|
+
|
|
516
|
+
### Error Types
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
// Base SDK error
|
|
520
|
+
PlayeSDKError {
|
|
521
|
+
name: string;
|
|
522
|
+
message: string;
|
|
523
|
+
originalError?: Error;
|
|
524
|
+
context?: string;
|
|
525
|
+
timestamp: string;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Specific error types
|
|
529
|
+
ValidationError extends PlayeSDKError; // Validation failures
|
|
530
|
+
NetworkError extends PlayeSDKError; // Network issues
|
|
531
|
+
AuthenticationError extends PlayeSDKError; // Authentication failures
|
|
532
|
+
GameSessionError extends PlayeSDKError; // Session-specific errors
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### Error Recovery
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
// Enable debug mode for detailed error information
|
|
539
|
+
const sdk = createPlayeSDK({
|
|
540
|
+
apiBaseUrl: 'https://api.playe.com',
|
|
541
|
+
enableDebugMode: true,
|
|
542
|
+
retryAttempts: 3, // Configure retry behavior
|
|
543
|
+
timeoutMs: 30000, // Configure timeout
|
|
544
|
+
});
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
## 🔧 Troubleshooting
|
|
548
|
+
|
|
549
|
+
### Common Issues
|
|
464
550
|
|
|
465
|
-
|
|
551
|
+
#### "No sessionId found in URL" Error
|
|
552
|
+
|
|
553
|
+
**Problem:** Getting an error when calling `initializeGameSession()`.
|
|
554
|
+
|
|
555
|
+
**Solution:** Ensure your game URL includes a `sessionId` query parameter:
|
|
556
|
+
```
|
|
557
|
+
https://yourgame.com/play?sessionId=abc123-def456-ghi789
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
#### Network/Timeout Errors
|
|
561
|
+
|
|
562
|
+
**Problem:** API calls failing with network errors.
|
|
563
|
+
|
|
564
|
+
**Solutions:**
|
|
565
|
+
1. Check API endpoint configuration
|
|
566
|
+
2. Verify API key is correct
|
|
567
|
+
3. Check network connectivity
|
|
568
|
+
4. Increase timeout for slow networks
|
|
569
|
+
|
|
570
|
+
#### Integrity Validation Failures
|
|
571
|
+
|
|
572
|
+
**Problem:** Game completion failing with integrity validation errors.
|
|
573
|
+
|
|
574
|
+
**Solutions:**
|
|
575
|
+
1. Ensure game state is valid and serializable
|
|
576
|
+
2. Check timing data is reasonable
|
|
577
|
+
3. Use debug mode to inspect requests
|
|
578
|
+
|
|
579
|
+
## 🤝 Contributing
|
|
580
|
+
|
|
581
|
+
We welcome contributions to the Playe Developer SDK!
|
|
582
|
+
|
|
583
|
+
### Development Setup
|
|
584
|
+
|
|
585
|
+
```bash
|
|
586
|
+
# Clone repository
|
|
587
|
+
git clone https://github.com/playe/playe.git
|
|
588
|
+
cd playe
|
|
589
|
+
|
|
590
|
+
# Install dependencies
|
|
591
|
+
pnpm install
|
|
592
|
+
|
|
593
|
+
# Build SDK
|
|
594
|
+
pnpm --filter playe-developer-sdk build
|
|
595
|
+
|
|
596
|
+
# Run tests
|
|
597
|
+
pnpm --filter playe-developer-sdk test
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Code Guidelines
|
|
601
|
+
|
|
602
|
+
- Follow TypeScript best practices
|
|
603
|
+
- Add tests for new functionality
|
|
604
|
+
- Update documentation as needed
|
|
605
|
+
- Ensure all tests pass
|
|
606
|
+
|
|
607
|
+
## 📄 License
|
|
608
|
+
|
|
609
|
+
MIT License - see LICENSE file for details.
|
|
466
610
|
|
|
467
|
-
|
|
611
|
+
Copyright (c) 2024 Playe
|
|
612
|
+
|
|
613
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
614
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
615
|
+
in the Software without restriction, including without limitation the rights
|
|
616
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
617
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
618
|
+
furnished to do so, subject to the following conditions:
|
|
619
|
+
|
|
620
|
+
The above copyright notice and this permission notice shall be included in all
|
|
621
|
+
copies or substantial portions of the Software.
|
|
622
|
+
|
|
623
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
624
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
625
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
626
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
627
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
628
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
629
|
+
SOFTWARE.
|
package/dist/index.cjs.js
CHANGED
|
@@ -196,14 +196,6 @@ class HttpClient {
|
|
|
196
196
|
const jwtToken = this.getUrlParameter('accessToken');
|
|
197
197
|
if (jwtToken) {
|
|
198
198
|
headers['Authorization'] = `Bearer ${jwtToken}`;
|
|
199
|
-
// Debug logging for iframe contexts
|
|
200
|
-
if (this.config.enableDebugMode) {
|
|
201
|
-
console.log('[Playe SDK] Using GO session token in iframe context:', {
|
|
202
|
-
hasToken: !!jwtToken,
|
|
203
|
-
tokenLength: jwtToken?.length,
|
|
204
|
-
tokenSource: jwtToken,
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
199
|
}
|
|
208
200
|
return headers;
|
|
209
201
|
}
|
|
@@ -238,28 +230,16 @@ class HttpClient {
|
|
|
238
230
|
let lastError;
|
|
239
231
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
240
232
|
try {
|
|
241
|
-
if (this.config.enableDebugMode) {
|
|
242
|
-
console.log(`[Playe SDK] ${options.method || 'GET'} ${url}`, {
|
|
243
|
-
attempt: attempt + 1,
|
|
244
|
-
body: options.body,
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
233
|
const response = await fetch(url, requestOptions);
|
|
248
234
|
if (!response.ok) {
|
|
249
235
|
const errorText = await response.text();
|
|
250
236
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
251
237
|
}
|
|
252
238
|
const data = await response.json();
|
|
253
|
-
if (this.config.enableDebugMode) {
|
|
254
|
-
console.log(`[Playe SDK] Response:`, data);
|
|
255
|
-
}
|
|
256
239
|
return data;
|
|
257
240
|
}
|
|
258
241
|
catch (error) {
|
|
259
242
|
lastError = error;
|
|
260
|
-
if (this.config.enableDebugMode) {
|
|
261
|
-
console.warn(`[Playe SDK] Request failed (attempt ${attempt + 1}/${retries + 1}):`, error);
|
|
262
|
-
}
|
|
263
243
|
// Don't retry on client errors (4xx)
|
|
264
244
|
if (error instanceof Error && error.message.includes('HTTP 4')) {
|
|
265
245
|
break;
|
|
@@ -558,7 +538,7 @@ class PlayeDeveloperSDK {
|
|
|
558
538
|
}
|
|
559
539
|
// Prepare request body
|
|
560
540
|
const body = { ...progressData };
|
|
561
|
-
const response = await this.httpClient.put(`/
|
|
541
|
+
const response = await this.httpClient.put(`/game-session//${this.sessionId}/progress`, body);
|
|
562
542
|
if (this.config.enableDebugMode) {
|
|
563
543
|
console.log('[Playe SDK] Progress updated:', {
|
|
564
544
|
score: progressData.currentScore,
|
|
@@ -633,7 +613,7 @@ class PlayeDeveloperSDK {
|
|
|
633
613
|
async getCampaignStatus(campaignId, playerId) {
|
|
634
614
|
try {
|
|
635
615
|
const params = playerId ? `?playerId=${encodeURIComponent(playerId)}` : '';
|
|
636
|
-
return await this.httpClient.get(`/api/
|
|
616
|
+
return await this.httpClient.get(`/api/game-session/campaign/${campaignId}/status${params}`);
|
|
637
617
|
}
|
|
638
618
|
catch (error) {
|
|
639
619
|
throw this.handleError(error, 'Failed to get campaign status');
|
|
@@ -647,7 +627,7 @@ class PlayeDeveloperSDK {
|
|
|
647
627
|
if (playerId)
|
|
648
628
|
params.append('playerId', playerId);
|
|
649
629
|
const queryString = params.toString() ? `?${params.toString()}` : '';
|
|
650
|
-
return await this.httpClient.get(`/api/
|
|
630
|
+
return await this.httpClient.get(`/api/game-session/campaign/${campaignId}/leaderboard${queryString}`);
|
|
651
631
|
}
|
|
652
632
|
catch (error) {
|
|
653
633
|
throw this.handleError(error, 'Failed to get leaderboard');
|
|
@@ -655,7 +635,7 @@ class PlayeDeveloperSDK {
|
|
|
655
635
|
}
|
|
656
636
|
async getPlayerAttempts(campaignId, playerId) {
|
|
657
637
|
try {
|
|
658
|
-
return await this.httpClient.get(`/api/
|
|
638
|
+
return await this.httpClient.get(`/api/game-session/campaign/${campaignId}/players/${playerId}/attempts`);
|
|
659
639
|
}
|
|
660
640
|
catch (error) {
|
|
661
641
|
throw this.handleError(error, 'Failed to get player attempts');
|
|
@@ -673,7 +653,7 @@ class PlayeDeveloperSDK {
|
|
|
673
653
|
timingData: request.timingData,
|
|
674
654
|
behaviorMetrics: request.behaviorMetrics
|
|
675
655
|
};
|
|
676
|
-
return await this.httpClient.post(`/
|
|
656
|
+
return await this.httpClient.post(`/game-session/${this.sessionId}/validate`, body);
|
|
677
657
|
}
|
|
678
658
|
catch (error) {
|
|
679
659
|
throw this.handleError(error, 'Failed to validate game session');
|